四元数乘法(Quaternion Multiplication)是3D图形学中用于组合旋转的核心运算。在草地渲染系统中,这个函数用于组合多个旋转变换,生成每片草叶独特的生长方向。
四元数是四维超复数,可以表示为:
q=w+xi+yj+zk
其中:
- w 是实部(标量部分)
- (x,y,z) 是虚部(向量部分)
- i,j,k 是虚数单位
虚数单位满足以下基本关系:
i2=j2=k2=ijk=−1
四元数乘法基于虚数单位的乘法规则(右手定则):
i⋅jj⋅i=k,j⋅k=i,k⋅i=j=−k,k⋅j=−i,i⋅k=−j
记忆技巧:顺时针相乘为正,逆时针相乘为负。
对于两个四元数 q1=(x1,y1,z1,w1) 和 q2=(x2,y2,z2,w2),它们的乘积 q1×q2 计算如下:
xyzw=w1x2+x1w2+y1z2−z1y2=w1y2−x1z2+y1w2+z1x2=w1z2+x1y2−y1x2+z1w2=w1w2−x1x2−y1y2−z1z2
让我们一步一步推导这个公式,理解为什么是这样的。
回忆四元数的定义:
q1q2=w1+x1i+y1j+z1k=w2+x2i+y2j+z2k
把 q1×q2 展开,就像 (a+b)(c+d)=ac+ad+bc+bd 一样:
q1×q2=(w1+x1i+y1j+z1k)(w2+x2i+y2j+z2k)
展开后得到 16 项(4×4):
q1×q2=w1w2+w1x2i+w1y2j+w1z2k+x1iw2+x1i⋅x2i+x1i⋅y2j+x1i⋅z2k+y1jw2+y1j⋅x2i+y1j⋅y2j+y1j⋅z2k+z1kw2+z1k⋅x2i+z1k⋅y2j+z1k⋅z2k
现在关键来了!使用我们前面学的乘法规则:
规则回顾:
- i2=j2=k2=−1
- i⋅j=k,j⋅k=i,k⋅i=j
- j⋅i=−k,k⋅j=−i,i⋅k=−j
让我们逐项化简:
第1行(w1 的项):
w1w2+w1x2i+w1y2j+w1z2k
这些项已经是最简形式了。
第2行(x1i 的项):
x1w2ix1x2i2x1y2(i⋅j)x1z2(i⋅k)→x1w2i(已是最简)→x1x2⋅(−1)=−x1x2(实部)→x1y2⋅k(变成 k 分量)→x1z2⋅(−j)=−x1z2j(变成负的 j)
第3行(y1j 的项):
y1w2jy1x2(j⋅i)y1y2j2y1z2(j⋅k)→y1w2j(已是最简)→y1x2⋅(−k)=−y1x2k(变成负的 k)→y1y2⋅(−1)=−y1y2(实部)→y1z2⋅i(变成 i 分量)
第4行(z1k 的项):
z1w2kz1x2(k⋅i)z1y2(k⋅j)z1z2k2→z1w2k(已是最简)→z1x2⋅j(变成 j 分量)→z1y2⋅(−i)=−z1y2i(变成负的 i)→z1z2⋅(−1)=−z1z2(实部)
现在把所有项按照 i,j,k,实部 分组:
实部(w 分量):
w=w1w2−x1x2−y1y2−z1z2
来源:直接乘积 + 三个 i2,j2,k2 项
i 分量(x 分量):
x=w1x2i+x1w2i+y1z2i−z1y2i=(w1x2+x1w2+y1z2−z1y2)i
所以:x=w1x2+x1w2+y1z2−z1y2
j 分量(y 分量):
y=w1y2j+y1w2j−x1z2j+z1x2j=(w1y2+y1w2−x1z2+z1x2)j
所以:y=w1y2−x1z2+y1w2+z1x2
k 分量(z 分量):
z=w1z2k+z1w2k+x1y2k−y1x2k=(w1z2+z1w2+x1y2−y1x2)k
所以:z=w1z2+x1y2−y1x2+z1w2
这就得到了我们的四元数乘法公式!
xyzw=w1x2+x1w2+y1z2−z1y2=w1y2−x1z2+y1w2+z1x2=w1z2+x1y2−y1x2+z1w2=w1w2−x1x2−y1y2−z1z2
-
实部(w):所有平方项都是负的(−x2,−y2,−z2)
-
虚部(x, y, z):
- 前两项:对应分量与实部的交叉项(如 x 的 w1x2+x1w2)
- 后两项:其他两个虚部的”循环”交叉(一正一负)
-
符号规律:
- 正号:顺时针循环(i→j→k→i)
- 负号:逆时针循环(i→k→j→i)
也可以用向量和标量的形式表示:
q1×q2=(w1w2−v1⋅v2w1v2+w2v1+v1×v2)
其中 v1=(x1,y1,z1) 和 v2=(x2,y2,z2) 是虚部向量。
function multiplyQuaternions(q1: Cesium.Quaternion, q2: Cesium.Quaternion): Cesium.Quaternion {
// x 分量:w₁x₂ + x₁w₂ + y₁z₂ - z₁y₂
const x = q1.x * q2.w + q1.w * q2.x + q1.y * q2.z - q1.z * q2.y
// ↑ x₁w₂ ↑ w₁x₂ ↑ y₁z₂ ↑ -z₁y₂
// y 分量:w₁y₂ - x₁z₂ + y₁w₂ + z₁x₂
const y = -q1.x * q2.z + q1.w * q2.y + q1.y * q2.w + q1.z * q2.x
// ↑ -x₁z₂ ↑ w₁y₂ ↑ y₁w₂ ↑ z₁x₂
// z 分量:w₁z₂ + x₁y₂ - y₁x₂ + z₁w₂
const z = q1.x * q2.y - q1.y * q2.x + q1.w * q2.z + q1.z * q2.w
// ↑ x₁y₂ ↑ -y₁x₂ ↑ w₁z₂ ↑ z₁w₂
// w 分量:w₁w₂ - x₁x₂ - y₁y₂ - z₁z₂
const w = -q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + q1.w * q2.w
// ↑ -x₁x₂ ↑ -y₁y₂ ↑ -z₁z₂ ↑ w₁w₂
return new Cesium.Quaternion(x, y, z, w)
四元数乘法的主要几何意义是旋转的组合:
qresult=q1×q2
表示:先应用旋转 q2,再应用旋转 q1
⚠️ 注意:旋转顺序从右到左!
四元数乘法是非交换的:
q1×q2=q2×q1
这意味着旋转的顺序非常重要。例如:
- 先绕X轴转90°,再绕Y轴转90°
- 先绕Y轴转90°,再绕X轴转90°
这两种操作的结果完全不同!
用于表示旋转的四元数必须是单位四元数,满足:
x2+y2+z2+w2=1
单位四元数与旋转的关系:
q=(sin(θ/2)⋅axiscos(θ/2))
其中:
- θ 是旋转角度
- axis=(x,y,z) 是归一化的旋转轴
在 generateInstancesWithTerrain() 方法中,使用四元数乘法创建草叶的复杂朝向:
// 1️⃣ 绕Y轴旋转(基础方向)- 随机水平朝向
let angle = Math.PI - Math.random() * (2 * Math.PI) // 0 到 2π
let rotationAxis = new Cesium.Cartesian3(0, 1, 0) // Y轴
let x = rotationAxis.x * Math.sin(angle / 2.0)
let y = rotationAxis.y * Math.sin(angle / 2.0)
let z = rotationAxis.z * Math.sin(angle / 2.0)
let w = Math.cos(angle / 2.0)
quaternion0 = new Cesium.Quaternion(x, y, z, w)
angle = Math.random() * (0.25 - (-0.25)) + (-0.25) // -0.25 到 0.25 弧度
rotationAxis = new Cesium.Cartesian3(1, 0, 0) // X轴
x = rotationAxis.x * Math.sin(angle / 2.0)
y = rotationAxis.y * Math.sin(angle / 2.0)
z = rotationAxis.z * Math.sin(angle / 2.0)
w = Math.cos(angle / 2.0)
quaternion1 = new Cesium.Quaternion(x, y, z, w)
quaternion0 = multiplyQuaternions(quaternion0, quaternion1)
const microVariation = (Math.random() - 0.5) * 0.1 // -0.05 到 0.05
rotationAxis = new Cesium.Cartesian3(0, 0, 1) // Z轴
x = rotationAxis.x * Math.sin(angle / 2.0)
y = rotationAxis.y * Math.sin(angle / 2.0)
z = rotationAxis.z * Math.sin(angle / 2.0)
w = Math.cos(angle / 2.0)
quaternion1 = new Cesium.Quaternion(x, y, z, w)
const orientation = multiplyQuaternions(quaternion0, quaternion1)
通过这种三次旋转的组合,每片草叶获得:
- 随机水平朝向(Y轴旋转):草叶向各个方向生长
- 自然倾斜(X轴旋转):轻微的前后倾斜,模拟重力和生长不均匀
- 细微扭转(Z轴旋转):微小的旋转变化,避免过于规则
最终结果是每片草都有独特的、自然的三维朝向,极大增强了草地的真实感和自然度。
(q1×q2)×q3=q1×(q2×q3)
q1×q2=q2×q1
q×qidentity=qidentity×q=q
其中 qidentity=(0,0,0,1)
如果 ∥q1∥=∥q2∥=1,则 ∥q1×q2∥=1