Computer Graphics:下面简称CG,本节有一些不是很懂,直接没摘抄了。如齐次坐标的定义要搞懂。后面要加深学习的话参见CG的专业书籍把
教授推荐书目:<Computer Graphics: Principles and Practices> by Foley,Van Dam, Feiner, and Hughes (Addison-Wesley, 1995).一些参考是notes by Ronald Goldman and by Tony DeRose.
在CG当中,图片被移动、大小改变、3维的被投影为2维等等。这些操作都是通过矩阵完成的,但是这些矩阵的形状是很令人惊讶的。
三维空间当中的变换是由4-4矩阵完成的 。你可能会以为是3-3的矩阵才对。需要4-4,是因为,4个关键操作的其中1个,不能由3-3的矩阵乘法来完成,下面是4个关键操作
平移:把原点变换到其他一个点 P 0 = ( x 0 , y 0 , z 0 ) P_0= (x_0,y_0,z_0) P 0 = ( x 0 , y 0 , z 0 ) (Translation :shift the origin to another point P o = ( x o , Y o , z o ) P_o = (x_o, Y_o, z_o) P o = ( x o , Y o , z o )
缩放:所有方向都伸缩因子c,或者不同方向的伸缩因子是c 1 , c 2 , c 3 c_1,c_2,c_3 c 1 , c 2 , c 3 (Rescaling:by c in all directions or by different factors c 1 , c 2 , c 3 c_1, c_2, c_3 c 1 , c 2 , c 3 )
旋转:绕着经过原点的轴或者经过某个P 0 P_0 P 0 点的轴旋转(Rotation:around an axis through the origin or an axis through P o P_o P o )
投影:投影到经过原点或P 0 P_0 P 0 点的平面(Projection:onto a plane through the origin or a plane through Po).
首先注意2点:
CG当中使用的是齐次坐标(homogeneous coordinates) ,如点 (x,y,z)的的齐次坐标是 (x,y,z,1),也就是在第4维添加1。
重要:CG当中是使用行向量。所以是 行*矩阵,而不是 矩阵*列
1 平移(Translation)
平移是最简单的,只需要把v 0 = ( x 0 , y 0 , z 0 ) v_0=(x_0,y_0,z_0) v 0 = ( x 0 , y 0 , z 0 ) 加到每1个向量上,这时沿着向量 v 0 v_0 v 0 平移(shift)这个3维空间。但这不是线性的!(sp:可参见 <01-07>) 。没有任何3-3的矩阵可以移动原点。所以我们把原点的坐标设为 (0,0,0,1),这就是为什么矩阵是4-4的。
原点会被移动到 ( x 0 , y 0 , z 0 ) (x_0,y_0,z_0) ( x 0 , y 0 , z 0 ) ,向量 v 0 v_0 v 0 被加到R 3 R^3 R 3 下的每一个点。使用齐次坐标,下面4-4的矩阵T会把整个空间平移v 0 v_0 v 0
Translation Matrix: T = [ 1 0 0 0 0 1 0 0 0 0 1 0 x 0 y 0 z 0 1 ] \text{Translation Matrix:}\quad T = \left[ \begin{array} { l l l l } 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ x _ { 0 } & y _ { 0 } & z _ { 0 } & 1 \end{array} \right] Translation Matrix: T = 1 0 0 x 0 0 1 0 y 0 0 0 1 z 0 0 0 0 1
可快速检查一下 [ 0 0 0 1 ] T = ( x 0 , y 0 , z 0 , 1 ) \left[\begin{matrix} 0 & 0 & 0 & 1 \\\end{matrix} \right] T = (x_0,y_0,z_0,1) [ 0 0 0 1 ] T = ( x 0 , y 0 , z 0 , 1 ) .
为了把三维点 (0,0,0) 和 (x,y,z) 移动 v 0 v_0 v 0 ,首先切换到齐次坐标 ( 0 , 0 , 0 , 1 ) ; ( x , y , z , 1 ) (0,0,0,1);(x,y,z,1) ( 0 , 0 , 0 , 1 ) ; ( x , y , z , 1 ) ,然后乘以T:行向量乘以T,结果还是行向量。而且任何向量 v 移动到都是 v + v 0 v+v_0 v + v 0 :[ x y z 1 ] T = ( x + x 0 , y + y 0 , z + z 0 , 1 ) \left[\begin{matrix} x & y & z & 1 \\\end{matrix} \right] T = (x+x_0,y+y_0,z+z_0,1) [ x y z 1 ] T = ( x + x 0 , y + y 0 , z + z 0 , 1 )
2 缩放(Scaling)
如果要把图片缩放为90%大小,在线代的标准做法是用 0.9 乘以单位矩阵 I 得到的矩阵 S L S_L S L 来代表缩放。S L S_L S L 对于平面是2-2的,三维是3-3的。但在CG,因为使用齐次坐标,所以矩阵会多1行1列,下面用S S S 表示CG下的缩放矩阵:
Rescale a plane to 0.9: S = [ .9 .9 1 ] Rescale a solid to c: S = [ c 0 0 0 0 c 0 0 0 0 c 0 0 0 0 1 ] \text { Rescale a plane to 0.9: } \quad S = \left[ \begin{array} { l l l } .9 & & \\ & .9 & \\ & & 1 \end{array} \right]
\\[4ex]
\text { Rescale a solid to c: } \quad S = \left[ \begin{array} { l l l l } c & 0 & 0 & 0 \\ 0 & c & 0 & 0 \\ 0 & 0 & c & 0 \\ 0 & 0 & 0 & 1 \end{array} \right] Rescale a plane to 0.9: S = .9 .9 1 Rescale a solid to c: S = c 0 0 0 0 c 0 0 0 0 c 0 0 0 0 1
所以要注意,线代的 S L S_L S L 是 CI,但在CG,S S S 不是 cI,S S S 右下角一定是1 。如 [x,y,1] 乘以S,才能得到齐次坐标下的正确答案。原点保持不变,因为 [0,0,1]S = [0,0,1]。
如果不同方向伸缩因子不一样,如果需要把x,y,z方向变为 c 1 , c 2 , c 3 c_1,c_2,c_3 c 1 , c 2 , c 3 ,此时的S矩阵如下
S = [ c 1 c 2 c 3 1 ] S = \left[ \begin{array} { c c c c } c _ { 1 } & & & \\ & c _ { 2 } & & \\ & & c _ { 3 } & \\ & & & 1 \end{array} \right] S = c 1 c 2 c 3 1
总结 :缩放矩阵 S 和平移矩阵 T 大小是一样的,它们可以乘起来! 对于向量v
先平移,后缩放,是 vTS
先缩放,后皮影,是 vST
注意1,2是不等价 的! R 3 R^3 R 3 下的点 ( x , y , z ) (x,y,z) ( x , y , z ) 的齐次坐标是 P 3 P^3 P 3 下的 ( x , y , z , 1 ) (x,y,z,1) ( x , y , z , 1 ) .P 3 P^3 P 3 是一个投影空间(Projective space),注意 P 3 P^3 P 3 和R 4 R^4 R 4 不一样,它还是三维的。
CG使用的是仿射变换(affine transformation),也就是:线性变换+平移(shitf)。P 3 P^3 P 3 下的仿射变换T,是由1个多了额外1列的4-4的矩阵执行的:
A = [ a 11 a 12 a 13 0 a 21 a 22 a 23 0 a 31 a 32 a 33 0 a 41 a 42 a 43 1 ] = [ T ( 1 , 0 , 0 ) 0 T ( 0 , 1 , 0 ) 0 T ( 0 , 0 , 1 ) 0 T ( 0 , 0 , 0 ) 1 ] A = \left[ \begin{array} { l l l l } a _ { 11 } & a _ { 12 } & a _ { 13 } & 0 \\ a _ { 21 } & a _ { 22 } & a _ { 23 } & 0 \\ a _ { 31 } & a _ { 32 } & a _ { 33 } & 0 \\ a _ { 41 } & a _ { 42 } & a _ { 43 } & 1 \end{array} \right] = \left[ \begin{array} { c c } T ( 1,0,0 ) & 0 \\ T ( 0,1,0 ) & 0 \\ T ( 0,0,1 ) & 0 \\ T ( 0,0,0 ) & 1 \end{array} \right] A = a 11 a 21 a 31 a 41 a 12 a 22 a 32 a 42 a 13 a 23 a 33 a 43 0 0 0 1 = T ( 1 , 0 , 0 ) T ( 0 , 1 , 0 ) T ( 0 , 0 , 1 ) T ( 0 , 0 , 0 ) 0 0 0 1
如果是3-3矩阵,那么只有3个输出,也就是输入 (1,0,0),(0,1,0),(0,0,1)的输出。如果只有线性变换,3个输出就可以了。但当变换是仿射的,如上的4-4矩阵会包含(0,0,0)的输出,从而我们可以知道有平移的存在
3 旋转(Rotation) R 2 , R 3 R^2,R^3 R 2 , R 3 下的旋转是由正交矩阵 Q完成的,它的行列式是 + 1 +1 + 1 (如果行列式是-1,那么可以得到额外的镜像反射),注意还是需要使用齐次坐标:
Plane Rotation Q = [ cos θ − sin θ sin θ cos θ ] becomes R = [ cos θ − sin θ 0 sin θ cos θ 0 0 0 1 ] . \text{Plane Rotation }\quad Q = \left[ \begin{array} { c c } \cos \theta & - \sin \theta \\ \sin \theta & \cos \theta \end{array} \right] \text { becomes } \quad R = \left[ \begin{array} { c c c } \cos \theta & - \sin \theta & 0 \\ \sin \theta & \cos \theta & 0 \\ 0 & 0 & 1 \end{array} \right] . Plane Rotation Q = [ cos θ sin θ − sin θ cos θ ] becomes R = cos θ sin θ 0 − sin θ cos θ 0 0 0 1 .
如上矩阵是把平面绕着原点 旋转,但如果要绕不同的点,如(4,5) 旋转怎么办?答案展示了齐次坐标的美丽之处:
把(4,5)平移到(0,0):v T − vT_- v T −
旋转 θ \theta θ :v T − ∗ R vT_{-} * R v T − ∗ R
把(0,0)平移回去(4,5): v T − R ∗ T + vT_{-}R * T_{+} v T − R ∗ T +
v T − R T + = [ x y 1 ] [ 1 0 0 0 1 0 − 4 − 5 1 ] [ cos θ − sin θ 0 sin θ cos θ 0 0 0 1 ] [ 1 0 0 0 1 0 4 5 1 ] \boldsymbol { v } T _ { - } R T _ { + } = \left[ \begin{array} { l l l } x & y & 1 \end{array} \right] \left[ \begin{array} { r r r } 1 & 0 & 0 \\ 0 & 1 & 0 \\ - 4 & - 5 & 1 \end{array} \right] \left[ \begin{array} { c c c } \cos \theta & - \sin \theta & 0 \\ \sin \theta & \cos \theta & 0 \\ 0 & 0 & 1 \end{array} \right] \left[ \begin{array} { l l l } 1 & 0 & 0 \\ 0 & 1 & 0 \\ 4 & 5 & 1 \end{array} \right] v T − R T + = [ x y 1 ] 1 0 − 4 0 1 − 5 0 0 1 cos θ sin θ 0 − sin θ cos θ 0 0 0 1 1 0 4 0 1 5 0 0 1
注意,因为 v 是行向量,所以 T − T_- T − 先起作用,把旋转中心(4,5),也就是其次坐标下的(4,5,1)移动到了 ( 0 , 0 , 1 ) (0,0,1) ( 0 , 0 , 1 ) 。旋转矩阵R没有改变旋转中心,最后 T + T_+ T + 把旋转中心移动回去(4,5,1)
三维下,旋转矩阵Q都是绕着一个轴 旋转的,这个轴是不会移动的--它是λ = 1 \lambda = 1 λ = 1 的特征向量所在的直线。现在假设这个轴是 Z 轴,Q当中的1表示不处理Z轴,R当中的1表示不处理原点(The 1 in Q is to leave the z axis alone, the extra 1 in R is to leave the origin alone ):
Q = [ cos θ − sin θ 0 sin θ cos θ 0 0 0 1 ] and R = [ 0 Q 0 0 0 0 0 1 ] Q = \left[ \begin{array} { c c c } \cos \theta & - \sin \theta & 0 \\ \sin \theta & \cos \theta & 0 \\ 0 & 0 & 1 \end{array} \right] \quad \text { and } \quad
R = \left[ \begin{array} { r r r} & & & 0 \\ & Q & &0 \\ &&&0 \\ 0&0&0&1 \end{array} \right] Q = cos θ sin θ 0 − sin θ cos θ 0 0 0 1 and R = 0 Q 0 0 0 0 0 1
现在假设是绕着单位 向量 a ⃗ = ( a 1 , a 2 , a 3 ) \vec{a}=(a_1,a_2,a_3) a = ( a 1 , a 2 , a 3 ) ,这时Q需要通过三部分化为R:
Q = ( cos θ ) I + ( 1 − cos θ ) [ a 1 2 a 1 a 2 a 1 a 3 a 1 a 2 a 2 2 a 2 a 3 a 1 a 3 a 2 a 3 a 3 2 ] − sin θ [ 0 a 3 − a 2 − a 3 0 a 1 a 2 − a 1 0 ] (1) Q = ( \cos \theta ) I + ( 1 - \cos \theta ) \left[ \begin{array} { c c c } a _ { 1 } ^ { 2 } & a _ { 1 } a _ { 2 } & a _ { 1 } a _ { 3 } \\ a _ { 1 } a _ { 2 } & a _ { 2 } ^ { 2 } & a _ { 2 } a _ { 3 } \\ a _ { 1 } a _ { 3 } & a _ { 2 } a _ { 3 } & a _ { 3 } ^ { 2 } \end{array} \right] - \sin \theta \left[ \begin{array} { r r r } 0 & a _ { 3 } & - a _ { 2 } \\ - a _ { 3 } & 0 & a _ { 1 } \\ a _ { 2 } & - a _ { 1 } & 0 \end{array} \right]
\tag{1} Q = ( cos θ ) I + ( 1 − cos θ ) a 1 2 a 1 a 2 a 1 a 3 a 1 a 2 a 2 2 a 2 a 3 a 1 a 3 a 2 a 3 a 3 2 − sin θ 0 − a 3 a 2 a 3 0 − a 1 − a 2 a 1 0 ( 1 )
这个轴不会转动,因为 a ⃗ Q = a ⃗ \vec{a}Q = \vec{a} a Q = a .如果 a=(0,0,1) 是Z轴上,那么这个Q就是前面那个Q--也就是绕着Z轴旋转
线性变换的Q总是在R的左上角,Q的下面都是0,这时因为旋转不会移动原点。如果最小面不是0,那么变换就是仿射,原点会被移动
4 投影(Projection)
在线代课程,大多数平面会经过原点,但现实当中,大多数平面不经过原点。
经过原点的平面是向量空间
不经过原点的是仿射空间,它是将向量空间平移形成的
我们想要将三维向量投影到平面。设这个平面经过原点,并且其单位法向量是 n ⃗ \vec{n} n (我们设 n ⃗ \vec{n} n 为列向量).那么平面当中的向量 v 满足 n ⃗ T v ⃗ = 0 \vec{n}^T\vec{v} = 0 n T v = 0 .投影到这个平面的矩阵是 I − n n T I - nn^T I − n n T .向量乘以这个矩阵即可投影到这个平面,而 n 会被投影为0,平面内的向量 v 投影为自身
( I − n n T ) n = n − n ( n T n ) = 0 and ( I − n n T ) v = v − n ( n T v ) = v \left( I - n n ^ { \mathrm { T } } \right) n = n - n \left( n ^ { \mathrm { T } } n \right) = 0 \quad \text { and } \quad \left( I - n \boldsymbol { n } ^ { \mathrm { T } } \right) v = v - n \left( n ^ { \mathrm { T } } v \right) = v ( I − n n T ) n = n − n ( n T n ) = 0 and ( I − n n T ) v = v − n ( n T v ) = v
在齐次坐标下,投影矩阵变为4-4(注意原点不移动):
Projectin onto the plane: n T v = 0 P = [ 0 I − n n T 0 0 0 0 0 1 ] \text{Projectin onto the plane:}\quad n ^ { \mathrm { T } } v = 0 \qquad
P = \left[ \begin{array} { c c c c}& & & 0 \\ I - n n ^ { T } & & & 0 \\&&&0\\ 0 & 0 & 0 & 1 \end{array} \right] Projectin onto the plane: n T v = 0 P = I − n n T 0 0 0 0 0 0 1
现在投影到不经过原点的平面 n ⃗ T ( v − v 0 ) = 0 \vec{n}^T(v-v_0) = 0 n T ( v − v 0 ) = 0 ,v 0 v_0 v 0 是平面上的1个点。这个等式就像是右边不为0的 Av = b的等式,特解v 0 v_0 v 0 被加到零空间上。
投影到放射空间,需要3步骤:
用 T − T_- T − 把 v 0 v_0 v 0 平移到原点
沿着n的方向投影
沿着行向量v 0 v_0 v 0 平移回去
T − P T + = [ I 0 − v 0 1 ] [ I − n n T 0 0 1 ] [ I 0 v 0 1 ] T _ { - } P T _ { + } = \left[ \begin{array} { r r } I & 0 \\ - v _ { 0 } & 1 \end{array} \right] \left[ \begin{array} { c c } I - n n ^ { \mathrm { T } } & 0 \\ 0 & 1 \end{array} \right] \left[ \begin{array} { c c } I & 0 \\ v _ { 0 } & 1 \end{array} \right] T − P T + = [ I − v 0 0 1 ] [ I − n n T 0 0 1 ] [ I v 0 0 1 ]
注意T − , T + T_-,T_+ T − , T + 是逆矩阵
习题还出现反射(reflection)矩阵,也称为镜像(mirror)矩阵,这个CG需要第五种变换。反射移动的距离是投影的2倍:反射会穿过平面,把图像放倒平面的另一边 。所以只要阿静投影矩阵的 I − n n T I - n n ^ { \mathrm { T }} I − n n T 改为 I − 2 n n T I - 2n n ^ { \mathrm { T }} I − 2 n n T 可得到镜像矩阵