美文网首页
《计算机图形学基础》之变换矩阵

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

作者: 烂醉花间dlitf | 来源:发表于2021-06-01 23:00 被阅读0次

    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是正交矩阵,我们称他的列为 v_{1},v_{2}
    • S是对角矩阵,从左上到右下依次为\lambda_{1},\lambda_{1}
      (这一块不明白的可以看 这里

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

    • v_{1},v_{2}旋转到跟标准基坐标对齐 (R^{T}
    • 在标准基坐标上进行缩放 (S
    • 旋转回原来的角度 (R
      任意对称矩阵 A,也被叫做非轴对齐的非均匀缩放变换

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

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

    对于非对称矩阵,我们可以使用 奇异值分解(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 中,也是类似的情况:

    相关文章

      网友评论

          本文标题:《计算机图形学基础》之变换矩阵

          本文链接:https://www.haomeiwen.com/subject/nuwysltx.html