Tag DirectX下的博客主要用于记录DirectX的学习过程,主要参考《DirectX 12 3D 游戏实战开发》。本篇主要是顺着DX12龙书的节奏温习线性代数中的仿射变换。
仿射变换
仿射变换是在线性变换的基础上加入平移变换得到的。之前线性变换的对象都是3维向量,向量只表示方向,对向量作平移是没有意义的,因此平移只能作用于点。齐次坐标表示法可以统一对点和向量的平移变换。
齐次坐标
在普通3维坐标的基础上加入第四维w即构成齐次坐标。参考《3D数学基础:图形与游戏开发》,可以通过“投影”来理解齐次坐标。先考虑2D的齐次坐标(x,y,w),截取w=1处的平面,对坐标系内的点作关于原点的透视投影,投影之后的坐标值为(x/w,y/w,1)。而当w=0时,除零可以看作趋于无穷,即形如(x,y,0)的点在无穷远处,此时我们用它来表示方向。类比2维,可以推出3维的情况,截取w=1处的超平面作投影即可。类似地,我们可以用(x,y,z,1)表示点,用(x,y,z,0)表示向量。
仿射变换
仿射变换即在线性变换的基础上增加一个平移变换,通常用下式表示:
\[
\alpha(\vec u)=\tau(\vec u)+\vec b,\vec b为平移向量
\]
又或者:(其中,M为线性变换矩阵,b为平移变换向量)
\[
\alpha(\vec u)=\vec u\times M+\vec b=[x,y,z]\times
\begin{bmatrix}
A_{11}&A_{12}&A_{13}\\
A_{21}&A_{22}&A_{23}\\
A_{31}&A_{32}&A_{33}
\end{bmatrix}
+[b_x,b_y,b_z]=[x\prime,y\prime,z\prime]
\]
我们把仿射变换矩阵记为A,同时,记线性变换矩阵为M`,平移向量为b,采用如下方式扩展M:
\[
M\prime=
\begin{bmatrix}
M&0\\
0&1
\end{bmatrix}
=
\begin{bmatrix}
A_{11}&A_{12}&A_{13}&0\\
A_{21}&A_{22}&A_{23}&0\\
A_{31}&A_{32}&A_{33}&0\\
0&0&0&1
\end{bmatrix}
\]
采用这种表示的好处是,他可以保留线性变换的正确结果,同时又不会改变w。
在齐次坐标中,采用如下矩阵B表示平移向量:
\[
B=
\begin{bmatrix}
I&0\\
\vec b&1
\end{bmatrix}
=
\begin{bmatrix}
1&0&0&0\\
0&1&0&0\\
0&0&1&0\\
b_x&b_y&b_z&1
\end{bmatrix}
\]
同时还有:
\[
\begin{aligned}
&[x,y,z,1]\times\begin{bmatrix}
1&0&0&0\\
0&1&0&0\\
0&0&1&0\\
b_x&b_y&b_z&1
\end{bmatrix}=[x+b_x,y+b_y,z+b_z,1]\\
&[x,y,z,0]\times\begin{bmatrix}
1&0&0&0\\
0&1&0&0\\
0&0&1&0\\
b_x&b_y&b_z&1
\end{bmatrix}=[x,y,z,0]
\end{aligned}
\]
这正是平移的结果。同时,根据平移的性质容易得到其逆变换矩阵为:
\[
B^{-1}=
\begin{bmatrix}
1&0&0&0\\
0&1&0&0\\
0&0&1&0\\
-b_x&-b_y&-b_z&1
\end{bmatrix}
\]
找到线性变换和平移变换对应的齐次矩阵之后,直接组合便可以得到仿射变换的矩阵:
\[
A=M\prime\times B=
\begin{bmatrix}
A_{11}&A_{12}&A_{13}&0\\
A_{21}&A_{22}&A_{23}&0\\
A_{31}&A_{32}&A_{33}&0\\
0&0&0&1
\end{bmatrix}
\times
\begin{bmatrix}
1&0&0&0\\
0&1&0&0\\
0&0&1&0\\
b_x&b_y&b_z&1
\end{bmatrix}
=
\begin{bmatrix}
A_{11}&A_{12}&A_{13}&0\\
A_{21}&A_{22}&A_{23}&0\\
A_{31}&A_{32}&A_{33}&0\\
b_x&b_y&b_z&1
\end{bmatrix}
\]
用分块法表示为:
\[
A=
\begin{bmatrix}
M&0\\
\vec b&1
\end{bmatrix}
\]
但其实仿射变换矩阵的推导过程比较复杂,不过结果的形式很简单。
组合变换
也就是把缩放、旋转、平移变换组合为一个变换,通过矩阵乘法可以方便的实现。在对多物体进行同一系列变换时,可以提升效率。通常变换的连接顺序为缩放(Scale)、旋转(Rotate)、平移(Transform)。通过变换,也可以更形象地理解矩阵乘法为什么一般不满足交换律:先旋转再平移与先平移再旋转的结果往往是不同的。