《计算机图形学基础》之变换矩阵

2021-06-01  本文已影响0人  烂醉花间dlitf

6.1 2D 线性变换

缩放变换 是最基本的变换,可以改变向量的长度和方向。



错切 变换,在一个轴向上根据另一个轴上的值以一定比例移动,看图很容易明白。沿 x 轴和沿 y 轴上的错切矩阵分别如下:


沿 x 轴的错切
沿 y 轴的错切

沿 x 轴的错切也可以理解是沿 y 轴顺时针旋转 \phi\(与 y 轴的夹角):


沿 y 轴的错切也可以理解是沿 x 轴逆时针旋转 \phi\(与 x 轴的夹角):

旋转变换,证明过程 ,逆时针旋转 \phi\ 的矩阵为:


顺时针旋转 \phi\ 的矩阵为(其实就是把所有的 \phi\ 换成 -\phi\):
rotate(\phi)=\begin{bmatrix} cos\phi & sin\phi \\ -sin\phi & cos\phi \end{bmatrix}

可以看到旋转矩阵是 正交矩阵,并且有两对正交向量,一对是第一行和第二行向量;一对是第一列和第二列向量。每一行会被带给标准基向量((1,0)(0,1)),标准基向量会被带给每一列。简单来说就是,对标准基向量进行一个 R 旋转变换,就会变成 R 的列向量,看下图的 (0,1)点,变换后为 (-0.707,0.707),就是 R 的第二列(因为0,1相当于是 y,所以是第二列);对 R 的每一行做 R 的旋转变换,结果就是标准基向量,看下面的(0.707,-0.707),变换后为(0,1)

反射变换 是一种使用负数的缩放变换,下面分别是关于 y 轴的反射变换矩阵,和关于 x 轴的反射变换矩阵:



有人会认为矩阵的左上角和右下角都为 -1 时,也是一种反射变换(关于原点的反射),但实际上那只是 \phi=\pi 的旋转变换而已。


我们经常需要对一个图案进行多种变换,这些变换可以通过将他们的变换矩阵连乘进行 合并,比如需要先对 v_{1} 进行 S 变换得到 v_{2},然后再对 v_{2} 进行 R 变换得到 v_{3},那么有以下转换:



也就是说我们可以把所有需要用到的变换,从右往左 依次乘起来,在读变换的时候也要注意是 从右往左,比如 RS是先应用 S变换,再应用 R变换。

有时候我们也需要将一个组合的变换进行 分解,所有的 2D 矩阵都可以通过 奇异值分解(SVD) 成为旋转、缩放、旋转的形式。下图是把一个错切变换进行 SVD 的过程:


我们先从 对称矩阵 开始,对称矩阵可以通过特征值分解成 A=RSR^{T} 的形式。

我们可以把 R 当做是一次旋转,把 S 当成是一次缩放,那么其实就是一个组合变换,请结合下面的文字看图:

我们可以发现对于 对称矩阵 来说,变换的表现就是沿着一对基向量进行非均匀缩放,这一对基向量依然是正交的,跟标准基向量没什么不同,只是整体方向不一样。而这一对基向量正是 对称矩阵 的特征向量。
看一个例子:

这个式子上一篇中计算过了
对应的结果如下图,实际上是在以 特征向量为轴,并进行了大小为 特征值缩放 的过程。可以看出对称矩阵有 三个自由度,一个旋转,两个缩放。

对于非对称矩阵,我们可以使用 奇异值分解(SVD),对此有疑问的可以看 这里。他与特征值分解基本一样,不同的是左右旋转矩阵不再是同一个,而是分为两个,特征值分解的结果是A=RSR^{T},而奇异值分解 写成 A=USV^T,这里的 U依然是一个正交矩阵,列是 左奇异向量V也是一个正交向量,列是 右奇异向量S依然是对角矩阵,对角线上是奇异值。


可以看到,奇异值分解的几何意义跟特征值分解相似,但变换的角度不再是一样的。

