6.1 2D 线性变换
缩放变换 是最基本的变换,可以改变向量的长度和方向。
错切 变换,在一个轴向上根据另一个轴上的值以一定比例移动,看图很容易明白。沿 轴和沿
轴上的错切矩阵分别如下:
沿 轴的错切也可以理解是沿
轴顺时针旋转
(与
轴的夹角):
沿
旋转变换,证明过程 略,逆时针旋转 的矩阵为:
顺时针旋转
可以看到旋转矩阵是 正交矩阵,并且有两对正交向量,一对是第一行和第二行向量;一对是第一列和第二列向量。每一行会被带给标准基向量(),标准基向量会被带给每一列。简单来说就是,对标准基向量进行一个
旋转变换,就会变成
的列向量,看下图的
点,变换后为
,就是
的第二列(因为
相当于是
,所以是第二列);对
的每一行做
的旋转变换,结果就是标准基向量,看下面的
,变换后为
。
反射变换 是一种使用负数的缩放变换,下面分别是关于 轴的反射变换矩阵,和关于
轴的反射变换矩阵:
有人会认为矩阵的左上角和右下角都为 时,也是一种反射变换(关于原点的反射),但实际上那只是
的旋转变换而已。
我们经常需要对一个图案进行多种变换,这些变换可以通过将他们的变换矩阵连乘进行 合并,比如需要先对 进行
变换得到
,然后再对
进行
变换得到
,那么有以下转换:
也就是说我们可以把所有需要用到的变换,从右往左 依次乘起来,在读变换的时候也要注意是 从右往左,比如
有时候我们也需要将一个组合的变换进行 分解,所有的 2D 矩阵都可以通过 奇异值分解(SVD) 成为旋转、缩放、旋转的形式。下图是把一个错切变换进行 SVD 的过程:
我们先从 对称矩阵 开始,对称矩阵可以通过特征值分解成
-
是正交矩阵,我们称他的列为
-
是对角矩阵,从左上到右下依次为
(这一块不明白的可以看 这里)
我们可以把 当做是一次旋转,把
当成是一次缩放,那么其实就是一个组合变换,请结合下面的文字看图:
- 将
旋转到跟标准基坐标对齐 (
)
- 在标准基坐标上进行缩放 (
)
- 旋转回原来的角度 (
)
任意对称矩阵 A,也被叫做非轴对齐的非均匀缩放变换
我们可以发现对于 对称矩阵 来说,变换的表现就是沿着一对基向量进行非均匀缩放,这一对基向量依然是正交的,跟标准基向量没什么不同,只是整体方向不一样。而这一对基向量正是 对称矩阵 的特征向量。
看一个例子:
对应的结果如下图,实际上是在以 特征向量为轴,并进行了大小为 特征值 的 缩放 的过程。可以看出对称矩阵有 三个自由度,一个旋转,两个缩放。
对于非对称矩阵,我们可以使用 奇异值分解(SVD),对此有疑问的可以看 这里。他与特征值分解基本一样,不同的是左右旋转矩阵不再是同一个,而是分为两个,特征值分解的结果是,而奇异值分解 写成
,这里的
依然是一个正交矩阵,列是 左奇异向量,
也是一个正交向量,列是 右奇异向量,S依然是对角矩阵,对角线上是奇异值。
可以看到,奇异值分解的几何意义跟特征值分解相似,但变换的角度不再是一样的。
前面提过对于非对称矩阵
对于
还有一种旋转的分解叫做 Paeth 分解,这是将旋转分解成 错切 的方式,最大的好处就是不会在图像中出现间隙,下面是分解公式:
举个例子,如果要旋转 45°,那么写作:
分解的过程如下:
6.3 3D 线性变换
顺着笛卡尔坐标系的 缩放 矩阵为:
绕着 z 轴,x轴,y轴 逆时针 旋转 的矩阵分别为:
注意围绕 y 轴的时候有点不一样,这个我的理解是左上角的 4 个逐渐向右下角移动,当超出边界的时候,右边超出的列往最左边补,下面超出的行往最上面补。因为 x-y-z-x-y-z-x-... 其实是循环的。
也可以在特定轴上进行 错切 变换,下面是在 x 轴上进行错切,沿着哪一个轴,就是在哪个轴上值不变。
在 3D 中,跟 2D 一样,可以将对称矩阵进行特征值分解,对非对称矩阵进行奇异值分解。
如何将一个点绕着 3D 中任意轴进行旋转呢?假设该点为 ,旋转轴为
(这里的
是起点为原点的向量,所以不涉及平移),那么如果能构建一组以
为
轴的基向量,并把
转换到该空间,进行旋转,再转回来就可以了。
第一步:构建以 为
的一组正交基
首先我们将 进行归一化得到
:
再找一个跟
最后再次使用叉乘得到第三个正交基:
我们只关心
第二步:构建空间转换矩阵
假设我们有一组基向量,,还有一个点
,将
按行来摆好,写成
我们可以提前知道
在上述基向量中的坐标应该为
,正是
的结果。下面是书上的证明过程,有兴趣的可以看一下,没兴趣就记着我们可以用任意的一组正交基,把
三个分量摆第一行,把
三个分量摆第二行,把
三个分量摆第三行,总而构建出转换到该空间下的转换矩阵。并且再次乘其转置,就可以再次变回来。
第三步:实现
也就是按上面所说的,先转换空间(从右往左看),再绕着转换后空间内的
上面所说的变换都是方向或者点,还有一种特殊的向量叫做 法线,如果图形应用的变换矩阵我们称为 ,那么
经过
变换之后不再垂于表面,但切线
依然与表面相切。期望求出一个矩阵
,使得
,其中
。
下面是证明过程,有兴趣的可以看一下,没兴趣的可以直接跳过图片看结论。
我们并不关心法线的长度,只需要知道它的方向,所以在知道了
进一步就是:
6.3 仿射变换和齐次坐标
以上所有的变换都是 线性变换(原点不变,且直线变换后依然是直线),而 平移 变换并不满足。我们把一个线性变换 + 一次平移的操作叫做 仿射变换,通过增加一个维度的方式来实现,叫做 齐次坐标。
我们把一个 2D 中的点 写成
,把
的矩阵写成:
这样应用变换就将写成:
也就巧妙在不改变线性变换的计算时,加入了平移变换。当我们 不想进行平移操作,只想进行线性变换的时候,对于不是位置的向量,比如说偏移,或者方向,确实也不应该在改变物体的时候进行平移。那可以
我们可以把任意多个线性变换和平移变换组合成一个矩阵,在 3D 中也一样,增加一个维度:
看一个例子,下图和式子是表示的同一个过程:
另一种类似的、在 3D 中的变换为,将一个盒子
注意,我们 先 应用一个线性变换,然后再 进行平移,得到的矩阵还是可以很清楚的把线性和平移分离开来,如下面的式子所示。
变换中一个比较重要的类叫做 刚体,他们只有旋转和平移组成,没有拉伸或者缩放。
6.4 变换的逆
我们知道了矩阵的几何意义之后,可以通过几何意义来进行逆操作,比如 的逆就是
;比如旋转矩阵的逆就是角度变成相反的符号;平移矩阵的逆就是相反的方向。如果我们有一系列的变换
,那么逆操作就是
。
不过,有些矩阵在代数上也是很好求的,比如说对于缩放矩阵,他是对角矩阵;第二重要的是旋转矩阵,他是正交矩阵,逆就是它的转置。所以使得求旋转和缸体的逆操作都变得简单。当然我们也需要知道,求完逆之后,原矩阵最下面一行不要动,比如是 的话,那逆的最下面一行也是
。
有趣的是,我们也可以使用奇异值分解来求逆,我们知道可以将一个矩阵分解成旋转——缩放——旋转的方式:
那么按照上面说的,这个矩阵的逆就是:
6.5 坐标转换
通常我们会在场景中有一个全局坐标系(世界坐标系),图中的 ,图中有另外一个坐标系
,还有一个点
。
在
在
我们在存储的时候也只需要存简写的两个数字而已,
我们只是将
反过来的矩阵为:
也就是:
注意
在 3D 中,也是类似的情况: