中EN
概念页

四元数

Quaternion

更新于 2026-10-16 约 18 分钟旋转四元数插值动画

单位四元数可以紧凑地表示任意三维旋转,与轴-角表示互相转换很简单,并能做稳定、匀速的朝向插值(slerp),这些都是欧拉角做不好的。它可以高效地转换为矩阵以便与其他变换合并。

定义与运算

q^=(qv,qw)=iqx+jqy+kqz+qw\hat{\mathbf{q}}=(\mathbf{q}_v,q_w)=iq_x+jq_y+kq_z+q_w,i2=j2=k2=−1i^2=j^2=k^2=-1,jk=−kj=ijk=-kj=i,ki=−ik=jki=-ik=j,ij=−ji=kij=-ji=k。

运算公式
乘法(不可交换)q^r^=(qv×rv+rwqv+qwrv,  qwrw−qv⋅rv)\hat{\mathbf{q}}\hat{\mathbf{r}}=(\mathbf{q}_v\times\mathbf{r}_v+r_w\mathbf{q}_v+q_w\mathbf{r}_v,\; q_wr_w-\mathbf{q}_v\cdot\mathbf{r}_v)
共轭q^∗=(−qv,qw)\hat{\mathbf{q}}^*=(-\mathbf{q}_v,q_w)
范数n(q^)=qx2+qy2+qz2+qw2n(\hat{\mathbf{q}})=\sqrt{q_x^2+q_y^2+q_z^2+q_w^2}
单位元i^=(0,1)\hat{\mathbf{i}}=(\mathbf{0},1)
逆q^−1=q^∗/n(q^)2\hat{\mathbf{q}}^{-1}=\hat{\mathbf{q}}^*/n(\hat{\mathbf{q}})^2

其他规则:(q^r^)∗=r^∗q^∗(\hat{\mathbf{q}}\hat{\mathbf{r}})^*=\hat{\mathbf{r}}^*\hat{\mathbf{q}}^*,n(q^r^)=n(q^)n(r^)n(\hat{\mathbf{q}}\hat{\mathbf{r}})=n(\hat{\mathbf{q}})n(\hat{\mathbf{r}}),乘法满足结合律与线性。

单位四元数可写为 q^=(sin⁡ϕ uq,cos⁡ϕ)=eϕuq\hat{\mathbf{q}}=(\sin\phi\,\mathbf{u}_q,\cos\phi)=e^{\phi\mathbf{u}_q},于是 log⁡(q^)=ϕuq\log(\hat{\mathbf{q}})=\phi\mathbf{u}_q,q^t=sin⁡(ϕt)uq+cos⁡(ϕt)\hat{\mathbf{q}}^t=\sin(\phi t)\mathbf{u}_q+\cos(\phi t)。

表示旋转

  • 把点或向量放进四元数 p^\hat{\mathbf{p}},q^p^q^−1\hat{\mathbf{q}}\hat{\mathbf{p}}\hat{\mathbf{q}}^{-1} 绕轴 uq\mathbf{u}_q 旋转 2ϕ2\phi;单位四元数的逆就是共轭。
  • 任意非零实数倍表示同一旋转,所以 q^\hat{\mathbf{q}} 与 −q^-\hat{\mathbf{q}} 等价;从矩阵提取四元数可能得到其中任一个。
  • 先 q^\hat{\mathbf{q}} 再 r^\hat{\mathbf{r}}:c^=r^q^\hat{\mathbf{c}}=\hat{\mathbf{r}}\hat{\mathbf{q}}。

单位四元数通过夹心积把向量绕轴旋转,步骤如下(角度为 2ϕ2\phi)。

flowchart LR
  V["向量 v"] --> P["写入纯四元数 p = 0,v"]
  P --> Mul["计算 q p q⁻¹"]
  Q["单位四元数 q"] --> Mul
  Mul --> Out["取出虚部得 v'"]

