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)。通过变换,也可以更形象地理解矩阵乘法为什么一般不满足交换律:先旋转再平移与先平移再旋转的结果往往是不同的。