前言 最近在学习计算机图形学的知识,为学习WebGL打下基础,下面是闫令琪老师的《现代计算机图形学入门》课程的笔记+自己的总结与感悟。
变换在WebGL中一般是分为两种:
Modeling--模型变换 Viewing--视图变换
举几个模型变换的例子:
1、比如在一个静态模型中,摄像机在移动
2、又比如一个机器人模型在跳舞
而视图变换的一个重要例子就是投影,如图所示:在人眼的地方放一个摄像机,然后拍一张照片,就将三维的场景变成二维的照片,这中间发生的过程从三维到二维的变换就是投影。
这其中涉及的原理需要线性代数一些数学知识。线性代数是高等数学的一部分,它的研究对象是向量和矩阵。接下来说一说WebGL是怎么和向量、矩阵关联在一起的。
线性变换 线性空间 首先WebGL是一个用来在Web中生成三维图形效果的应用API。三维图形当然是在三维空间中活动的,也就是我们最熟悉并生活在其中的空间。
那么问题来了:什么是空间,或者说空间的定义是什么?,从数学上来讲,大致是“空间是一个定义某些概念,具有某些性质的集合“。比如说一个线性空间定义了范数,就形成了赋范线性空间。
那么空间的特点有什么呢?比如说三维空间里:
由很多个位置点组成的 在空间中可以定义长度、角度和方向等这些概念 空间可以存在运动(变换),也就是一个点到另一个点的移动(不是微积分意义上连续的运动) ...
其中最重要的就是第三点:空间存在运动(变换),毫不夸张的说这就是空间的本质。所以不管是三维空间,还是其他空间,都必须存在和支持符合规则的运动(变换)。比如说线性空间存在着线性变换,拓扑空间存在拓扑变换。这些变换就是对应空间中允许的运动。 所以简单来说空间是一个存在运动的集合,而变换则规定了对应空间的运动。
线性空间也是一个空间,当然也是一个对象集合,而且线性空间中的任何一个对象,都可以通过选取基和坐标的方式,表达为向量的的形式 。所以向量很是厉害,只要找到合适的基,向量可以表示线性空间里任何一个对象。
这句话怎么理解呢,我们从一片空白开始:
随便选取一个点作为原点,以此原点作两个单位正交的向量(先从二维空间开始)
所以在平面上某个点,可以这样表示:
所以整个二维平面上的点,显然都可以通过a i + b j ai + bj ai + bj 的方式来表示。用数学的语言就是整个二维平面是i , j i, j i , j 所张成的线性空间。例如:
如果i , j i, j i , j 不正交,长度也不相等,依然张成整个二维空间,只是网格有所不同
这就有了很大的启发。举个例子,比如说接下来要说的旋转变换T r o t a t e x ⃗ = x ⃗ ′ T_{rotate} \vec x = \vec x' T ro t a t e x = x ′
变换前:
变换后:
在整个变换过程中x ⃗ \vec x x 以i ⃗ , j ⃗ \vec i, \vec j i , j 为基的坐标并没有发生变换。而是i ⃗ , j ⃗ \vec i, \vec j i , j 这两个基发生了旋转,导致x ⃗ \vec x x 发生了变换。
也就是说x ⃗ = 2 i ^ + 2 j ^ \vec x = 2\hat i + 2\hat j x = 2 i ^ + 2 j ^ ,经过变换后x ⃗ ′ = 2 i ^ t + 2 j ^ t \vec x' = 2\hat i_t + 2\hat j_t x ′ = 2 i ^ t + 2 j ^ t 而将变换后的基在原来的基上表示为i ^ t \hat i_t i ^ t = [ 0 1 ] \begin{bmatrix}
{0}\\
{1}\\
\end{bmatrix} [ 0 1 ] ,j ^ t \hat j_t j ^ t = [ − 1 0 ] \begin{bmatrix}
{-1}\\
{0}\\
\end{bmatrix} [ − 1 0 ] ,所以经过变换后得到新的向量为$\vec x' =2 2 2 $\begin{bmatrix}
{0}\
{1}\
\end{bmatrix}\begin{bmatrix}
{-1}\
{0}\
\end{bmatrix}\begin{bmatrix}
{-2}\
{2}\
\end{bmatrix}$。将 \hat i_t和 和 和 \hat j_t放在一起变成一个 2 x 2 的矩阵 放在一起变成一个2 x 2的矩阵 放在一起变成一个 2 x 2 的矩阵 $\begin{bmatrix}
{0}&{-1}\
{1}&{0}\
\end{bmatrix}$其实就是[ \hat i_t, $\hat j_t ] = T r o t a t e T_{rotate} T ro t a t e 。
所以T r o t a t e T_{rotate} T ro t a t e 实际上是改变了基,其中x ⃗ = a i ⃗ + b j ⃗ , x ⃗ ′ = a i ⃗ ′ + b j ⃗ ′ \vec x = a\vec i + b\vec j, \vec x' = a\vec i' + b\vec j' x = a i + b j , x ′ = a i ′ + b j ′ ,通过T r o t a t e T_{rotate} T ro t a t e 把i ⃗ — i ⃗ ′ , j ⃗ — j ⃗ ′ \vec i — \vec i', \vec j — \vec j' i — i ′ , j — j ′
T r o t a t e T_{rotate} T ro t a t e 就是空间中的运动描述,表述为一个矩阵。
所以说,在线性空间中,当选定一组基后,不仅可以用向量来描述空间中的对象,而且还能用矩阵描述该空间的任何一个运动(变换)。而使某个对象发生对应运动的方法,就是用代表运动的矩阵,乘以表示对象的向量。
这就是学习WebGL要先学习向量和矩阵的原因。
向量 线性代数中最基础、最根源的组成部分就是向量。
向量是高中的数学知识,相信大家都学习过,这里不再啰嗦,只帮大家回忆一下知识。
1、向量 :既有大小又有方向的量,记为A B ⃗ \vec {AB} A B 或者a ⃗ \vec a a ,在物理上由称为矢量。向量常用有向线段来表示,但也不能说向量就是有向线段,因为向量是“自由的”,可以平移等;而有向线段有固定的起点和终点,不能随便移动。
2、向量的模 :向量的大小又叫向量的模,指的是:向量的有向线段的长度。记为:∣ A B ⃗ ∣ |\vec {AB}| ∣ A B ∣ 或者∣ a ⃗ ∣ |\vec a| ∣ a ∣ 。向量本身不能比大小,只有向量的模才能比大小。
3、零向量 :模为0的向量叫零向量,记为0 ⃗ \vec 0 0 ,零向量的特点是方向是任意的,也就是说与所有向量都平行
4、单位向量 :模为1个单位长度的非零向量叫单位向量,比如在二维坐标系中,指向正右方的称为i ^ \hat i i ^ ,指向正上方的称为j ^ \hat j j ^ 。i ^ \hat i i ^ 和j ^ \hat j j ^ 被称为二维坐标系的基。
5、向量的表示 :根据这两个特殊的基向量构成的坐标系中任一向量a ⃗ \vec a a 都可以表示为\vec a = x\vec i + y\vec j = $ $ \begin{bmatrix}
{x}\
{y}\
\end{bmatrix}$,此时 |\vec a| = \sqrt {x^2 + y^2} sin\theta$。记住每当用数字描述向量时,它都依赖于正在使用的基。
向量的线性运算 1、向量加法 :
从图中可以得出: u ⃗ + v ⃗ = w ⃗ = ( u x + v x , u y + v y ) \vec u + \vec v = \vec w = (u_x + v_x, u_y + v_y) u + v = w = ( u x + v x , u y + v y )
2、向量减法 :
举一反三,减法如下:u ⃗ = w ⃗ − v ⃗ = ( w x − v x , w y − v y ) \vec u = \vec w - \vec v = (w_x - v_x, w_y - v_y) u = w − v = ( w x − v x , w y − v y )
向量的加减法的运算法则:
3、向量点乘
已知两个非零向量a ⃗ \vec a a 与b ⃗ \vec b b 和它们的夹角θ \theta θ ,则$\vec a * \vec b = |\vec a| * |\vec b| cos\theta $。
证明,利用余弦定理:∣ C ⃗ ∣ 2 = ∣ A ⃗ ∣ 2 + ∣ B ⃗ ∣ 2 − 2 ∣ A ∣ ∣ B ∣ c o s θ |\vec C|^2 = |\vec A|^2 + |\vec B|^2 - 2|A||B|cos \theta ∣ C ∣ 2 = ∣ A ∣ 2 + ∣ B ∣ 2 − 2∣ A ∣∣ B ∣ cos θ
另外有:∣ C ⃗ ∣ 2 = C ⃗ ∗ C ⃗ = ( A ⃗ − B ⃗ ) ∗ ( A ⃗ − B ⃗ ) = A ⃗ ∗ A ⃗ + B ⃗ ∗ B ⃗ − 2 A ⃗ ∗ B ⃗ |\vec C|^2 = \vec C * \vec C = (\vec A - \vec B) * (\vec A - \vec B) = \vec A * \vec A + \vec B * \vec B - 2\vec A * \vec B ∣ C ∣ 2 = C ∗ C = ( A − B ) ∗ ( A − B ) = A ∗ A + B ∗ B − 2 A ∗ B
比较两式可得:A ⃗ ∗ B ⃗ = ∣ A ⃗ ∣ ∣ B ⃗ ∣ c o s θ \vec A * \vec B = |\vec A||\vec B|cos\theta A ∗ B = ∣ A ∣∣ B ∣ cos θ 符合交换律、分配律,不符合结合律 当角度为90度时,两个向量的点乘为0,这两个向量正交。 向量点乘在笛卡尔坐标系中定义就更加简单: 对应元素相乘相加a ⃗ ∗ b ⃗ = ∑ x i y i \vec a * \vec b = \sum{x_i y_i} a ∗ b = ∑ x i y i 。比如两个向量a ⃗ \vec a a 与b ⃗ \vec b b :
1、在二维里,a ⃗ ∗ b ⃗ \vec a * \vec b a ∗ b = [ x a y a ] \begin{bmatrix}
{x_a}\\
{y_a}\\
\end{bmatrix} [ x a y a ] * [ x b y b ] \begin{bmatrix}
{x_b}\\
{y_b}\\
\end{bmatrix} [ x b y b ] = x a x b + y a y b x_ax_b + y_ay_b x a x b + y a y b
2、在三维里,a ⃗ ∗ b ⃗ \vec a * \vec b a ∗ b = [ x a y a z a ] \begin{bmatrix}
{x_a}\\
{y_a}\\
{z_a}\\
\end{bmatrix} ⎣ ⎡ x a y a z a ⎦ ⎤ * [ x b y b z b ] \begin{bmatrix}
{x_b}\\
{y_b}\\
{z_b}\\
\end{bmatrix} ⎣ ⎡ x b y b z b ⎦ ⎤ = x a x b + y a y b + z a z b x_ax_b + y_ay_b + z_az_b x a x b + y a y b + z a z b
点乘的意义在图形学中有两个重要的作用:
找到两个向量间的夹角或者余弦夹角 得出一个向量在另一个向量中的投影 比如,有一束光垂直着向量a ⃗ \vec a a 照射,向量b ⃗ \vec b b 自然会在得出一个阴影在向量a ⃗ \vec a a 上,这就是b ⃗ \vec b b 在a ⃗ \vec a a 上的投影
如图所示,怎么计算这个b ⃗ \vec b b 在a ⃗ \vec a a 上的投影-称为b τ ⃗ \vec {b_{\tau}} b τ (图中的符号打不出来),看图可以得出以下几个结论:
b τ ⃗ \vec {b_{\tau}} b τ 的方向一定和a ⃗ \vec a a 是一样的 用a表示a ⃗ \vec a a 单位向量,那么b τ ⃗ = k a \vec {b_{\tau}} = ka b τ = ka b τ ⃗ \vec {b_{\tau}} b τ 与b ⃗ \vec b b 组成一个直角三角型
根据上述结论可以得出:k = ∣ b τ ⃗ ∣ = ∣ b ⃗ ∣ c o s θ k = |\vec {b_{\tau}}| = |\vec b|cos\theta k = ∣ b τ ∣ = ∣ b ∣ cos θ ,又由于c o s θ = a ⃗ ∗ b ⃗ ∣ a ⃗ ∣ ∗ ∣ b ⃗ ∣ cos \theta = \frac{\vec a * \vec b}{|\vec a| * |\vec b|} cos θ = ∣ a ∣ ∗ ∣ b ∣ a ∗ b
得出k = a ⃗ ∗ b ⃗ ∣ a ⃗ ∣ k = \frac{\vec a * \vec b}{|\vec a|} k = ∣ a ∣ a ∗ b 点乘还能给出一个很重要的信息,两向量的方向信息
如图所示,以向量a ⃗ \vec a a 为起点,形成一个圆,这个圆分为两部分:上半部分与下半部分。向量b ⃗ \vec b b 的是落在上半部分的,就可以说向量a ⃗ \vec a a 和向量b ⃗ \vec b b 算是方向基本一致。否则如向量c ⃗ \vec c c 与向量a ⃗ \vec a a 方向基本相反。这就是点乘可以告诉的信息。
4、向量叉乘
这种乘法的计算结果是一个向量:a ⃗ \vec a a x b ⃗ = c ⃗ \vec b = \vec c b = c ,向量c ⃗ \vec c c 的大小是∣ c ⃗ ∣ = ∣ a ⃗ ∣ ∣ b ⃗ ∣ s i n θ |\vec c| = |\vec a||\vec b| sin \theta ∣ c ∣ = ∣ a ∣∣ b ∣ s in θ ,向量c ⃗ \vec c c 的方向则是由“右手法则”规定:右手的四个手指指向向量a ⃗ \vec a a ,然后四指弯曲向第二个向量b ⃗ \vec b b 的方向,大拇指方向就是向量c ⃗ \vec c c 的方向。
应用这个定则会发现,a ⃗ \vec a a x b ⃗ \vec b b 正好与b ⃗ \vec b b x a ⃗ \vec a a 方向相反,所以向量的叉乘并不满足交换律。
向量叉乘可以建立三维空间中的直角坐标系。比如说给定x轴与y轴,用x轴叉乘y轴就能得到x轴。举一反三用y轴叉乘z轴就能得到x轴
向量叉乘也可以用代数表示,如果向量a ⃗ = \vec a = a = [ x a y a z a ] \begin{bmatrix}
{x_a}\\
{y_a}\\
{z_a}\\
\end{bmatrix} ⎣ ⎡ x a y a z a ⎦ ⎤ , 向量b ⃗ = \vec b = b = [ x b y b z b ] \begin{bmatrix}
{x_b}\\
{y_b}\\
{z_b}\\
\end{bmatrix} ⎣ ⎡ x b y b z b ⎦ ⎤ ,那么a ⃗ \vec a a x b ⃗ = \vec b = b = [ y a z b − y b z a z a x b − x a z b x a y b − y a x b ] \begin{bmatrix}
{y_az_b - y_bz_a}\\
{z_ax_b - x_az_b}\\
{x_ay_b - y_ax_b}\\
\end{bmatrix} ⎣ ⎡ y a z b − y b z a z a x b − x a z b x a y b − y a x b ⎦ ⎤ = A ∗ b ⃗ A * \vec b A ∗ b = [ 0 − z a y a z a 0 − x a − y a x a 0 ] \begin{bmatrix}
{0}&{-z_a}&{y_a}\\
{z_a}&{0}&{-x_a}\\
{-y_a}&{x_a}&{0}\\
\end{bmatrix} ⎣ ⎡ 0 z a − y a − z a 0 x a y a − x a 0 ⎦ ⎤ [ x b y b z b ] \begin{bmatrix}
{x_b}\\
{y_b}\\
{z_b}\\
\end{bmatrix} ⎣ ⎡ x b y b z b ⎦ ⎤
叉乘在图形学的作用
判定左和右 判定内与外
比如说左边的图所示,想要知道向量b ⃗ \vec b b 在向量a ⃗ \vec a a 的左边还是右边,或者说向量a ⃗ \vec a a 向逆时针旋转还是顺时针旋转。
如果a ⃗ \vec a a x b ⃗ \vec b b 的结果是正的,那就说明b ⃗ \vec b b 在a ⃗ \vec a a 的左侧。 如右图所示,判定p点是否在三角形的内部。如果
A ⃗ B \vec AB A B x A ⃗ P \vec AP A P 得出的结果是A ⃗ P \vec AP A P 在A ⃗ B \vec AB A B 左侧 B ⃗ C \vec BC B C x B ⃗ P \vec BP B P 得出的结果是B ⃗ P \vec BP B P 在B ⃗ C \vec BC B C 左侧 C ⃗ A \vec CA C A x C ⃗ P \vec CP C P 得出的结果是C ⃗ P \vec CP C P 在C ⃗ A \vec CA C A 左侧
所以就可以说p点在三角形的内部,这是光栅化的基础,要判定某个三角形覆盖了哪些像素,就得判断这些像素是否在三角形的内部。 矩阵 矩阵的定义如上所说的,它是描述空间中任何一个运动,也就是变换。
矩阵表示为[ 1 3 5 2 0 4 ] \begin{bmatrix}
{1}&{3}\\
{5}&{2}\\
{0}&{4}\\
\end{bmatrix} ⎣ ⎡ 1 5 0 3 2 4 ⎦ ⎤ 这称为(3 x 2)的矩阵,3行2列。
矩阵的乘法:只有第一个矩阵的列数与第二个矩阵的行数相同,相乘才有意义(M x N)(N x P) = (M x P)
举例:[ 1 3 5 2 0 4 ] \begin{bmatrix}
{1}&{3}\\
{5}&{2}\\
{0}&{4}\\
\end{bmatrix} ⎣ ⎡ 1 5 0 3 2 4 ⎦ ⎤ * [ 3 6 9 4 2 7 8 3 ] \begin{bmatrix}
{3}&{6}&{9}&{4}\\
{2}&{7}&{8}&{3}\\
\end{bmatrix} [ 3 2 6 7 9 8 4 3 ] = [ 9 27 33 13 19 44 61 26 8 28 32 12 ] \begin{bmatrix}
{9}&{27}&{33}&{13}\\
{19}&{44}&{61}&{26}\\
{8}&{28}&{32}&{12}\\
\end{bmatrix} ⎣ ⎡ 9 19 8 27 44 28 33 61 32 13 26 12 ⎦ ⎤
结果是这样算的,比如结果中第一行第四列的13,就是取第一个矩阵的第一行[1 3]和第二个矩阵的第四列[4 3]相乘相加1 ∗ 4 + 3 ∗ 3 1*4 + 3*3 1 ∗ 4 + 3 ∗ 3 得到的13。
矩阵符合结合律和分配律,不符合交换律。
那么矩阵与向量怎么结合在一样?那就是将向量表示为一个[N x 1]的矩阵,这样矩阵就能与向量相乘。
比如在二维中将一个向量按y轴做一个对称变换:[ − 1 0 0 1 ] \begin{bmatrix}
{-1}&{0}\\
{0}&{1}\\
\end{bmatrix} [ − 1 0 0 1 ] [ x y ] \begin{bmatrix}
{x}\\
{y}\\
\end{bmatrix} [ x y ] = [ − x y ] \begin{bmatrix}
{-x}\\
{y}\\
\end{bmatrix} [ − x y ]
矩阵还有几个性质:转秩
向量的点乘和叉乘都可以表示为矩阵的乘法
模型变换 先介绍一下什么是线性变换--linear transformation:
事实上变换只是函数的一种说法;接收一个数,并输出对应的结果,在线性代数的情况下,这个数指的就是一个向量。就变成了接收一个向量并输出一个向量。使用变换这个名词大概是以特定的方式来可视化这一输入-输出关系。似乎在说向量通过运动变成另一个向量。
如果一个变换具有以下两条性质,就可以称它为线性变换:
直线在变换后仍然保持为直线,不能弯曲 原点必须保持固定
总的来说,线性变换可以看作是保持网格线平行且等距分布 的变换。 Scale--缩放变换
如图所示:左边的图形经过S 0.5 S_{0.5} S 0.5 的缩放变成右边的图形,因为是在二维坐标系中,所以具体来说就是x轴和y轴都缩放0.5倍。
方程组如下 \begin{cases}
x^{'}=sx\\
y^{'}=sy\\
用矩阵的方式表示[ x ′ y ′ ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
\end{bmatrix} [ x ′ y ′ ] = [ s 0 0 s ] \begin{bmatrix}
{s}&{0}\\
{0}&{s}\\
\end{bmatrix} [ s 0 0 s ] [ x y ] \begin{bmatrix}
{x}\\
{y}\\
\end{bmatrix} [ x y ]
如图所示,如果x轴缩放0.5倍y轴不变,那么表达式就变成了[ x ′ y ′ ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
\end{bmatrix} [ x ′ y ′ ] = [ s x 0 0 s y ] \begin{bmatrix}
{s_{x}}&{0}\\
{0}&{s_{y}}\\
\end{bmatrix} [ s x 0 0 s y ] [ x y ] \begin{bmatrix}
{x}\\
{y}\\
\end{bmatrix} [ x y ]
缩放变换有一个特殊的变换叫做反射变换
如图所示,图形相对于y轴做一个对称变换,也就是x轴取反,y轴不变: [ x ′ y ′ ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
\end{bmatrix} [ x ′ y ′ ] = [ − 1 0 0 1 ] \begin{bmatrix}
{-1}&{0}\\
{0}&{1}\\
\end{bmatrix} [ − 1 0 0 1 ] [ x y ] \begin{bmatrix}
{x}\\
{y}\\
\end{bmatrix} [ x y ]
Shear--切变
如图所示:边长都为1的正方形变换为了一个平行四边形,对比左右图型可以发现:y轴坐标都没有发生变化,图形的下边x轴没有发生变化,只有上边的x轴都加上a,所以中间的点的x左边都要加上ay
列出方程组
\begin{cases}
x^{'}=x + ay\\
y^{'}=y\\
用矩阵的方式表示[ x ′ y ′ ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
\end{bmatrix} [ x ′ y ′ ] = [ 1 a 0 1 ] \begin{bmatrix}
{1}&{a}\\
{0}&{1}\\
\end{bmatrix} [ 1 0 a 1 ] [ x y ] \begin{bmatrix}
{x}\\
{y}\\
\end{bmatrix} [ x y ]
Rotate--旋转变换 为了简化旋转变换,先作出两个定义
只要不作具体说明,认为都是围绕着原点(0,0)旋转 只要不作具体的旋转方向,都认为是逆时针方向
如图所示边长为1的正方形,围绕原点(0,0)旋转,旋转θ \theta θ 角度。A点从(1, 0)到A ′ ( c o s θ , s i n θ ) A^{'}(cos \theta,sin \theta) A ′ ( cos θ , s in θ ) ,B点从(0, 1)到B ′ ( − s i n θ , c o s θ ) B^{'}(-sin\theta, cos\theta) B ′ ( − s in θ , cos θ ) 所以可以列出方程组
\begin{cases}
x^{'}=cos\theta x - sin\theta y\\
y^{'}=sin\theta x + cos\theta y\\
得出矩阵[ x ′ y ′ ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
\end{bmatrix} [ x ′ y ′ ] = [ c o s θ − s i n θ s i n θ c o s θ ] \begin{bmatrix}
{cos{\theta}}&{-sin{\theta}}\\
{sin{\theta}}&{cos{\theta}}\\
\end{bmatrix} [ cos θ s in θ − s in θ cos θ ] [ x y ] \begin{bmatrix}
{x}\\
{y}\\
\end{bmatrix} [ x y ]
线性变换本质 从上面的几个例子中得出,在二维中,从A点移动到A ′ A^{'} A ′ 点都可以用列出一个方程组求解
\begin{cases}
x^{'}=ax + by\\
y^{'}=cx + dy\\
而这些方程组都可以表达为矩阵的形式:[ x ′ y ′ ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
\end{bmatrix} [ x ′ y ′ ] = [ a b c d ] \begin{bmatrix}
{a}&{b}\\
{c}&{d}\\
\end{bmatrix} [ a c b d ] [ x y ] \begin{bmatrix}
{x}\\
{y}\\
\end{bmatrix} [ x y ]
写成更一般的公式:x ⃗ ′ = M x ⃗ \vec x^{'} = M\vec x x ′ = M x 。在几何中的意义就是,通过M让x ⃗ \vec x x 运动到x ⃗ ′ \vec x^{'} x ′ ,这也认证了前面的结论。
Translation--平移变换 经过上面的介绍,平移变换就显得非常简单。物体平移t x t_x t x ,t y t_y t y ,从几何上来说就是x轴坐标都加上t x t_x t x ,y轴坐标都加上t y t_y t y 。
方程组求解
\begin{cases}
x^{'}=x + t_x\\
y^{'}=y + t_y\\
因为t x t_x t x ,t y t_y t y 都是常数,所以这方程组无法写成一般的x ⃗ ′ = M x ⃗ \vec x^{'} = M\vec x x ′ = M x 的公式,只能写成x ⃗ ′ = M x ⃗ + t \vec x^{'} = M\vec x + t x ′ = M x + t 表示为矩阵形式就是[ x ′ y ′ ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
\end{bmatrix} [ x ′ y ′ ] = [ a b c d ] \begin{bmatrix}
{a}&{b}\\
{c}&{d}\\
\end{bmatrix} [ a c b d ] [ x y ] \begin{bmatrix}
{x}\\
{y}\\
\end{bmatrix} [ x y ] + [ t x t y ] \begin{bmatrix}
{t_{x}}\\
{t_{y}}\\
\end{bmatrix} [ t x t y ]
所以可以得出一个结论,平移变换不属于线性变换 。很吃惊,平移怎么不是线性变换呢,因为在线性空间中是用向量来表示物体的,向量具有平移不变性,也就是说一个向量移动到某一个点但方向和大小都没有发生变化,就表示这个向量根本没有变换。但数学家们不满足于单独将平移当作特殊处理,仍然希望将其与线性变换统一处理。所以引入了齐次坐标 。
齐次坐标 数学家发现,通过将坐标都增加一个纬度,比如说在二维中
点表示为(x, y, 1) 向量表示为(x, y, 0)
就可以将平移表示为:[ x ′ y ′ w ′ ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
{w^{'}}\\
\end{bmatrix} ⎣ ⎡ x ′ y ′ w ′ ⎦ ⎤ = [ 1 0 t x 0 1 t y 0 0 1 ] \begin{bmatrix}
{1}&{0}&{t_{x}}\\
{0}&{1}&{t_{y}}\\
{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ 1 0 0 0 1 0 t x t y 1 ⎦ ⎤ [ x + t x y + t y 1 ] \begin{bmatrix}
{x+t_{x}}\\
{y+t_{y}}\\
{1}
\end{bmatrix} ⎣ ⎡ x + t x y + t y 1 ⎦ ⎤ 这就能写成x ⃗ ′ = M x ⃗ \vec x^{'} = M\vec x x ′ = M x 这种形式了。
而且引入齐次坐标将点与向量分开表示了,这是因为如上面所讲的,向量具有平移不变性。而上面公式中经过平移,x变成了x + t x x+t_x x + t x ,y变成了y + t y y+t_y y + t y ,这在向量里是不允许的。所以向量表示为(x, y, 0)就是保护它的平移不变性
加上了齐次坐标之后,就可以将线性变换与平移合到一起,数学家将这个变换称为Affine(仿射变换)= linear tranformation + translation。齐次坐标形式为:[ x ′ y ′ w ′ ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
{w^{'}}\\
\end{bmatrix} ⎣ ⎡ x ′ y ′ w ′ ⎦ ⎤ = [ a b t x c d t y 0 0 1 ] \begin{bmatrix}
{a}&{b}&{t_{x}}\\
{c}&{d}&{t_{y}}\\
{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ a c 0 b d 0 t x t y 1 ⎦ ⎤ [ x + t x y + t y 1 ] \begin{bmatrix}
{x+t_{x}}\\
{y+t_{y}}\\
{1}
\end{bmatrix} ⎣ ⎡ x + t x y + t y 1 ⎦ ⎤
上次介绍的线性变换都改为以下形式:
1、Scale:S ( s x , s y ) S({s_x, s_y}) S ( s x , s y ) = [ s x 0 0 0 s y 0 0 0 1 ] \begin{bmatrix}
{s_{x}}&{0}&{0}\\
{0}&{s_{y}}&{0}\\
{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ s x 0 0 0 s y 0 0 0 1 ⎦ ⎤
2、Rotation:R ( θ R(\theta R ( θ )$ = [ c o s θ − s i n θ 0 s i n θ c o s θ 0 0 0 1 ] \begin{bmatrix}
{cos{\theta}}&{-sin{\theta}}&{0}\\
{sin{\theta}}&{cos{\theta}}&{0}\\
{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ cos θ s in θ 0 − s in θ cos θ 0 0 0 1 ⎦ ⎤
3、Translation:T ( t x , t y ) T(t_x, t_y) T ( t x , t y ) = [ 1 0 t x 0 1 t y 0 0 1 ] \begin{bmatrix}
{1}&{0}&{t_{x}}\\
{0}&{1}&{t_{y}}\\
{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ 1 0 0 0 1 0 t x t y 1 ⎦ ⎤
变换组合
如图所示,左边的图怎么变换到右边的图呢?很简单就是平移加旋转,那应该是先平移在旋转还是先旋转再平移?
如果是先平移在旋转:
会发现不对,结果并不是变换后的结果
所以是先旋转再平移:
所以得出两个结论
一个复杂的变换能分解成基础变换的组合 基础变换的顺序是至关重要的
这也反应出矩阵不符合交换律 所以上述变换组合写成矩阵形式: T ( 1 , 0 ) R 45 T_{(1, 0)} R_{45} T ( 1 , 0 ) R 45 [ x y 1 ] \begin{bmatrix}
{x}\\
{y}\\
{1}
\end{bmatrix} ⎣ ⎡ x y 1 ⎦ ⎤ = [ 1 0 1 0 1 0 0 0 1 ] \begin{bmatrix}
{1}&{0}&{1}\\
{0}&{1}&{0}\\
{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ 1 0 0 0 1 0 1 0 1 ⎦ ⎤ [ c o s 45 − s i n 45 0 s i n 45 c o s 45 0 0 0 1 ] \begin{bmatrix}
{cos45}&{-sin45}&{0}\\
{sin45}&{cos45}&{0}\\
{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ cos 45 s in 45 0 − s in 45 cos 45 0 0 0 1 ⎦ ⎤ [ x y 1 ] \begin{bmatrix}
{x}\\
{y}\\
{1}
\end{bmatrix} ⎣ ⎡ x y 1 ⎦ ⎤
注意顺序,顺序是从右到左的顺序相乘的,这是因为向量在最右边,依次向左乘上变换矩阵
三维变换 从二维变换推广到三维变换很容易,先看齐次坐标的定义
点表示为(x, y, z, 1) 向量表示为(x, y, z, 0)
可以使用(4 x 4)的矩阵形式表示三维的线性变换:[ x ′ y ′ z ′ 1 ] \begin{bmatrix}
{x^{'}}\\
{y^{'}}\\
{z^{'}}\\
{1}
\end{bmatrix} ⎣ ⎡ x ′ y ′ z ′ 1 ⎦ ⎤ = [ a b c t x d e f t y g h i t z 0 0 0 1 ] \begin{bmatrix}
{a}&{b}&{c}&{t_{x}}\\
{d}&{e}&{f}&{t_{y}}\\
{g}&{h}&{i}&{t_{z}}\\
{0}&{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ a d g 0 b e h 0 c f i 0 t x t y t z 1 ⎦ ⎤ [ x y z 1 ] \begin{bmatrix}
{x}\\
{y}\\
{z}\\
{1}
\end{bmatrix} ⎣ ⎡ x y z 1 ⎦ ⎤ 三维变换公式:
1、Scale:S ( s x , s y , s z ) S({s_x, s_y, s_z}) S ( s x , s y , s z ) = [ 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} ⎣ ⎡ s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ⎦ ⎤
2、Translation:T ( t x , t y ) T(t_x, t_y) T ( t x , t y ) = [ 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ] \begin{bmatrix}
{1}&{0}&{0}&{t_{x}}\\
{0}&{1}&{0}&{t_{y}}\\
{0}&{0}&{1}&{t_z}\\
{0}&{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ 1 0 0 0 0 1 0 0 0 0 1 0 t x t y t z 1 ⎦ ⎤
最复杂的就是旋转了,对于任意的旋转是非常困难的,所以先从简单旋转开始分析:
(1):围绕x轴旋转,也就是说x轴坐标不变,y轴与z轴的坐标在做旋转变换,反应到矩阵中:
R x ( θ ) R_x(\theta) R x ( θ ) = [ 1 0 0 0 0 c o s θ − s i n θ 0 0 s i n θ c o s θ 0 0 0 0 1 ] \begin{bmatrix}
{1}&{0}&{0}&{0}\\
{0}&{cos{\theta}}&{-sin{\theta}}&{0}\\
{0}&{sin{\theta}}&{cos{\theta}}&{0}\\
{0}&{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ 1 0 0 0 0 cos θ s in θ 0 0 − s in θ cos θ 0 0 0 0 1 ⎦ ⎤
(2):围绕y轴旋转,同理y轴坐标不变,z轴和x轴坐标做旋转
R y ( θ ) R_y(\theta) R y ( θ ) = [ c o s θ 0 s i n θ 0 0 1 0 0 − s i n θ 0 c o s θ 0 0 0 0 1 ] \begin{bmatrix}
{cos{\theta}}&{0}&{sin{\theta}}&{0}\\
{0}&{1}&{0}&{0}\\
{-sin{\theta}}&{0}&{cos{\theta}}&{0}\\
{0}&{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ cos θ 0 − s in θ 0 0 1 0 0 s in θ 0 cos θ 0 0 0 0 1 ⎦ ⎤
(3):围绕z轴旋转
R z ( θ ) R_z(\theta) R z ( θ ) = [ c o s θ − s i n θ 0 0 s i n θ c o s θ 0 0 0 0 1 0 0 0 0 1 ] \begin{bmatrix}
{cos{\theta}}&{-sin{\theta}}&{0}&{0}\\
{sin{\theta}}&{cos{\theta}}&{0}&{0}\\
{0}&{0}&{1}&{0}\\
{0}&{0}&{0}&{1}\\
\end{bmatrix} ⎣ ⎡ cos θ s in θ 0 0 − s in θ cos θ 0 0 0 0 1 0 0 0 0 1 ⎦ ⎤
复杂的变换都可以分解成基础变换的组合,所以对三维空间中任意的旋转可以分解为对x轴、y轴、z轴旋转的组合:R x y z ( α , β , γ ) = R x ( α ) R y ( β ) R z ( γ ) R_{xyz}(\alpha,\beta,\gamma) = R_x(\alpha)R_y(\beta)R_z(\gamma) R x yz ( α , β , γ ) = R x ( α ) R y ( β ) R z ( γ )
总结成为罗德里格斯旋转公式: