土法炼钢兴趣小组的算法知识备份

游戏中的数学 (3) - 四元数

目录

引言

在 Unity 的 Inspector 中,你看到的是 \((x, y, z)\) 的欧拉角。但在代码底层,旋转通常是存储为四元数 (Quaternion) \((x, y, z, w)\)。 为什么?为什么不直接用三个角度?

1. 欧拉角 (Euler Angles) 的问题

欧拉角非常直观:绕 X 轴转多少度,绕 Y 轴转多少度,绕 Z 轴转多少度。 但它有一个致命缺陷:万向节死锁 (Gimbal Lock)

当中间的旋转轴(通常是 Y 或 X,取决于旋转顺序)旋转 90 度时,第三个旋转轴会与第一个旋转轴重合。此时,你失去了一个自由度。无论你怎么转第三个轴,效果都和转第一个轴一样。

此外,欧拉角很难进行平滑插值。直接对角度进行 Lerp 会导致奇怪的旋转路径(比如从 350度 转到 10度,会绕一大圈经过 180度,而不是直接跨过 0度)。

2. 什么是四元数?

四元数由 4 个数组成:\((x, y, z, w)\)。 它本质上是轴-角 (Axis-Angle) 表示法的数学扩展。

如果你想绕轴 \(\vec{n} = (n_x, n_y, n_z)\) 旋转 \(\theta\) 度,对应的四元数为: \[ \begin{align*} x &= n_x \cdot \sin(\theta/2) \\ y &= n_y \cdot \sin(\theta/2) \\ z &= n_z \cdot \sin(\theta/2) \\ w &= \cos(\theta/2) \end{align*} \]

3. 四元数的运算

乘法 = 组合旋转

就像矩阵一样,两个四元数相乘表示旋转的叠加。 \[ Q_{final} = Q_{second} \times Q_{first} \] 注意:顺序依然很重要!

逆 (Inverse)

\(Q^{-1}\) 表示相反的旋转。 如果你想“撤销”一个旋转,就乘以它的逆。

常用函数

4. 球面线性插值 (Slerp)

这是四元数最强大的功能之一。 Lerp (线性插值) 是沿着直线走的。对于旋转来说,这意味着它会切过球体内部,导致旋转速度不均匀,甚至变形(如果用于矩阵)。 Slerp (Spherical Linear Interpolation) 是沿着球体的表面(大圆弧)走的。

Slerp Visual

它保证了旋转是最短路径匀速的。

// 平滑旋转向目标
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * speed);

总结

在写代码时,尽量使用 Quaternion 的 API(如 LookRotation, Slerp, AngleAxis),避免手动操作 \((x,y,z,w)\) 分量。


< 上一篇: 矩阵与变换 | 回到目录 | 下一篇: 距离与检测 >


By .