与矩阵互转

  • 单位四元数到矩阵(Eq. 4.46)只需乘加,无三角函数,例如左上元素为 1−2(qy2+qz2)1-2(q_y^2+q_z^2)。
  • 矩阵到四元数:qw=12tr⁡(Mq)q_w=\frac12\sqrt{\operatorname{tr}(\mathbf{M}^q)},qx=m21−m124qwq_x=\frac{m_{21}-m_{12}}{4q_w} 等。为数值稳定、避免除以小数,先比较 m00,m11,m22m_{00},m_{11},m_{22} 与迹,确定 qx,qy,qz,qwq_x,q_y,q_z,q_w 中最大者,先算它再算其余分量。也有无分支但用四次开方的变体。

何时把四元数转成矩阵:需要批量变换大量向量或与仿射矩阵连乘时;插值与串接旋转则留在四元数空间更划算。

flowchart TD
  Need["当前任务"] --> Q1{"要插值或串接旋转?"}
  Q1 -->|"是"| Keep["留在四元数"]
  Q1 -->|"否"| Q2{"要批量乘大量向量 / 与 T·S 合并?"}
  Q2 -->|"是"| Mat["转为矩阵再乘"]
  Q2 -->|"否"| Keep

球面线性插值 (slerp)

slerp(q^,r^,t)=sin⁡(ϕ(1−t))sin⁡ϕq^+sin⁡(ϕt)sin⁡ϕr^,cos⁡ϕ=qxrx+qyry+qzrz+qwrw\text{slerp}(\hat{\mathbf{q}},\hat{\mathbf{r}},t)=\frac{\sin(\phi(1-t))}{\sin\phi}\hat{\mathbf{q}}+\frac{\sin(\phi t)}{\sin\phi}\hat{\mathbf{r}},\quad \cos\phi=q_xr_x+q_yr_y+q_zr_z+q_wr_w

  • 代数形式为 (r^q^−1)tq^(\hat{\mathbf{r}}\hat{\mathbf{q}}^{-1})^t\hat{\mathbf{q}}。
  • 结果是四维单位球面上的最短大圆弧(测地线),对应绕固定轴匀速旋转。 下图对比 slerp 沿单位球大圆最短弧前进,与先线性插值再归一化(nlerp/lerp)走弦的差别:前者角速度恒定,后者在两端更快、中间更慢。
flowchart TD
  Start["起点朝向 q"] --> Choice{"插值方式"}
  Choice -->|"slerp"| Arc["沿大圆最短弧匀速"]
  Choice -->|"lerp 再归一化"| Chord["沿弦采样再投回球面"]
  Arc --> End1["终点朝向 r:角速度恒定"]
  Chord --> End2["终点朝向 r:两端快、中间慢"]
  • 适合动画物体;不太适合相机朝向插值,因为相机的"上"向量可能在插值中倾斜。
  • 直接计算 slerp 要调用三角函数,较贵。书中提到:在像素着色器里只做归一化代替 slerp,90° 时误差最大 4°,对光栅化三角形可以接受;也有不损精度的增量算法和只用加乘的快速算法。

多个关键帧:squad

逐段 slerp 在经过关键帧时会突然变向。用样条更好:在 q^i\hat{\mathbf{q}}_i 与 q^i+1\hat{\mathbf{q}}_{i+1} 之间引入 a^i=q^iexp⁡[−log⁡(q^i−1q^i−1)+log⁡(q^i−1q^i+1)4]\hat{\mathbf{a}}_i=\hat{\mathbf{q}}_i\exp\left[-\frac{\log(\hat{\mathbf{q}}_i^{-1}\hat{\mathbf{q}}_{i-1})+\log(\hat{\mathbf{q}}_i^{-1}\hat{\mathbf{q}}_{i+1})}{4}\right] squad(q^i,q^i+1,a^i,a^i+1,t)=slerp(slerp(q^i,q^i+1,t),slerp(a^i,a^i+1,t),2t(1−t))\text{squad}(\hat{\mathbf{q}}_i,\hat{\mathbf{q}}_{i+1},\hat{\mathbf{a}}_i,\hat{\mathbf{a}}_{i+1},t)=\text{slerp}(\text{slerp}(\hat{\mathbf{q}}_i,\hat{\mathbf{q}}_{i+1},t),\text{slerp}(\hat{\mathbf{a}}_i,\hat{\mathbf{a}}_{i+1},t),2t(1-t)) 插值经过各 q^i\hat{\mathbf{q}}_i,但不经过 a^i\hat{\mathbf{a}}_i(它们表示切向朝向)。

从一个方向转到另一个方向

单位向量 s\mathbf{s} 转到 t\mathbf{t},e=s⋅t=cos⁡2ϕe=\mathbf{s}\cdot\mathbf{t}=\cos 2\phi: q^=(12(1+e)(s×t), 2(1+e)2)\hat{\mathbf{q}}=\left(\frac{1}{\sqrt{2(1+e)}}(\mathbf{s}\times\mathbf{t}),\ \frac{\sqrt{2(1+e)}}{2}\right)

  • 这样直接构造(而不是先归一化 s×t\mathbf{s}\times\mathbf{t})在两者几乎同向时数值稳定。
  • 两者反向时会除以零,此时取任意垂直于 s\mathbf{s} 的轴旋转。
  • 也可直接写出对应矩阵(Eq. 4.57,h=1/(1+e)h=1/(1+e)),不含开方和三角函数;接近平行时,ϕ≈0\phi\approx0 返回单位矩阵,2ϕ≈π2\phi\approx\pi 绕任意垂直轴转 π\pi。

对比

方面四元数欧拉角
与轴-角互转简单困难
插值slerp 稳定匀速不能逐角度插值
万向节锁无有

GEA 的视角:游戏引擎中的四元数(卷 I 5.4)

GEA 第 5 章从游戏引擎实践出发讲四元数,结论与上文 RTR4 一致,但在记法、乘法顺序的表述、矩阵转换代码和 lerp/slerp 取舍上有补充。GEA 使用行向量约定。

为什么不用矩阵表示旋转(卷 I 5.4)

  1. 9 个浮点数表示只有 3 个自由度的旋转,太浪费;
  2. 旋转向量要做向量-矩阵乘法:三个点积,共 9 次乘法和 6 次加法;
  3. 很难在两个矩阵表示的朝向之间求中间旋转(如相机在几秒内从朝向 A 平滑转到 B)。

原书问题:GEA 说四元数「克服了这三个问题」,但第 2 条(旋转单个向量的开销)并不成立:用四元数直接旋转一个向量,即使用优化公式 v′=v+2r×(r×v+wv)\mathbf{v}'=\mathbf{v}+2\mathbf{r}\times(\mathbf{r}\times\mathbf{v}+w\mathbf{v}),也要约 15 次乘法 + 15 次加法,而 3×3 矩阵只要 9 次乘法 + 6 次加法;要批量旋转大量向量,通常先把四元数转成矩阵。四元数真正便宜的是串接旋转(16 乘 12 加,矩阵为 27 乘 18 加)、存储和插值。来源:Wikipedia「Quaternions and spatial rotation」§Performance comparisons(引 D. Eberly, Rotation Representations and Performance Issues)。 四元数由 Hamilton 于 1843 年作为复数的推广提出,可视为一个实轴加三个虚轴 i,j,ki,j,k 的「四维复数」,复数形式 q=iqx+jqy+kqz+qw\mathbf{q}=iq_x+jq_y+kq_z+q_w;技术上它服从实数上的四维赋范可除代数。游戏中只需知道:单位长度四元数表示三维旋转。

单位四元数与轴角(卷 I 5.4.1)

q=[qv  qs]=[asin⁡θ2  cos⁡θ2]\mathbf{q}=[\mathbf{q}_v\ \ q_s]=[\mathbf{a}\sin\tfrac{\theta}{2}\ \ \cos\tfrac{\theta}{2}] a\mathbf{a} 为单位旋转轴,θ\theta 为转角,方向遵循右手定则。它很像轴角表示 [a θ][\mathbf{a}\ \theta],但数学上更方便。这与上文 RTR4「q^p^q^−1\hat{\mathbf{q}}\hat{\mathbf{p}}\hat{\mathbf{q}}^{-1} 旋转 2ϕ2\phi」是同一件事:RTR4 的 ϕ\phi 即 GEA 的半角 θ/2\theta/2。

运算(卷 I 5.4.2)

  • 两个单位四元数之和不是单位四元数,不表示旋转;引擎里看不到未经缩放的四元数和。
  • Grassman 积(原书拼写;人名应为 Grassmann):pq=[(psqv+qspv+pv×qv)  (psqs−pv⋅qv)]\mathbf{pq}=[(p_s\mathbf{q}_v+q_s\mathbf{p}_v+\mathbf{p}_v\times\mathbf{q}_v)\ \ (p_sq_s-\mathbf{p}_v\cdot\mathbf{q}_v)],向量部分放在 x/y/z、标量部分在 w。四元数乘法有多种,GEA 只讨论与三维旋转配合的这一种。pq\mathbf{pq} 表示先 Q 后 P 的复合旋转。
  • 共轭 q∗=[−qv qs]\mathbf{q}^*=[-\mathbf{q}_v\ q_s],逆 q−1=q∗/∣q∣2\mathbf{q}^{-1}=\mathbf{q}^*/|\mathbf{q}|^2;单位四元数时逆等于共轭,免去除法——求四元数的逆通常比求 3×3 矩阵的逆快得多,可用于优化。[0 0 0 1][0\ 0\ 0\ 1] 表示零旋转。
  • (pq)∗=q∗p∗(\mathbf{pq})^*=\mathbf{q}^*\mathbf{p}^*,(pq)−1=q−1p−1(\mathbf{pq})^{-1}=\mathbf{q}^{-1}\mathbf{p}^{-1},与矩阵乘积的转置、求逆反序类似。

旋转向量与串接(卷 I 5.4.3)

  • 向量写成标量部分为 0 的四元数 [v 0][\mathbf{v}\ 0],v′=qvq−1=qvq∗\mathbf{v}'=\mathbf{q}\mathbf{v}\mathbf{q}^{-1}=\mathbf{q}\mathbf{v}\mathbf{q}^*。
  • 例:游戏约定模型空间前向 fM=[0 0 1]\mathbf{f}_M=[0\ 0\ 1],飞机朝向四元数 q\mathbf{q} 给出世界前向 fW=q[0 0 1 0]q−1\mathbf{f}_W=\mathbf{q}[0\ 0\ 1\ 0]\mathbf{q}^{-1}。
  • 串接顺序:依次施加旋转 1、2、3,矩阵(行向量)为 Rnet=R1R2R3\mathbf{R}_{net}=\mathbf{R}_1\mathbf{R}_2\mathbf{R}_3,四元数却是 qnet=q3q2q1\mathbf{q}_{net}=\mathbf{q}_3\mathbf{q}_2\mathbf{q}_1——因为四元数总在向量两侧相乘,未取逆的在左、从右往左读,取逆的在右、从左往右读。上文 RTR4 的「先 q^\hat{\mathbf{q}} 再 r^\hat{\mathbf{r}} 得 r^q^\hat{\mathbf{r}}\hat{\mathbf{q}}」与此一致;差别在于 RTR4 的矩阵是列向量,所以矩阵与四元数顺序相同,而 GEA 的行向量矩阵与四元数顺序相反。

四元数与矩阵互转(卷 I 5.4.4)

设 q=[x y z w]\mathbf{q}=[x\ y\ z\ w],行向量约定下 R=[1−2y2−2z22xy+2zw2xz−2yw2xy−2zw1−2x2−2z22yz+2xw2xz+2yw2yz−2xw1−2x2−2y2]\mathbf{R}=\begin{bmatrix}1-2y^2-2z^2&2xy+2zw&2xz-2yw\\2xy-2zw&1-2x^2-2z^2&2yz+2xw\\2xz+2yw&2yz-2xw&1-2x^2-2y^2\end{bmatrix} 它是 RTR4 列向量形式(Eq. 4.46)的转置。矩阵到四元数,GEA 给出改编自 Nick Bobic 1998 年 Gamasutra 文章的 C 代码(q[0..2] 为向量部分,q[3] 为标量),思路与 RTR4 相同:

  • 迹 >0>0:s=tr+1s=\sqrt{\text{tr}+1},qw=s/2q_w=s/2,t=0.5/st=0.5/s,qx=(R21−R12)tq_x=(R_{21}-R_{12})t,qy=(R02−R20)tq_y=(R_{02}-R_{20})t,qz=(R10−R01)tq_z=(R_{10}-R_{01})t;
  • 否则找出对角线最大元素的下标 ii,按 NEXT = {1, 2, 0} 得到 j,kj,k,s=Rii−(Rjj+Rkk)+1s=\sqrt{R_{ii}-(R_{jj}+R_{kk})+1},qi=s/2q_i=s/2,t=0.5/st=0.5/s(s=0s=0 时 t=st=s),qw=(Rkj−Rjk)tq_w=(R_{kj}-R_{jk})t,qj=(Rji+Rij)tq_j=(R_{ji}+R_{ij})t,qk=(Rki+Rik)tq_k=(R_{ki}+R_{ik})t。 GEA 另指出存在利用矩阵性质假设的更快转换方法。

原书问题:上面这段代码与 GEA 自己给出的行向量矩阵 R\mathbf{R} 符号不一致。代码沿用列向量矩阵的下标(qx=(R21−R12)tq_x=(R_{21}-R_{12})t 等),但对上式的行向量 R\mathbf{R} 有 R21−R12=(2yz−2xw)−(2yz+2xw)=−4xwR_{21}-R_{12}=(2yz-2xw)-(2yz+2xw)=-4xw,于是得到 qx=−xq_x=-x;同理 qy,qzq_y,q_z 以及 else 分支里的 qw=(Rkj−Rjk)tq_w=(R_{kj}-R_{jk})t 也都变号,结果是**共轭(逆旋转)**而不是 q\mathbf{q}。(本 wiki 用数值验证过:取任意单位 q\mathbf{q},按上式构造 R\mathbf{R},确认 vR=qvq∗\mathbf{v}\mathbf{R}=\mathbf{q}\mathbf{v}\mathbf{q}^*,再代入迹 >0>0 分支,得到 [−x −y −z w][-x\ -y\ -z\ w]。)要配合 GEA 的行向量 R\mathbf{R},应交换这几处差值的两项(如 qx=(R12−R21)tq_x=(R_{12}-R_{21})t),或者把矩阵转置后再传入。上文 RTR4 的公式用于列向量矩阵,本身没有问题;问题在于 GEA 把它原样用在行向量矩阵上。

记法分歧:[x y z w] 还是 [w x y z]

GEA 写作 [x y z w][x\ y\ z\ w],与齐次向量 [x y z 1][x\ y\ z\ 1] 的习惯一致;很多学术论文按复数类比写成 q=w+ix+jy+kzq=w+ix+jy+kz,即 [w x y z][w\ x\ y\ z]。读论文前先确认约定。(本页上文 RTR4 写作 (qv,qw)(\mathbf{q}_v,q_w),与 GEA 顺序相同。)

lerp 与 slerp(卷 I 5.4.5)

  • 四元数 lerp:把四元数当四维向量线性插值再重新归一化:qlerp=(1−β)qA+βqB∣(1−β)qA+βqB∣\mathbf{q}_{lerp}=\dfrac{(1-\beta)\mathbf{q}_A+\beta\mathbf{q}_B}{|(1-\beta)\mathbf{q}_A+\beta\mathbf{q}_B|}。最简单、最便宜。
  • lerp 沿四维超球面的弦插值,β\beta 匀速变化时角速度不恒定:两端慢、中间快。slerp 沿大圆弧插值,角速度恒定:slerp(p,q,β)=sin⁡(1−β)θsin⁡θp+sin⁡βθsin⁡θq\text{slerp}(\mathbf{p},\mathbf{q},\beta)=\frac{\sin(1-\beta)\theta}{\sin\theta}\mathbf{p}+\frac{\sin\beta\theta}{\sin\theta}\mathbf{q},cos⁡θ=p⋅q\cos\theta=\mathbf{p}\cdot\mathbf{q}(四维点积)。
  • 补充(GEA 未提及的实现注意事项):因为 q\mathbf{q} 与 −q-\mathbf{q} 表示同一旋转(见上文 RTR4),若 p⋅q<0\mathbf{p}\cdot\mathbf{q}<0,应先把其中一个取负再做 lerp/slerp,否则会走「远路」,转过大于 180° 的角度;当 θ→0\theta\to0 时 sin⁡θ→0\sin\theta\to0,slerp 的权重会变成除以零,实践中此时退回归一化 lerp。
  • 用不用 slerp 仍无定论:Jonathan Blow 撰文认为 slerp 太贵而 lerp 质量不差,主张理解 slerp 但不在引擎中使用;Naughty Dog 的同事发现好的 slerp 实现几乎和 lerp 一样快——PS3 SPU 上 Ice 团队的 slerp 每关节 20 个周期,lerp 每关节 16.25 个周期。作者建议先分别做性能分析:slerp 开销可接受就用(动画可能略好看),否则 lerp 对多数用途足够。
  • 与上文 RTR4 对照:RTR4 也指出直接计算 slerp 要调三角函数、较贵,并给出在像素着色器里只做归一化代替 slerp 的做法(90° 时误差最大 4°)。两书结论相容:归一化 lerp 是廉价近似,是否值得用 slerp 取决于实测。RTR4 还提醒 slerp 不太适合相机朝向插值,GEA 未讨论这一点。

