首先是两个参考视频:
视频1:现代计算机图形学入门-闫令琪(第三章:变换的介绍)
视频2:线性代数的本质 - 03 - 矩阵与线性变换
在生活中,或者说在我们开发游戏的时候,会碰见很多很多的变换。在图形学中,主要有如下两种变换,模型变换(例如模型的缩放,IK)和视图变换(例如相机的移动旋转)。还有例如三维空间到二维空间(投影)也是非常重要的变换。
上面提到的移动,缩放,旋转这些变换,其实都是将一个输入的值,进过一些操作,变成一个新的输出值。例如输入一个点的位置0,最后输出其位置10,即发生了移动变换。由这一个特性也可得出,所谓的变换其实就是函数。
输入值x -> 变换( 函数f(x) ) -> 输出值x
而使用变换是为了让我们以运动的方式去思考,例如前面提到位置0变为10,我们要想成是从0慢慢移动到10,并不是一下子变为10。
在线性代数中,变换考虑的是一个向量的输入以及输出,向量的起点都为原点,例如将向量(2,4)缩放0.5倍,即得到向量(1,2)。对于一个整个空间(称之为线性空间或向量空间),我们可以看作空间内有无数个点,而原点到每一个点的连线即为一个向量。空间的变换即空间中每一个向量都移动到对应输出向量的位置,也可以看作是空间中的每个点移动到变换后的目标位置。
例如下图,便是一个简单的空间旋转变换,向量(0,1)旋转后变为(1,0)。
接下来我们来看一个比较复杂的变换,如下图,为复平面上 的变换:
看着很高级,那么它是怎么变换成这样的呢?首先我们要了解何为复平面,简单来说复平面是用来表示复数的,即a+bi,其中a和b为实数,i为虚数()。复平面中x轴的值代表着复数中实部a的值,y轴的值代表着虚部b的值,因此点(1,1)代表着1+i,点(7,-8)代表着7-8i。清楚这一点后,我们就可以通过一些特殊的点,来计算出其变化后的值了,例如:
变化前的点 | 对应的复数 | 进行 变化 | 变化后的点 |
(1,0) | 1 | (0.5,0) | |
(1,1) | 1+i | (0,1) | |
(1,2) | 1+2i | (-1.5,2) |
上面其实也就解释了下图中两根黄线的变化前后的缘由。至于为什么要在复平面上,应该是因为如果单纯的只是向量的平方那是没有意义的,因为向量是一个2*1的矩阵,向量的平方即为2*1的矩阵乘以2*1的矩阵,根据矩阵的乘法定义,我们知道它们无法相乘。
线性代数限制在一种特殊类型的变换上,即线性变换。如果一个变换拥有以下两个性质,我们就称它为线性的变化:
我们知道变换即为一个函数,我们假设这个函数为 ,那么站在数学的角度上,如果同一个空间中的任意两个向量 和 ,以及数域中的一个数k(可以简单的理解为k为一个实数),满足以下条件的话,函数 即为线性变换:
例如 ,代表着一个放大两倍的变换,设 , ,那么 。可得到 ,, ,满足第一条定则。设k=3,那么,,满足第二条定则。因此该变换为线性变换。
设两个基向量 , 那么任意一个向量 都有 ,当空间发生线性变换后,所有向量都会发生变换,包括我们的基向量。假设变换后,,那么变换后的即等于,能推导出这步也是因为线性变换的那两个性质。
我们把它写成矩阵的形式:
到这一步我们发现,我们输入的向量为 ,输出的向量为 ,学习了矩阵的乘法后会发现,这个结果不就是矩阵 乘以 的值。
因此线性变换的本质即是一个矩阵与向量的相乘,所有的线性变换都可以通过下面表达式来表达:
并且矩阵 的 和 即为 变化后的值, 和 即为 变化后的值。
当然了,我们也可以通过其他两个任意向量的初始值和变换后的值来求出矩阵 的值,这类似于解二元一次方程式。
设 变换后为 , 变换后为 ,可得
即可解得a,b,c,d四个的值。
同时也可验证原点不变性,因为无论a,b,c,d值为多少, 都等于 。
接下来我们来看看常见的变换及其对应的矩阵。
设缩放比例为s,那么(1,0)缩放后为(s,0),(0,1)缩放后为(0,s),所有我们的矩阵为 ,该对角阵也称为缩放矩阵。
我们也可通过上面提到的解二元一次方程式的方法来求值,例如 (1,1) 缩放后为 (s,s),(-0.5,1) 缩放后为 (-0.5s,s),可得:
可知a=s,b=0
可知c=0,d=s
如下图,缩放后的应该是情况1还是情况2呢?
从图中我们可以看出,情况1是以坐标点(2,2)为原点进行缩放,而情况2是以坐标点(0,0)为原点进行缩放,那么哪种是对的呢?
我们可以想象一下,图中的坐标系是一部手机,坐标系中的小方块是手机中的后置摄像头,有如下几种情况。
注意:后续介绍到的几种变换也都会有一样的情况,例如对称可以以y轴对称,也可以以x=1的轴对称,旋转可以以原点旋转,也可以以其他任意点旋转。但是我们后面介绍的几个变换的前提都是线性变换,因此都是以原点或者原点相关的轴进行变换。
若是沿y轴对称,那么(1,0)变为(-1,0),(0,1)不变,那么矩阵为
如下图,即为一种切变(空间中所有的竖线以与x轴的交点为中点进行倾斜)
可以发现(1,0)在切变后保持不变,(0,1)在切变后变为(a,1),a即为切变的偏移量,上图中a=1。
因此切变的矩阵为
设我们的线性空间逆时针旋转 度,通过三角函数我们可以知道,(1,0)变为,(0,1)变为
平移是一个非常特殊的变换,我们知道若一个点 (x,y) 在坐标系上平移 (i,j) 后的位置为 (x+i,y+j),但是对于向量而言,(x,y)无论怎么移动始终都是(x,y),例如两个初始向量(0,1)和(1,0)平移后依旧不变(转换为矩阵就是单位矩阵),因为向量拥有平移不变性。因此平移变换的表达式应为一个向量加上一个偏移向量,而不是矩阵与向量的相乘了,如下:
该表达式也无法用矩阵的方式来表示,因为 的两个方程式为 ax+by 和 cx+dy,无论如何都不可能等价于 x+i 和 y+i。因此平移变换不是线性变换。
理解线性变换和平移之后,仿射变换理解起来就非常的简单了。仿射变换即先做一次线性变换,然后再做一次平移变换,其表达式如下:
那么有没有什么方法,可以通过一个表达式就表达好线性变换以及反射变换呢?聪明的数学家们就此引入了齐次坐标的概念来解决这个问题。直接来看结果(站在巨人的肩膀上的我们通过结果来反推,理解起来会更加的容易),新的表达式如下:
可以发现当 和 为0时,得到的值即为 去掉1后就是线性变换的结果。当 为 时,得到的值即为 去掉1后就是平移变换的结果。这样我们就可以通过一个矩阵 来表示这些所有的变换了。例如:
我们会发现原本的向量 被变为了 ,这就是齐次坐标的意义。齐次坐标会将一个原本是n维的向量用一个n+1维向量来表示,在笛卡尔坐标系上的点 引入齐次坐标后写作了 ,例如笛卡尔坐标系上的点 可以用齐次坐标 或者 来表示,因此,与笛卡儿坐标不同,一个点可以有无限多个齐次坐标表示法。
从上面所述,也可得知,若我们有个齐次坐标 那么它对应的笛卡尔坐标即为 ,我们会发现当 w 无限接近于 0 时,x/w 和 y/w 会无限接近正无穷,因此当w=0时,该齐次坐标代表一个无限远的点。
对于w的值,我们还可以进行另一种理解(OpenGL中也使用了这样的想法),如下:
前面我们用到的是w=1的情况,若我们用w=0会出现什么结果呢?
会发现平移的操作没有了,这也表达了向量的平移不变性。这样当矩阵和点相乘后表示的还是一个点,和向量相乘后表示的依旧还是一个向量。
此外在加减法中也具有一定的意义(为了方便就不写成矩阵的形式了,这里简单的写成(x,y,w)):
前面提到齐次坐标中允许有一个无限远的点(w=0),而在3D坐标中这个是不允许的,该属性可以应用在光照的判断上。
我们知道一个点光源的无限远处是平行光,类似于太阳光,太阳是一个点光源,光线到地球后变成了平行光。因此平行光可以通过改变点光源位置向量对应的齐次坐标中的 w 的值来表示,当 w=1 时,即还在点光源的原来位置,依旧是一个点光源;当 w=0 时,即在点光源的无限远处,变为一个平行光。
复合变换即进行多次的仿射变换,例如先旋转后缩放再平移最后切变。
假设向量 进过变换A(对应矩阵 )变换B(对应矩阵 )变换C(对应矩阵 )后,我们的公式应该写为:
由于矩阵的乘法不满足交换律(),因此不能写作,因此例如先旋转后平移的变换不等价于先平移后旋转。
所有若一个向量进过 ,,... 次变换后,其公式为 。其中由于,,... 都是3*3的矩阵,所以相乘后的结果依旧是个 3*3 的矩阵。设相乘后的结果为,那么矩阵就可以代表上面所有的变换,这个思路可以应用于矩阵变换的压缩上,使用一个矩阵代表多个变换。
前面我们的旋转是以原点进行旋转,那么如果我们想以坐标系中的其他点进行旋转,变换的表达式应该是怎么样的?
如下图,便是以点(2,3)进行逆时针旋转45度的前后变换:
前面我们学习了以原点旋转以及平移的操作,那么我们可以将上面的操作进行分解,如下:
三个步骤对应的矩阵分别为:
结合起来即为:
等于:
同理在最前面缩放变换中,我们提到的缩放的情况1,即可以使用这种情况来解。
和一个变换相反的变换,我们称之为逆变换,例如逆时针旋转的变换,那它的逆变换即为顺时针旋转。
假设向量 进过一次矩阵为 变换后变为 ,然后我们可以通过矩阵为 逆变换使 变回 ,即 。由此可得 (),因此 为 的逆矩阵。
因此一个矩阵为 的变换的逆变换,对应的矩阵即为 的逆矩阵:。
例如我们逆时针旋转 度的矩阵 为:,那么他的逆变换即为顺时针旋转 度,或者说是逆时针旋转 - 度,矩阵 即为 等价于。
将他们相乘可得
由三角函数可知,,所有上面得到的值正是单位矩阵, 为 的逆矩阵。
此外我们还可以发现在旋转变换中, 正好为 的转置矩阵 ,因此通过矩阵的定义,他俩都为正交矩阵。