图形学学习笔记1 --三维旋转和四元数(3D Rotations and Quaternions)
在图形学,3D视觉等领域,矩阵变换是在常见不过的一种操作,而旋转变换又是其中尤其特别的一种,我们在玩游戏时,移动鼠标看向不同地方就是在进行三维旋转;我们看到的动画电影中角色变换的身姿也是通过三维旋转实现的。因此,深入理解3维空间的旋转至关重要。
Matrix Transformation of Vector(向量的矩阵变换)
空间中的方向,位置都可以通过矩阵进行变换,v′=Mv\bold{v}'=M\bold{v}v′=Mv,旋转也不例外,想让物体在三维空间中旋转,本质上也是通过将位置乘上一个旋转矩阵的来的。
Basis(基底)
在深入探究旋转矩阵前,可以先理解下矩阵在几何领域的含义:
变换矩阵MMM的每一列都是一个基向量,M=[e1e2e3]M=\begin{bmatrix} \bold{e_1}&\bold{e_2}&\bold{e_3} \end{bmatrix}M=[e1e2e3],它们组成了一个本地坐标系,对于任意一个向量,我们都可以将其写作本地坐标系下的坐标。
若我们有两个本地坐标系 M1=[u1u2u3]M_1=\begin{bmatrix} \bold{u_1}&\bold{u_2}&\bold{u_3} \end{bmatrix}M1=[u1u2u3],M2=[v1v2v3]M_2=\begin{bmatrix} \bold{v_1}&\bold{v_2}&\bold{v_3} \end{bmatrix}M2=[v1v2v3],我们希望将一个用本地坐标系M1M_1M1表示的点坐标p1\bold{p}_1p1用本地坐标系M2M_2M2表示,我们需要先将其转换到全局坐标系下,再转换到M2M_2M2。列举所有情况如下:
- L1→W→L2L_1\to{W}\to{}L_2L1→W→L2:p2=M2−1M1p1\bold{p}_2=M_2^{-1}M_1\bold{p}_1p2=M2−1M1p1
- W→L2{W}\to{}L_2W→L2:p2=M2−1pglobal\bold{p}_2=M_2^{-1}\bold{p}_{global}p2=M2−1pglobal
- L1→WL_1\to{}WL1→W:pglobal=M1p1\bold{p}_{global}=M_1\bold{p}_{1}pglobal=M1p1
3B1B就矩阵的几何解释做了很多期相关视频,有兴趣的同学可以去看看 https://www.bilibili.com/video/BV1ib411t7YR/?spm_id_from=333.337.search-card.all.click&vd_source=aac7fb9ff30051b45d68db048d45e689。
3D Rotation
Rotation Matrix
话说回旋转矩阵,旋转变换矩阵较为特殊,旋转矩阵RRR都是正交矩阵(orthogonal matrix),即RT=R−1,det(R)=1R^T=R^{-1}, \det(R)=1RT=R−1,det(R)=1。R=[e1e2e3]R=\begin{bmatrix} \bold{e_1}&\bold{e_2}&\bold{e_3} \end{bmatrix}R=[e1e2e3] 的基向量是互相垂直的(点积为 0),并且模长都为 1。
Rodrigues’ rotation formula(罗德里格斯旋转公式)
在三维情况下,若我们知道旋转轴向量,可以使用罗德里格斯旋转公式绕任意轴旋转。
假设我们现在有单位向量w∈R3\bold{w}\in\mathbb{R}^3w∈R3有w⊤=[wx,wy,wz]\bold{w}^\top=[w_x,w_y,w_z]w⊤=[wx,wy,wz],现让向量v\bold{v}v绕轴w\bold{w}w按右手旋转方向旋转θ\thetaθ角度,旋转后的向量为:
vrot=vcosθ+(w×v)sinθ+w(w⋅v)(1−cosθ) \begin{equation} \bold{v}_{\mathrm{rot}}=\bold{v}\cos\theta+(\bold{w}\times\bold{v})\sin\theta+\bold{w}(\bold{w}\cdot\bold{v})(1-\cos\theta) \end{equation} vrot=vcosθ+(w×v)sinθ+w(w⋅v)(1−cosθ)
同时,我们希望将此旋转用矩阵表示,因此需要用矩阵形式表示叉乘与点乘,点乘可以简单使用转置乘法,即w⋅v=w⊤v\bold{w}\cdot{\bold{v}}=\bold{w}^\top\bold{v}w⋅v=w⊤v;叉乘可以使用一个矩阵表示,W=[0−wzwywz0−wx−wywx0]\bold{W}=\begin{bmatrix} 0&-w_z&w_y\\ w_z&0&-w_x\\ -w_y&w_x&0 \end{bmatrix}W=0wz−wy−wz0wxwy−wx0,有w×v=Wv\bold{w}\times{\bold{v}}=\bold{W}\bold{v}w×v=Wv。
由此可以写作矩阵形式:
R(w,θ)=cosθI+(1−cosθ)wwT+sinθW \begin{equation} \bold{R}(\bold{w},\theta)=\cos{\theta}\bold{I}+(1-\cos{\theta})\bold{w}\bold{w}^T+\sin{\theta} \bold{W} \end{equation} R(w,θ)=cosθI+(1−cosθ)wwT+sinθW
此外也可写作:
Rotation Representations
我们希望用一些数字来表示三维空间中的任意旋转,一般用于表示旋转的方法有欧拉角(Euler angles)和四元数(Quaternions)。
Euler angles(欧拉角)
欧拉角使用三个角度[roll,pitch,yaw][\mathrm{roll, pitch, yaw}][roll,pitch,yaw]来表示任意旋转,三个角度分别代表绕轴旋转的角度α,β,γ\alpha,\beta,\gammaα,β,γ。三次旋转按照顺序进行,会产生三个旋转矩阵R1,R2,R3R_1,R_2,R_3R1,R2,R3,最终矩阵为R=R3R2R1R=R_3R_2R_1R=R3R2R1。由于后面的旋转是在旋转后的本地坐标系下进行的,因此旋转的顺序不同最终的结果也不同。
绕 xyz 轴旋转θ\thetaθ度的单个旋转矩阵分别为:
Rx=[1000cosθ−sinθ0sinθcosθ],Ry=[cosθ0sinθ010−sinθ0cosθ],Rz=[cosθ−sinθ0sinθcosθ0001]
R_x=\begin{bmatrix}
1&0&0\\0&\cos\theta&-\sin\theta\\0&\sin\theta&\cos\theta
\end{bmatrix}
,
R_y=\begin{bmatrix}
\cos\theta&0&\sin\theta\\0&1&0\\-\sin\theta&0&\cos\theta
\end{bmatrix}
,
R_z=\begin{bmatrix}
\cos\theta&-\sin\theta&0\\\sin\theta&\cos\theta&0\\0&0&1
\end{bmatrix}
Rx=1000cosθsinθ0−sinθcosθ,Ry=cosθ0−sinθ010sinθ0cosθ,Rz=cosθsinθ0−sinθcosθ0001
不同的软件默认的旋转角和旋转顺序都不尽相同,例如UE中默认先绕z轴旋转γ\gammaγ,再绕y轴旋转β\betaβ,最后绕x轴旋转α\alphaα

Gimbal Lock(万向锁)
欧拉角虽然表示含义清晰,但会出现万向锁问题,即两个轴对齐时会失去一个自由度。
Quaternions(四元数)
四元数是对复数的推广,四元数的表示有三个虚数符号i,j,k\bold{i,j,k}i,j,k,其计算方法如下:
i2=−1,j2=−1,k2=−1,ij=k,jk=i,ki=j,ji=−k,kj=−i,ik=−j \bold{i}^2=-1,\bold{j}^2=-1,\bold{k}^2=-1, \\ \bold{i}\bold{j}=\bold{k}, \bold{j}\bold{k}=\bold{i}, \bold{k}\bold{i}=\bold{j}, \bold{j}\bold{i}=-\bold{k}, \bold{k}\bold{j}=-\bold{i}, \bold{i}\bold{k}=-\bold{j} i2=−1,j2=−1,k2=−1,ij=k,jk=i,ki=j,ji=−k,kj=−i,ik=−j
四元数表示为:q=s+xi+yj+zkq=s+x\bold{i}+y\bold{j}+z\bold{k}q=s+xi+yj+zk,s,x,y,zs,x,y,zs,x,y,z是标量 scalars
Properties of Quaternions
四元数遵循结合律,分配率,但不遵循交换律(not commutative)。
-
q1 q2≠q2 q1q_1\,q_2\neq{}q_2\,q_1q1q2=q2q1
-
(q1 q2) q3=q1 (q2 q3)(q_1\,q_2)\,q_3=q_1\,(q_2\,q_3)(q1q2)q3=q1(q2q3)
-
(q1+q2) q3=q1 q3+q2 q3(q_1+q_2)\,q_3=q_1\,q_3+q_2\,q_3(q1+q2)q3=q1q3+q2q3
-
α(q1+q2)=α q1+α q2\alpha(q_1+q_2)=\alpha\,{}q_1+\alpha\,{}q_2α(q1+q2)=αq1+αq2,α\alphaα是标量
对于四元数q=s+xi+yj+zkq=s+x\bold{i}+y\bold{j}+z\bold{k}q=s+xi+yj+zk,它的性质有:
- 模长(Norm):∣q∣2=s2+x2+y2+z2|q|^2=s^2+x^2+y^2+z^2∣q∣2=s2+x2+y2+z2
- 共轭四元数(Conjugate quaternion):qˉ=s−xi−yj−zk\bar{q}=s-x\bold{i}-y\bold{j}-z\bold{k}qˉ=s−xi−yj−zk
- 逆四元数(Inverse quaternion):q−1=qˉ/∣q∣2q^{-1}=\bar{q}/|q|^2q−1=qˉ/∣q∣2
- 单位四元数(Unity quaternion):∣q∣=1|q|=1∣q∣=1
- 单位四元数的逆(Inverse of unit quaternion):q−1=qˉq^{-1}=\bar{q}q−1=qˉ
Quaternions and Rotations
三维空间中的任意旋转都可以由一个单位四元数表示。
一个绕轴[ux,uy,uz][\bold{u}_x,\bold{u}_y,\bold{u}_z][ux,uy,uz]θ\thetaθ度的旋转,可以表示成:
q=cos(θ/2)+sin(θ/2)ux i+sin(θ/2)uy j+sin(θ/2)uz k \begin{equation} q=\cos(\theta/2)+\sin(\theta/2)\bold{u}_x\,\bold{i}+\sin(\theta/2)\bold{u}_y\,\bold{j}+\sin(\theta/2)\bold{u}_z\,\bold{k} \end{equation} q=cos(θ/2)+sin(θ/2)uxi+sin(θ/2)uyj+sin(θ/2)uzk
旋转q1q_1q1与q2q_2q2的组合可以写作q=q2 q1q=q_2\,q_1q=q2q1

四元数q=a+bi+cj+dkq=a+b\bold{i}+c\bold{j}+d\bold{k}q=a+bi+cj+dk转换为旋转矩阵的公式为:
R=[a2+b2+c2+d22bc−2ad2bd+2ac2bc+2ada2−b2+c2−d22cd−2ab2bd−2ac2cd+2aba2−b2−c2+d2] \begin{equation} R=\begin{bmatrix} a^2+b^2+c^2+d^2&2bc-2ad&2bd+2ac\\ 2bc+2ad&a^2-b^2+c^2-d^2&2cd-2ab\\ 2bd-2ac&2cd+2ab&a^2-b^2-c^2+d^2 \end{bmatrix} \end{equation} R=a2+b2+c2+d22bc+2ad2bd−2ac2bc−2ada2−b2+c2−d22cd+2ab2bd+2ac2cd−2aba2−b2−c2+d2
四元数qqq与−q-q−q表示的旋转相同,此外任何不同的四元数都代表不同的旋转。
Quaternion Interpolation
在计算机动画中,我们通常使用关键帧(Key frame)来表示动画,关键帧会记录各个关节(joint)的旋转情况,关键帧之间的旋转则需通过插值得到。
SLERP
使用四元数进行插值会比欧拉角的效果更好,四元数插值相当于在 4D 单位球上寻找最短路径,这种插值方法被称为 SLERP(Spherical Linear intERPolation)。

Slerp 的计算公式如下:
Slerp(q1,q2,u)=sin((1−u)θ)sinθq1+sin(uθ)sinθq2 \begin{equation} \mathrm{Slerp}(q_1,q_2,u)=\frac{\sin((1-u)\theta)}{\sin\theta}q_1+\frac{\sin(u\theta)}{\sin\theta}q_2 \end{equation} Slerp(q1,q2,u)=sinθsin((1−u)θ)q1+sinθsin(uθ)q2
其中u∈[0,1]u\in[0,1]u∈[0,1],θ\thetaθ的计算为:cosθ=q1⋅q2=s1s2+x1x2+y1y2+z1z2\cos\theta=q_1\cdot{}q_2=s_1s_2+x_1x_2+y_1y_2+z_1z_2cosθ=q1⋅q2=s1s2+x1x2+y1y2+z1z2
如果将其应用于多个四元数的插值,那么可能会导致在节点变化时角速度是不光滑(smooth)的。

Bezier Interpolation
Ken Shoemake in the SIGGRAPH '85 proceedings (Computer Graphics, V. 19, No. 3, P. 245)提出我们可以使用贝塞尔曲线光滑过渡不同的关键帧。
当我们有四元数qn−1,qn,qn+1q_{n-1},q_n,q_{n+1}qn−1,qn,qn+1时,我们可以构建如下图所示:
aˉn=Slerp(Slerp(qn−1,qn,2),qn+1,0.5)\bar{a}_n=\mathrm{Slerp}(\mathrm{Slerp}(q_{n-1}, q_n, 2), q_{n+1}, 0.5)aˉn=Slerp(Slerp(qn−1,qn,2),qn+1,0.5)
an=Slerp(qn,aˉn,1/3)a_n=\mathrm{Slerp}(q_n,\bar{a}_n,1/3)an=Slerp(qn,aˉn,1/3)
bn=Slerp(qn,aˉn,−1/3)b_n=\mathrm{Slerp}(q_n,\bar{a}_n,-1/3)bn=Slerp(qn,aˉn,−1/3)
边界情况:
a1=Slerp(q1,Slerp(q3,q2,2),1/3){a}_1=\mathrm{Slerp}(q_1, \mathrm{Slerp}(q_{3}, q_2, 2), 1/3)a1=Slerp(q1,Slerp(q3,q2,2),1/3)
bn=Slerp(qn,Slerp(qn−2,qn−1,2),1/3){b}_n=\mathrm{Slerp}(q_n, \mathrm{Slerp}(q_{n-2}, q_{n-1}, 2), 1/3)bn=Slerp(qn,Slerp(qn−2,qn−1,2),1/3)

因此,给定四元数$q_1,…,q_n 我们可以构建所有控制点我们可以构建所有控制点我们可以构建所有控制点a_1,…,a_n,b_1,…,b_n$。
qiq_iqi与qi+1q_{i+1}qi+1之间的曲线可以用qi,ai,bi+1,qi+1q_i,a_i,b_{i+1},q_{i+1}qi,ai,bi+1,qi+1四个控制点来进行表示,再使用 De Casteljau 算法就可以计算出插值四元数。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)