图形学数学

欧拉角 (Euler Angles)

欧拉角是描述 3D 空间物体取向的最直观方法,它将旋转分解为绕三个正交坐标轴(X, Y, Z)的三个连续旋转。

1. 定义

欧拉角用三个标量 $(\alpha, \beta, \gamma)$ 来表示旋转,分别对应绕三个轴的角度。 例如,常见的 Pitch-Yaw-Roll 系统:

  • Pitch (俯仰): 绕 X 轴旋转。
  • Yaw (偏航): 绕 Y 轴旋转。
  • Roll (翻滚): 绕 Z 轴旋转。

2. 旋转顺序 (Rotation Order)

欧拉角的关键特性是旋转顺序很重要。绕轴旋转的顺序不同,最终的姿态也不同。 常见的顺序有:

  • Tait-Bryan 角: $XYZ, XZY, YXZ, YZX, ZXY, ZYX$ (常用于航空航天和图形学,如 Unity 使用 $ZXY$)。
  • 经典欧拉角: $XYX, XZX, YXY, YZY, ZXZ, ZYZ$ (第一个和第三个轴相同)。

矩阵表示通常是三个轴旋转矩阵的乘积,例如 $R = R_z(\gamma) R_y(\beta) R_x(\alpha)$。

3. 万向节锁 (Gimbal Lock)

万向节锁是欧拉角最著名的缺陷。

3.1 什么是万向节锁?

当三个旋转轴中的中间轴旋转 90 度(或 -90 度)时,第一个旋转轴和第三个旋转轴会重合(或共线)。此时,系统失去了一个自由度,导致无法在特定的三维空间方向上进行旋转。

3.2 几何解释

假设旋转顺序是 $Z \to Y \to X$(Unity 的父子层级模拟):

  1. 首先绕 Z 轴 旋转(最外层万向节)。
  2. 然后绕 Y 轴 旋转(中间层万向节)。
  3. 最后绕 X 轴 旋转(最内层万向节)。

如果 Y 轴旋转了 90 度,原本的 X 轴会被旋转到与原本的 Z 轴相同的方向。此时,绕新的 X 轴旋转产生的效果,与绕原本 Z 轴旋转的效果是一样的(或者是相反的)。我们失去了“改变 Z 轴指向”的能力,因为 X 和 Z 轴的旋转平面重合了。

3.3 示例

想象一个望远镜:

  • 底座可以水平旋转 (Yaw/Y)。
  • 支架可以垂直旋转 (Pitch/X)。
  • 望远镜桶身可以自转 (Roll/Z)。

如果把望远镜垂直向上指(Pitch = 90度),此时:

  • 转动底座 (Yaw) 会让望远镜绕着垂直轴转。
  • 转动桶身 (Roll) 也会让望远镜绕着垂直轴转。 这两个操作重叠了,你无法再让望远镜“左右摆动”(原本 Yaw 的功能),只能转圈。

3.4 解决方法

  1. 限制旋转范围:例如在 FPS 游戏中限制 Pitch 不能超过 89 度。
  2. 使用四元数 (Quaternion):四元数不依赖于轴的顺序,不存在万向节锁问题。
  3. 重置父子关系:在特定的动画关键帧动态调整层级(复杂且不通用)。

4. 优缺点

  • 优点
    • 直观易懂:容易分解为“抬头”、“转身”、“倾斜”。
    • 数据量小:只需 3 个浮点数。
    • 易于编辑:动画师通常使用曲线编辑器调节欧拉角。
  • 缺点
    • 万向节锁 (Gimbal Lock)
    • 插值困难:简单的线性插值会导致奇怪的旋转路径。
    • 旋转顺序依赖:不同的软件或引擎可能使用不同的顺序,导致转换麻烦。
    • 坐标系依赖:也是一种坐标系相关的表示。

四元数 (Quaternion)

四元数是一种用于在 3D 空间中表示旋转的数学工具。相比欧拉角(Euler Angles)和旋转矩阵(Rotation Matrix),它具有无万向节锁(Gimbal Lock)、插值平滑(SLERP)和存储紧凑等优点。

1. 定义

四元数 $q$ 由一个实部 $w$ 和三个虚部 $(x, y, z)$ 组成,通常表示为:

$$ q = w + xi + yj + zk $$

或者向量形式:

$$ q = [w, \mathbf{v}] = [w, (x, y, z)] $$

其中虚数单位满足:

$$ i^2 = j^2 = k^2 = ijk = -1 $$

2. 旋转表示

单位四元数(模长为 1)可以表示 3D 旋转。 如果我们要绕着单位轴 $\mathbf{n} = (n_x, n_y, n_z)$ 旋转角度 $\theta$,则对应的四元数为:

$$ q = [\cos(\frac{\theta}{2}), \sin(\frac{\theta}{2})\mathbf{n}] $$
  • $w = \cos(\frac{\theta}{2})$
  • $x = n_x \sin(\frac{\theta}{2})$
  • $y = n_y \sin(\frac{\theta}{2})$
  • $z = n_z \sin(\frac{\theta}{2})$

3. 基本运算

3.1 模 (Magnitude)

$$ ||q|| = \sqrt{w^2 + x^2 + y^2 + z^2} $$

表示旋转的四元数必须是单位四元数 ($||q|| = 1$)。

3.2 共轭 (Conjugate)

$$ q^* = [w, -\mathbf{v}] = w - xi - yj - zk $$

对于单位四元数,共轭等于逆 ($q^{-1} = q^*$)。它表示相反方向的旋转。

3.3 乘法 (Multiplication)

四元数乘法表示旋转的组合。$q_2 \cdot q_1$ 表示先进行 $q_1$ 旋转,再进行 $q_2$ 旋转(注意顺序,通常是从右向左)。

$$ q_a \cdot q_b = [w_a w_b - \mathbf{v}_a \cdot \mathbf{v}_b, w_a \mathbf{v}_b + w_b \mathbf{v}_a + \mathbf{v}_a \times \mathbf{v}_b] $$

3.4 旋转向量 (Rotating a Vector)

要用四元数 $q$ 旋转 3D 向量 $\mathbf{p}$,首先将向量转换为纯四元数 $P = [0, \mathbf{p}]$,然后计算:

$$ P' = q \cdot P \cdot q^* $$

$P'$ 的虚部即为旋转后的向量。

4. 插值 (Interpolation)

4.1 LERP (Linear Interpolation)

线性插值,计算简单,但会导致角速度不均匀(中间快两头慢),且模长会变短(需要归一化)。

$$ q_t = \text{normalize}((1-t)q_1 + tq_2) $$

4.2 SLERP (Spherical Linear Interpolation)

球面线性插值(Spherical Linear Interpolation)是四元数最核心的特性之一。它保证了插值结果始终位于四维超球面上,并且从起点到终点的旋转是匀速的(角速度恒定),路径是最短的(大圆弧)。

1. 为什么不用 LERP?

普通线性插值(LERP)公式为:$q_t = (1-t)q_1 + tq_2$。 虽然计算简单,但它有两个问题:

  1. 模长改变:插值结果不在球面上(走了弦),必须每一步都归一化 ($normalize$)。
  2. 角速度不匀:当 $t$ 匀速变化时,归一化后的 $q_t$ 在球面上的移动速度是中间快、两头慢的。这会导致动画看起来忽快忽慢。

2. SLERP 数学推导 (几何直观)

为了实现匀角速度,我们需要在两个向量 $q_1$ 和 $q_2$ 张成的平面上,寻找一个向量 $q_t$,使得:

  • $q_t$ 与 $q_1$ 的夹角为 $t\Omega$。
  • $q_t$ 与 $q_2$ 的夹角为 $(1-t)\Omega$。
  • 其中 $\Omega$ 是 $q_1$ 和 $q_2$ 之间的总夹角。

我们可以利用向量的线性组合和几何三角学(正弦定理)来推导。 假设 $q_t$ 可以表示为 $q_1$ 和 $q_2$ 的线性组合:

$$ q_t = a \cdot q_1 + b \cdot q_2 $$

我们可以构建一个三角形来求解系数 $a$ 和 $b$。想象一个平行四边形,对角线是 $q_t$,两边分别是方向为 $q_1$ 和 $q_2$ 的向量。 利用平面几何中的正弦定理,权重系数与夹角的正弦成反比:

$$ q_t = \frac{\sin((1-t)\Omega)}{\sin(\Omega)}q_1 + \frac{\sin(t\Omega)}{\sin(\Omega)}q_2 $$

公式解读

  • 分母 $\sin(\Omega)$:归一化因子。
  • 分子 $\sin((1-t)\Omega)$:当 $t=0$ 时,该项为 $\sin(\Omega)$,系数为 1,即 $q_t = q_1$。
  • 分子 $\sin(t\Omega)$:当 $t=1$ 时,该项为 $\sin(\Omega)$,系数为 1,即 $q_t = q_2$。
  • 中间状态:利用正弦曲线的特性,完美抵消了投影带来的非线性,实现了角度的线性变化。

3. 关键计算步骤

  1. 计算夹角余弦: $$ \cos(\Omega) = q_1 \cdot q_2 = w_1w_2 + x_1x_2 + y_1y_2 + z_1z_2 $$
  2. 最短路径修正: 如果 $\cos(\Omega) < 0$(即夹角 $> 90^\circ$),说明这两个四元数在球面上“绕远路”了(或者说是方向相反但代表同一旋转)。 此时将 $q_2$ 取反 ($q_2 = -q_2$),并更新 $\cos(\Omega) = -\cos(\Omega)$。这样保证插值走的是小于 180 度的最短弧。
  3. 退化处理: 如果 $\cos(\Omega) > 0.9995$(非常接近 1,夹角 $\approx 0$),$\sin(\Omega)$ 会趋近于 0,导致除零错误。 此时直接使用 LERP 即可(在小角度下,LERP 和 SLERP 差别极小且更稳定)。
  4. 计算系数并组合: 计算 $\Omega = \arccos(\cos(\Omega))$,代入公式求解。

5. 与其他形式的转换

5.1 四元数转矩阵 (Quaternion to Matrix)

$$ R = \begin{bmatrix} 1 - 2(y^2 + z^2) & 2(xy - wz) & 2(xz + wy) \\ 2(xy + wz) & 1 - 2(x^2 + z^2) & 2(yz - wx) \\ 2(xz - wy) & 2(yz + wx) & 1 - 2(x^2 + y^2) \end{bmatrix} $$

5.2 欧拉角转四元数 (Euler to Quaternion)

通常按顺序(如 Z-Y-X)组合轴角旋转:

$$ q = q_z(\gamma) \cdot q_y(\beta) \cdot q_x(\alpha) $$

6. 优缺点

  • 优点
    • 无万向节锁 (No Gimbal Lock)
    • 插值平滑:SLERP 提供了完美的旋转插值。
    • 存储紧凑:只需 4 个浮点数(矩阵需要 9 个)。
    • 计算效率:组合旋转比矩阵乘法快(16 次乘加 vs 27 次),归一化方便。
  • 缺点
    • 不直观:很难直接从数字看出旋转含义。
    • 单个向量旋转慢:旋转一个向量比矩阵慢(需要两次乘法)。