旋转表示的整体比较(欧拉角、矩阵、轴角、四元数、SRT、对偶四元数)见 旋转表示的比较。

  1. realtime_rendering_4ed.pdf 第 4 章 Transforms
  2. Game_Engine_Architecture_4Ed_-_Jason_Gregory.pdf
  3. Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 I 第 5 章 5.4 节

相关页面

游戏数学欧拉角与万向节锁Euler Angles & Gimbal Lock欧拉变换用 head(yaw)、pitch、roll 三个角度构造朝向矩阵,直观、易于用日常语言讨论,适合小角度调整和观察者朝向。但它依赖旋转顺序,两组欧拉角难以组合和插值,并且会出现万向节锁,因此更复杂的朝向处理需要四元数。游戏数学基本仿射变换Basic Affine Transforms平移、旋转、缩放、切变是摆放和变形物体的基础矩阵;它们的连乘顺序有关、但满足结合律。刚体变换的逆可以直接写出,法线要用伴随矩阵的转置(传统说法是逆转置)变换。理解这些矩阵的性质能写出更快、更正确的变换代码。游戏美术顶点混合与蒙皮Vertex Blending & Skinning顶点混合(也叫线性混合蒙皮、enveloping、骨骼子空间变形)让一个顶点受多根骨骼的变换影响,按权重混合结果,使关节处的"皮肤"连续弯曲。它非常适合在 GPU 上执行;主要缺点是关节折叠、扭转和自相交,可用双四元数蒙皮等方法改善。图形学顶点压缩与精度Vertex Compression & Precision网格数据像纹理一样可以压缩:传输用的整体压缩(Draco 等)一次性解码,渲染用的定长压缩让顶点着色器在 GPU 上逐顶点解码,从而降低内存、带宽并改善缓存。另一面是精度问题:大世界中单一坐标系会让远离原点的物体抖动,需要相对相机的变换或分段原点。游戏数学贝塞尔曲线Bézier Curves参数曲线 \mathbf{p}(t) 用参数 t 生成连续的点,实时图形中常用于让相机或物体沿预定路径移动(与帧率无关),也用于渲染头发和字体。贝塞尔曲线由反复线性插值(de Casteljau 算法)得到,等价于 Bernstein 多项式加权控制点;多段拼接时要关注 C^n / G^n 连续性。图形学VR 与 AR 显示基础VR & AR Display Fundamentals虚拟现实 (VR) 完全替换用户所见的世界,增强现实 (AR) 把合成物体融入真实世界,二者常合称 XR。本页介绍与渲染相关的硬件与物理要素:追踪与显示设备、"动作到光子"延迟及其导致的模拟器晕动症、姿态预测、镜头光学畸变与色差的软件补偿、滚动与全局显示,以及立体视觉中的辐辏-调节冲突与瞳距。这些约束决定了 VR 渲染为何必须高帧率、低延迟并严格依赖厂商 SDK。图形学法线贴图与凹凸贴图Normal & Bump Mapping凹凸贴图是一类在像素着色中修改着色法线来表现中尺度细节的技术:几何法线不变,只改变光照计算使用的法线,从而在不增加几何的情况下显得更立体。最常用的形式是切线空间法线贴图,需要每顶点的切线框架;法线贴图的过滤是难点。游戏数学旋转表示的比较Comparison of Rotational Representations旋转可以用欧拉角、3×3 矩阵、轴角、四元数表示,再加上平移与缩放就有 4×4(或 4×3)矩阵与 SRT(SQT)变换;更进一步还有对偶四元数。没有一种在所有场合都最好。GEA 按大小、直观性、能否直接作用于向量、能否插值、有无万向节锁比较它们,并用「参数个数 − 约束个数 = 3 个自由度」统一解释为什么它们用的浮点数不同。游戏开发动画混合Animation Blending动画混合把两个或多个输入姿势合成一个输出姿势。基本工具是对每个关节的局部 SRT 分别做 lerp(旋转用 nlerp 或 slerp);在此之上有时间插值、交叉淡入淡出、方向移动、一维/二维混合空间、部分骨骼混合和叠加混合(差分片段)。前几种都是加权平均,叠加混合则是"加上一段变化"(GEA4 卷 II 13.6)。游戏开发动画约束与后处理Animation Constraints & Post-Processing片段混合之后、渲染之前,动画系统常常还要修改姿势,这叫动画后处理:程序化动画、逆向运动学 (IK)、布娃娃。另一大类需求是约束:把武器挂在手上(挂接点)、让多个角色对齐演出(参考定位器)、手抓物体(手部 IK)、脚不滑步(根运动提取与脚部 IK),以及注视、掩体、穿越辅助等(GEA4 卷 II 13.7、13.11)。游戏开发骨骼、姿势与动画片段Skeletons, Poses & Animation Clips角色动画系统的数据核心是三样东西:骨骼(关节层级)、姿势(每个关节的 SRT 变换)和动画片段(姿势随局部时间变化的采样)。GEA 把各种动画方法看成对"逐点控制表面"这一理想的不同压缩方式;骨骼蒙皮用少量关节驱动大量顶点,是今天最主流的方案(GEA4 卷 II 13.1–13.4)。游戏开发刚体动力学Rigid Body Dynamics游戏物理引擎关心的是动力学:力如何影响运动。它做了两个简化:经典(牛顿)力学(无量子、无相对论效应)和刚体(形状不变)。无约束刚体有 6 个自由度,其运动可以分成互相独立的线性动力学(质心像质点一样平动)和角动力学(绕质心转动)。线性部分是 F=ma 的常微分方程;三维角动力学则以角动量为主变量,并用一个四元数形式的微分方程更新朝向(GEA4 卷 II 14.4)。游戏数学信号与线性时不变系统Signals & LTI Systems信号与系统理论是几乎所有数字音频技术的数学基础,也用于图像处理、电子、流体等领域。核心结论是:线性时不变 (LTI) 系统完全由它的冲激响应 h 描述,任意输入的输出等于输入与 h 的卷积;借助傅里叶变换,时域卷积等于频域乘法,滤波器就是在频域里按频率响应 H(\omega) 衰减部分频率(GEA4 卷 II 15.2)。游戏开发动画压缩Animation Compression未压缩的动画每关节每样本最多 10 个 32 位浮点通道,数据量巨大。GEA 列出的压缩手段按力度递增:省略无用通道、量化(如 16 位 RL 编码)、降低采样率或省略近似线性的关键帧、用 B 样条拟合曲线、小波压缩,以及最根本的:只把需要的片段放进内存(选择性加载与流式加载)(GEA4 卷 II 13.8)。游戏开发动画管线与动作状态机Animation Pipeline & Action State Machines低层动画管线把片段和混合规格变成局部姿势、全局姿势和蒙皮矩阵调色板;其上的动作状态机 (ASM) 给游戏代码提供"按状态驱动动画"的接口。每个状态是任意复杂的片段混合,跟踪当前所有片段的方式有扁平加权平均和混合树两种;过渡用数据驱动的过渡矩阵描述,控制参数通过节点搜索、命名变量或控制结构体暴露给代码(GEA4 卷 II 13.9–13.10)。游戏数学点与向量运算Points & Vector Operations游戏程序员最常用的数学是三维向量与矩阵(三维线性代数)。本页按 GEA 第 5 章整理点与向量的基础:坐标系与手性、点与方向的区别、标量乘与 Hadamard 积、加减、模长与归一化、点积与投影、叉积、伪向量与外代数,以及线性插值 (lerp)。贯穿全章的两条经验是:能在二维里想清楚的问题先在二维里想,以及能不开方就不开方。

被这些页面引用1 篇

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原