概述
三维变换矩阵是计算机图形学中处理三维空间几何变换的核心数学工具。它通过一个4x4的齐次坐标矩阵,统一表示几何体的平移、旋转和缩放。
本文先从数学角度对相关理论进行介绍,文章最后会从几何意义角度再次理解三维变换,让读者以更直观的方式将三维变换矩阵彻底搞懂。
三维变换矩阵的组成
在各种图形软件中,三维变换一般由平移、旋转和缩放三个变换组成。我们常见的镜像,可以当做变换系数为负的缩放来处理。
一般情况下,平移、旋转和镜像的组合顺序是先镜像,再旋转,最后平移。这个顺序不用死记硬背,用的时候拿一个中心是原点的方块想象一下就行了,这个顺序出来的效果是最符合人类直觉的。假如先旋转再缩放,方块会变斜了;如果先平移再旋转,那么方块的位置就不是那么直观能确定了。
齐次坐标的意义
个人感觉齐次坐标这个概念的引入加大了理解的难度。
所谓齐次坐标,简单点讲,就是在原有向量三维的基础上增加了一个维度。
先抛开这个概念,在三维变换中,增加一个维度的目的就是要把平移、旋转和缩放三个矩阵能用矩阵乘法来合成一个矩阵,空间变换可以用如下形式表示
P ′ = M ⋅ P M = M T ⋅ M R ⋅ M S 其中: M T :平移矩阵 M R :旋转矩阵 M S :缩放矩阵 \begin{aligned} & P^{'}=M \cdot P \\[2pt] & M=M_T \cdot M_R \cdot M_S \\[2pt] 其中:&\\ & M_T:平移矩阵 \\[2pt] & M_R:旋转矩阵 \\[2pt] & M_S:缩放矩阵 \end{aligned} 其中:P′=M⋅PM=MT⋅MR⋅MSMT:平移矩阵MR:旋转矩阵MS:缩放矩阵
这里要注意一下公式中的顺序。矩阵乘法是满足结合律的,点被乘在右边,所以按这个顺序才是先缩放,再旋转,最后平移。
这是我们平时见到的形式,下面就来讲一下齐次坐标的意义。
如果不用齐次坐标,空间变换的公式是这样的
P ′ = M R ⋅ M S ⋅ P + P T P^{'}=M_R \cdot M_S \cdot P + P_T P′=MR⋅MS⋅P+PT
平移是个向量加法操作。变成齐次坐标,主要就是为了给矩阵增加一列来把这个加法包含进来,如下所示。
P ′ = [ M R ⋅ M S , P T ] ⋅ P P^{'}= \begin{bmatrix} M_R \cdot M_S, & P_T \end{bmatrix} \cdot P P′=[MR⋅MS,PT]⋅P
但这个公式还不够完美,做完一次乘法后,点又由齐次坐标变为了普通坐标,不适合连续变换,也不适合显卡等硬件的实现。
所以再加一行,让乘完的结果也是齐次坐标,如下所示
P ′ = [ M R ⋅ M S P T 0 0 0 1 ] ⋅ P P^{'}= \begin{bmatrix} M_R \cdot M_S & P_T\\ 0 \space \space \space 0 \space \space \space 0 & 1 \end{bmatrix} \cdot P P′=[MR⋅MS0 0 0PT1]⋅P
当然,齐次坐标还有更大的作用,我们规定齐次坐标转实际坐标的公式如下
齐次坐标: ( x , y , z , w ) 实际坐标 : ( x w , y w , z w ) 齐次坐标:(x, y, z, w) \\[8px] 实际坐标: (\frac{x}{w}, \frac{y}{w}, \frac{z}{w}) 齐次坐标:(x,y,z,w)实际坐标:(wx,wy,wz)
这样齐次坐标是可以表示无穷远点的(w为0)。
同样,它还可以处理例如世界坐标到屏幕坐标的映射等更加复杂的矩阵变换(w不等于1)。
平移矩阵
平移矩阵的公式如下:
[ 1 0 0 P T x 0 1 0 P T y 0 0 1 P T z 0 0 0 1 ] \begin{bmatrix} 1& 0 & 0 & P_{T_x} \\ 0& 1 & 0 & P_{T_y} \\ 0& 0 & 1 & P_{T_z} \\ 0& 0 & 0 & 1 \end{bmatrix} 100001000010PTxPTyPTz1
这个没啥好讲的,用矩阵乘法试下就知道它的作用了,如下所示
[ 1 0 0 P T x 0 1 0 P T y 0 0 1 P T z 0 0 0 1 ] ⋅ [ P x P y P z 1 ] = [ P x + P T x P y + P T y P z + P T z 1 ] \begin{bmatrix} 1& 0 & 0 & P_{T_x} \\ 0& 1 & 0 & P_{T_y} \\ 0& 0 & 1 & P_{T_z} \\ 0& 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} P_x\\ P_y\\ P_z\\ 1 \end{bmatrix}= \begin{bmatrix} P_x + P_{T_x}\\ P_y + P_{T_y}\\ P_z + P_{T_z}\\ 1 \end{bmatrix} 100001000010PTxPTyPTz1 ⋅ PxPyPz1 = Px+PTxPy+PTyPz+PTz1
旋转矩阵
旋转矩阵的公式如下:
[ r 00 r 01 r 02 0 r 10 r 11 r 12 0 r 20 r 21 r 22 0 0 0 0 1 ] \begin{bmatrix} r_{00} & r_{01} & r_{02} & 0 \\ r_{10} & r_{11} & r_{12} & 0 \\ r_{20} & r_{21} & r_{22} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} r00r10r200r01r11r210r02r12r2200001
这里没有用角度的正余弦来表示,主要是为了方便大家理解。
设: e 0 = [ r 00 r 10 r 20 ] e 1 = [ r 01 r 11 r 21 ] e 2 = [ r 02 r 12 r 22 ] \begin{aligned} 设:& \\[2px] & e0 = \begin{bmatrix} r_{00} \\ r_{10} \\ r_{20} \\ \end{bmatrix} \\[2px] & e1 = \begin{bmatrix} r_{01} \\ r_{11} \\ r_{21} \\ \end{bmatrix} \\[2px] & e2 = \begin{bmatrix} r_{02} \\ r_{12} \\ r_{22} \\ \end{bmatrix} \\[2px] \end{aligned} 设:e0= r00r10r20 e1= r01r11r21 e2= r02r12r22
这个矩阵乘出来长这个样子
P ′ = P x ⋅ e 0 + P y ⋅ e 1 + P z ⋅ e 2 P^{'}=P_x \cdot e0 + P_y \cdot e1 + P_z \cdot e2 P′=Px⋅e0+Py⋅e1+Pz⋅e2
通过这个公式,我们可以把旋转矩阵理解为坐标系的旋转,e0、e1、e2就是旋转后新的坐标轴,P点的值是P'点在新坐标系下的局部坐标。
这样旋转矩阵的性质也就记住了:
- e0、e1、e2都是单位向量
- e0、e1、e2互相正交
关于旋转矩阵的更多知识,参考下面这篇文章
缩放矩阵
缩放矩阵的定义如下:
[ s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ] \begin{bmatrix} s_{x} & 0 & 0 & 0 \\ 0 & s_{y} & 0 & 0 \\ 0 & 0 & s_{z} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} sx0000sy0000sz00001
这个也不需要过多的解释,乘出来就懂了,如下所示
[ s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ] ⋅ [ P x P y P z 1 ] = [ s x ⋅ P x s y ⋅ P y s z ⋅ P z 1 ] \begin{bmatrix} s_{x} & 0 & 0 & 0 \\ 0 & s_{y} & 0 & 0 \\ 0 & 0 & s_{z} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} P_x\\ P_y\\ P_z\\ 1 \end{bmatrix}= \begin{bmatrix} s_{x} \cdot P_x\\ s_{y} \cdot P_y \\ s_{z} \cdot P_z \\ 1 \end{bmatrix} sx0000sy0000sz00001 ⋅ PxPyPz1 = sx⋅Pxsy⋅Pysz⋅Pz1
三维矩阵变换的几何意义理解
三维空间变换,我们可以从坐标系统变换的角度来理。
下图演示的是一个二维的坐标变换就是一个坐标系到另一个坐标系的变换。三维是一样的,二维只是更好看清楚。
缩放实际是对坐标轴的缩放,也就是说,有缩放时,坐标轴有可能不再是单位向量,为了概念统一,下面的公式依然假设e0、e1、e2是单位向量,缩放系数单独处理。
三维变换的过程也就相当于根据局部坐标系下坐标计算世界坐标系坐标的过程,如下所示
P ′ = ( P x ⋅ s x ⋅ e 0 , P y ⋅ s y ⋅ e 1 , P z ⋅ s z ⋅ e 2 ) + P T P^{'}=(P_x \cdot s_x \cdot e0,\space\space P_y \cdot s_y \cdot e1,\space\space P_z \cdot s_z\cdot e2) + P_T P′=(Px⋅sx⋅e0, Py⋅sy⋅e1, Pz⋅sz⋅e2)+PT
这个公式也为我们提供了一个将三维变换矩阵拆解成移动、旋转和缩放的算法。
逆变换的过程相当于用世界坐标系的坐标计算局部坐标系的坐标的过程。
V = P ′ − P T P = ( V ⋅ e 0 s x , V ⋅ e 1 s y , V ⋅ e 2 s z ) \begin{aligned} & V=P^{'}-P_T \\[2px] & P=(\frac{V \cdot e0}{s_x}, \space\space\frac{V \cdot e1}{s_y}, \space\space\frac{V \cdot e2}{s_z}) \end{aligned} V=P′−PTP=(sxV⋅e0, syV⋅e1, szV⋅e2)
这个公式也是快速计算三维变换矩阵逆矩阵的算法基础。
三维变换矩阵拆解算法和快速求逆算法,后续文章会做更详细的讲解。