前面提过对于非对称矩阵 A 奇异值是对称矩阵 M=AA^{T} 的平方根,但是我们默认是取正的,这是因为取负的是没有必要的,因为我们可以 随时反转某个奇异值的符合和他对应的奇异向量的方向,结果是一样的,从图形中来看就是带着坐标轴一起反转了,所以是一样的。
对于 2\times 2 的矩阵,有四个自由度,两个缩放,两个旋转,还有一个反射,但这个包含在旋转里面了。因为旋转矩阵里面也包含了反射,当行列式结果为 -1 时为反射,当结果为 1 时为旋转。当实际是反射,但期望得到旋转的时候,可以将其中一个奇异值取负来把它变成旋转矩阵,这样的话,反射就不是跟随这旋转,而是跟随着缩放了。结果依然是 旋转——缩放——旋转 的形式。

还有一种旋转的分解叫做 Paeth 分解,这是将旋转分解成 错切 的方式,最大的好处就是不会在图像中出现间隙,下面是分解公式:


举个例子,如果要旋转 45°,那么写作:

分解的过程如下:

6.3 3D 线性变换

顺着笛卡尔坐标系的 缩放 矩阵为:


绕着 z 轴,x轴,y轴 逆时针 旋转 的矩阵分别为:


注意围绕 y 轴的时候有点不一样,这个我的理解是左上角的 4 个逐渐向右下角移动,当超出边界的时候,右边超出的列往最左边补,下面超出的行往最上面补。因为 x-y-z-x-y-z-x-... 其实是循环的。
也可以在特定轴上进行 错切 变换,下面是在 x 轴上进行错切,沿着哪一个轴,就是在哪个轴上值不变。

在 3D 中,跟 2D 一样,可以将对称矩阵进行特征值分解,对非对称矩阵进行奇异值分解。

如何将一个点绕着 3D 中任意轴进行旋转呢?假设该点为 P,旋转轴为 a (这里的 a 是起点为原点的向量,所以不涉及平移),那么如果能构建一组以 az 轴的基向量,并把 P 转换到该空间,进行旋转,再转回来就可以了。
第一步:构建以 az 的一组正交基
首先我们将 a 进行归一化得到 w


再找一个跟 w 不同,并且也不是很接近的向量 t,比较简单的一个办法就是直接将 w 的最小值改成 1。然后使用叉乘找到第二个正交基 u

最后再次使用叉乘得到第三个正交基:

我们只关心 w,剩下两个并不重要,只需要他们存在就够了。

第二步:构建空间转换矩阵
假设我们有一组基向量,x=(0,0,1),y=(1,0,0),z=(0,1,0),还有一个点 P=(1,0,1),将 x,t,z 按行来摆好,写成 R=\begin{bmatrix}0 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{bmatrix} 我们可以提前知道 P 在上述基向量中的坐标应该为 (1,1,0),正是 RP=\begin{bmatrix}0 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{bmatrix} \begin{bmatrix}1 \\ 0 \\ 1 \end{bmatrix} 的结果。下面是书上的证明过程,有兴趣的可以看一下,没兴趣就记着我们可以用任意的一组正交基,把 x 三个分量摆第一行,把 y 三个分量摆第二行,把 z 三个分量摆第三行,总而构建出转换到该空间下的转换矩阵。并且再次乘其转置,就可以再次变回来。


第三步:实现
也就是按上面所说的,先转换空间(从右往左看),再绕着转换后空间内的 z 轴,实际上(也就是在一开始的标准基向量空间)是 a 向量的旋转我们期望的 \phi 度,最后再转换回一开始的空间。注意转换空间的意思只是坐标改变了,但世界上位置不变,就像步骤一里面的 P 一样,他一直都在 (1,0,1) 的位置,只不过在另一个空间的坐标为 (1,1,0),我们只是让它在这两个坐标之间做转换。

上面所说的变换都是方向或者点,还有一种特殊的向量叫做 法线,如果图形应用的变换矩阵我们称为 M,那么 n 经过 M 变换之后不再垂于表面,但切线 t 依然与表面相切。期望求出一个矩阵 N,使得 n^{T}_{N}t^{M}=0,其中 n_{N}=Nn,t^{M}=Mt


下面是证明过程,有兴趣的可以看一下,没兴趣的可以直接跳过图片看结论。

我们并不关心法线的长度,只需要知道它的方向,所以在知道了 n_{N} =(M^{-1})^{T}n 之后,按照求逆的公式 A = \frac{1}{|A|}\begin{bmatrix} a_{11}^{c} & a_{21}^{c} & a_{31}^{c} & a_{41}^{c} \\ a_{12}^{c} & a_{22}^{c} & a_{32}^{c} & a_{42}^{c} \\ a_{13}^{c} & a_{23}^{c} & a_{33}^{c} & a_{43}^{c} \\ a_{14}^{c} & a_{24}^{c} & a_{34}^{c} & a_{44}^{c} \end{bmatrix},我们可以把 \frac{1}{|A|}去掉,所以:

进一步就是:

6.3 仿射变换和齐次坐标

以上所有的变换都是 线性变换(原点不变,且直线变换后依然是直线),而 平移 变换并不满足。我们把一个线性变换 + 一次平移的操作叫做 仿射变换,通过增加一个维度的方式来实现,叫做 齐次坐标
我们把一个 2D 中的点 (x,y) 写成 (x,y,1),把 2\times 2 的矩阵写成:


这样应用变换就将写成:

也就巧妙在不改变线性变换的计算时,加入了平移变换。当我们 不想进行平移操作,只想进行线性变换的时候,对于不是位置的向量,比如说偏移,或者方向,确实也不应该在改变物体的时候进行平移。那可以 \begin{bmatrix}x' \\ y' \\ 1\end{bmatrix} 中的 1 变成 0。并且在变换之后, 0 依然是 0,也就是方向向量依然是方向向量。(女少)

我们可以把任意多个线性变换和平移变换组合成一个矩阵,在 3D 中也一样,增加一个维度:

看一个例子,下图和式子是表示的同一个过程:


另一种类似的、在 3D 中的变换为,将一个盒子 [x_{l},x_{h}]\times [y_{l},y_{h}]\times [z_{l},z_{h}]映射到 [x'_{l},x'_{h}]\times [y'_{l},y'_{h}]\times [z'_{l},z'_{h}]。矩阵为:

注意,我们 应用一个线性变换,然后再 进行平移,得到的矩阵还是可以很清楚的把线性和平移分离开来,如下面的式子所示。

变换中一个比较重要的类叫做 刚体,他们只有旋转和平移组成,没有拉伸或者缩放。

6.4 变换的逆

我们知道了矩阵的几何意义之后,可以通过几何意义来进行逆操作,比如 scale(s_{x},s_{y},s_{z}) 的逆就是 scale(1/s_{x},1/s_{y},1/s_{z});比如旋转矩阵的逆就是角度变成相反的符号;平移矩阵的逆就是相反的方向。如果我们有一系列的变换 M=M_{1}M_{2}... M_{n},那么逆操作就是 M^{-1}=M^{-1}_{n}...M^{-1}_{2} M^{-1}_{1}
不过,有些矩阵在代数上也是很好求的,比如说对于缩放矩阵,他是对角矩阵;第二重要的是旋转矩阵,他是正交矩阵,逆就是它的转置。所以使得求旋转和缸体的逆操作都变得简单。当然我们也需要知道,求完逆之后,原矩阵最下面一行不要动,比如是 [0,0,0,1] 的话,那逆的最下面一行也是 0,0,0,1
有趣的是,我们也可以使用奇异值分解来求逆,我们知道可以将一个矩阵分解成旋转——缩放——旋转的方式:


那么按照上面说的,这个矩阵的逆就是:

6.5 坐标转换

通常我们会在场景中有一个全局坐标系(世界坐标系),图中的 oxy,图中有另外一个坐标系 euv,还有一个点 p


oxy 坐标系中,p=(2.5,0.9),这是简写,完整的写法是:
euv 坐标系中,p=(0.5,-0.7),这是简写,完整的写法是:

我们在存储的时候也只需要存简写的两个数字而已,o,x,y,e,,u,v 这些都存在心里,不会被写出来。如果我们将这种坐标系转换用矩阵表示出来,就是:

我们只是将 uve 按顺序放在列中,并在最底下写上 0 0 1。也就是以下形式:

反过来的矩阵为:

也就是:

注意 oxy 并没有什么特别的,只是我们习惯性将它看成是标准的,所以你完全可以把 oxyeuv 的矩阵写成:

在 3D 中,也是类似的情况:
上一篇下一篇

猜你喜欢

热点阅读