缩放(Scale): [ x ′ y ′ ] = [ s x 0 0 s y ] [ x y ] \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} s_x & 0\\ 0 & s_y \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix} [x′y′]=[sx00sy][xy]
反射(Reflection): [ x ′ y ′ ] = [ − 1 0 0 1 ] [ x y ] ( 关 于 y 轴 ) [ x ′ y ′ ] = [ 1 0 0 − 1 ] [ x y ] ( 关 于 x 轴 ) \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} -1 & 0\\ 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix}\quad(关于y轴) \quad\quad \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} 1 & 0\\ 0 & -1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix}\quad(关于x轴) [x′y′]=[−1001][xy](关于y轴)[x′y′]=[100−1][xy](关于x轴)
切变(Shear): [ x ′ y ′ ] = [ 1 a 0 1 ] [ x y ] ( x 方 向 上 的 切 变 ) [ x ′ y ′ ] = [ 1 0 a 1 ] [ x y ] ( y 方 向 上 的 切 变 ) \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} 1 & a\\ 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix}\quad(x方向上的切变) \quad\quad \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} 1 & 0\\ a & 1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix}\quad(y方向上的切变) [x′y′]=[10a1][xy](x方向上的切变)[x′y′]=[1a01][xy](y方向上的切变)
旋转(Rotate): R θ = [ cos θ − sin θ sin θ cos θ ] \mathbf{R}_{\theta}= \begin{bmatrix} \cos \theta & -\sin \theta \\ \sin \theta & \cos \theta \end{bmatrix} Rθ=[cosθsinθ−sinθcosθ]
平移(Translation): ( x ′ y ′ w ′ ) = ( 1 0 t x 0 1 t y 0 0 1 ) ⋅ ( x y 1 ) \begin{pmatrix} {x}'\\ {y}'\\ {w}' \end{pmatrix} = \begin{pmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{pmatrix} \cdot \begin{pmatrix} x\\ y\\ 1 \end{pmatrix} ⎝⎛x′y′w′⎠⎞=⎝⎛100010txty1⎠⎞⋅⎝⎛xy1⎠⎞
齐次坐标:2D 点: ( x , y , 1 ) T (x,y,1)^{T} (x,y,1)T,2D 向量: ( x , y , 0 ) T (x,y,0)^{T} (x,y,0)T 。 w ≠ 0 w \neq 0 w=0 时每一项都除以 w w w,就是 2D 点。
仿射变换(Affine Transformation)= (先)线性变换 + (再)平移: ( x ′ y ′ 1 ) = ( a b t x c d t y 0 0 1 ) ⋅ ( x y 1 ) \begin{pmatrix} {x}'\\ {y}'\\ 1 \end{pmatrix} = \begin{pmatrix} a & b & t_x \\ c & d & t_y \\ 0 & 0 & 1 \end{pmatrix} \cdot \begin{pmatrix} x\\ y\\ 1 \end{pmatrix} ⎝⎛x′y′1⎠⎞=⎝⎛ac0bd0txty1⎠⎞⋅⎝⎛xy1⎠⎞
变换的顺序不能调换,从右往左写(左乘)。
视图变换(View / Camera transformation):Camera is at the origin, up at Y Y Y, look at − Z -Z −Z,让物体跟着相机走。
正交投影(Orthographic projection):长方体 [ l , r ] × [ b , t ] × [ f , n ] \left [ l,r \right ]\times \left [ b,t \right ]\times \left [ f,n \right ] [l,r]×[b,t]×[f,n] map(映射) 到 标准视体 [ − 1 , 1 ] 3 \left [ -1,1 \right ]^{3} [−1,1]3 (注意: n > f n > f n>f),先平移再缩放
透视投影(Perspective projection):近大远小,平行线不再平行。
[ x ′ y ′ ] = [ s x 0 0 s y ] [ x y ] \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} s_x & 0\\ 0 & s_y \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix} [x′y′]=[sx00sy][xy]
【例】对应下图: [ x ′ y ′ ] = [ 0.5 0 0 1.5 ] [ x y ] \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} 0.5 & 0\\ 0 & 1.5 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix} [x′y′]=[0.5001.5][xy]
[ x ′ y ′ ] = [ − 1 0 0 1 ] [ x y ] ( 关 于 y 轴 ) \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} -1 & 0\\ 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix}\quad(关于y轴) [x′y′]=[−1001][xy](关于y轴)
[ x ′ y ′ ] = [ 1 0 0 − 1 ] [ x y ] ( 关 于 x 轴 ) \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} 1 & 0\\ 0 & -1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix}\quad(关于x轴) [x′y′]=[100−1][xy](关于x轴)
如果对角线的两个元素都是 − 1 -1 −1(即 [ − 1 0 0 − 1 ] \begin{bmatrix}-1 & 0\\ 0 & -1\end{bmatrix} [−100−1]),那就相当于是一个(绕原点) π \pi π 弧度的旋转。这种旋转也可以称为“通过原点的反射”。
[ x ′ y ′ ] = [ 1 a 0 1 ] [ x y ] ( x 方 向 上 的 切 变 ) \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} 1 & a\\ 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix}\quad(x方向上的切变) [x′y′]=[10a1][xy](x方向上的切变)
[ x ′ y ′ ] = [ 1 0 a 1 ] [ x y ] ( y 方 向 上 的 切 变 ) \begin{bmatrix} {x}'\\ {y}' \end{bmatrix} = \begin{bmatrix} 1 & 0\\ a & 1 \end{bmatrix} \begin{bmatrix} x\\ y \end{bmatrix}\quad(y方向上的切变) [x′y′]=[1a01][xy](y方向上的切变)
【例】 y y y 方向上的切变( a = 1 a=1 a=1)
* 注意:默认情况下指的是绕原点旋转
根据旋转 θ \theta θ 角的矩阵 R θ \mathbf{R}_{\theta} Rθ,很容易推导出旋转 − θ -\theta −θ 角的矩阵 R − θ \mathbf{R}_{-\theta} R−θ,它等于 R θ \mathbf{R}_{\theta} Rθ 的转置:
R − θ = ( cos ( − θ ) − sin ( − θ ) sin ( − θ ) cos ( − θ ) ) = ( cos θ sin θ − sin θ cos θ ) = R θ T \mathbf{R}_{-\theta} =\begin{pmatrix} \cos (-\theta) & -\sin (-\theta) \\ \sin (-\theta) & \cos (-\theta) \end{pmatrix} = \begin{pmatrix} \cos \theta & \sin \theta \\ -\sin \theta & \cos \theta \end{pmatrix} =\mathbf{R}_{\theta}^{T} R−θ=(cos(−θ)sin(−θ)−sin(−θ)cos(−θ))=(cosθ−sinθsinθcosθ)=RθT
又由定义,旋转 − θ -\theta −θ 角等于旋转 θ \theta θ 角的逆: R − θ = R θ − 1 \mathbf{R}_{-\theta}=\mathbf{R}_{\theta}^{-1} R−θ=Rθ−1
因此我们得到这样一个结论:旋转矩阵的逆就等于旋转矩阵的转置,即 R θ − 1 = R θ T \mathbf{R}_{\theta}^{-1}=\mathbf{R}_{\theta}^{T} Rθ−1=RθT
将原有的向量添加一维:
在齐次坐标下,当 w ≠ 0 w\neq 0 w=0 时, ( x y w ) \begin{pmatrix} x\\ y\\ w \end{pmatrix} ⎝⎛xyw⎠⎞ 就表示 2D 点 ( x / w y / w 1 ) \begin{pmatrix} x/w\\ y/w\\ 1 \end{pmatrix} ⎝⎛x/wy/w1⎠⎞(即每一项都除以 w w w)。
此时,平移操作可以表示为:
( x ′ y ′ w ′ ) = ( 1 0 t x 0 1 t y 0 0 1 ) ⋅ ( x y 1 ) = ( x + t x y + t y 1 ) \begin{pmatrix} {x}'\\ {y}'\\ {w}' \end{pmatrix} = \begin{pmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{pmatrix} \cdot \begin{pmatrix} x\\ y\\ 1 \end{pmatrix} = \begin{pmatrix} x+t_x\\ y+t_y\\ 1 \end{pmatrix} ⎝⎛x′y′w′⎠⎞=⎝⎛100010txty1⎠⎞⋅⎝⎛xy1⎠⎞=⎝⎛x+txy+ty1⎠⎞
仿射变换 = 线性变换 + 平移
用齐次坐标表示为:
( x ′ y ′ 1 ) = ( a b t x c d t y 0 0 1 ) ⋅ ( x y 1 ) \begin{pmatrix} {x}'\\ {y}'\\ 1 \end{pmatrix} = \begin{pmatrix} a & b & t_x \\ c & d & t_y \\ 0 & 0 & 1 \end{pmatrix} \cdot \begin{pmatrix} x\\ y\\ 1 \end{pmatrix} ⎝⎛x′y′1⎠⎞=⎝⎛ac0bd0txty1⎠⎞⋅⎝⎛xy1⎠⎞
上面的式子相当于 ( x ′ y ′ ) = ( a b c d ) ⋅ ( x y ) + ( t x t y ) \begin{pmatrix} x^{\prime} \\ y^{\prime} \end{pmatrix} =\begin{pmatrix} a & b \\ c & d \end{pmatrix}\cdot\begin{pmatrix} x \\ y \end{pmatrix}+\begin{pmatrix} t_{x} \\ t_{y} \end{pmatrix} (x′y′)=(acbd)⋅(xy)+(txty),所以顺序是先线性变换、再平移。
【例】
缩放(Scale): S ( s x , s y ) = ( s x 0 0 0 s y 0 0 0 1 ) \mathbf{S}\left ( s_x,s_y \right )= \begin{pmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{pmatrix} S(sx,sy)=⎝⎛sx000sy0001⎠⎞
旋转(Rotation): R ( α ) = ( cos α − sin α 0 sin α cos α 0 0 0 1 ) \mathbf{R}\left ( \alpha \right )= \begin{pmatrix} \cos \alpha & -\sin \alpha & 0 \\ \sin \alpha & \cos \alpha & 0 \\ 0 & 0 & 1 \end{pmatrix} R(α)=⎝⎛cosαsinα0−sinαcosα0001⎠⎞
平移(Translation): T ( t x , t y ) = ( 1 0 t x 0 1 t y 0 0 1 ) \mathbf{T}\left ( t_x,t_y \right )= \begin{pmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{pmatrix} T(tx,ty)=⎝⎛100010txty1⎠⎞
【例】绕某一点 c \mathbf{c} c(非原点)旋转 α \alpha α 角的操作,可以分解为如下三步:
写成矩阵乘法的形式: T ( c ) ⋅ R ( α ) ⋅ T ( − c ) \mathbf{T}(\mathbf{c})\cdot \mathbf{R}(\alpha )\cdot \mathbf{T}(-\mathbf{c}) T(c)⋅R(α)⋅T(−c) (注意是从右往左乘)
【例】一个切变可以被分解成旋转-缩放-旋转三步。
[ 1 1 0 1 ] = R 2 [ σ 1 0 0 σ 2 ] R 1 = [ 0.8507 − 0.5257 0.5257 0.8507 ] [ 1.618 0 0 0.618 ] [ 0.5257 0.8507 − 0.8507 0.5257 ] = rotate ( 31. 7 ∘ ) scale ( 1.618 , 0.618 ) rotate ( − 58. 3 ∘ ) \begin{bmatrix}1 & 1 \\ 0 & 1\end{bmatrix} \\=\mathbf{R}_{2}\begin{bmatrix} \sigma_{1} & 0 \\ 0 & \sigma_{2} \end{bmatrix} \mathbf{R}_{1} \\ =\begin{bmatrix} 0.8507 & -0.5257 \\ 0.5257 & 0.8507 \end{bmatrix}\begin{bmatrix} 1.618 & 0 \\ 0 & 0.618 \end{bmatrix}\begin{bmatrix} 0.5257 & 0.8507 \\ -0.8507 & 0.5257 \end{bmatrix} \\ =\text{rotate}\left(31.7^{\circ}\right) \text { scale}(1.618,0.618) \text { rotate}\left(-58.3^{\circ}\right) [1011]=R2[σ100σ2]R1=[0.85070.5257−0.52570.8507][1.618000.618][0.5257−0.85070.85070.5257]=rotate(31.7∘) scale(1.618,0.618) rotate(−58.3∘)
3D 空间中的点和向量可以表示为:
当 w ≠ 0 w\neq 0 w=0 时, ( x y z w ) \begin{pmatrix} x\\ y\\ z\\ w \end{pmatrix} ⎝⎜⎜⎛xyzw⎠⎟⎟⎞ 就表示 3D 点 ( x / w y / w z / w 1 ) \begin{pmatrix} x/w\\ y/w\\ z/w\\ 1 \end{pmatrix} ⎝⎜⎜⎛x/wy/wz/w1⎠⎟⎟⎞ 。
绕谁转,谁不变。用代数余子式的方法去理解下面的式子:
绕 x x x 轴旋转: R x ( α ) = ( 1 0 0 0 0 cos α − sin α 0 0 sin α cos α 0 0 0 0 1 ) \mathbf{R}_{x}(\alpha) = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos \alpha & -\sin \alpha & 0 \\ 0 & \sin \alpha & \cos \alpha & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} Rx(α)=⎝⎜⎜⎛10000cosαsinα00−sinαcosα00001⎠⎟⎟⎞
绕 y y y 轴旋转: R y ( α ) = ( cos α 0 sin α 0 0 1 0 0 − sin α 0 cos α 0 0 0 0 1 ) \mathbf{R}_{y}(\alpha) = \begin{pmatrix} \cos \alpha & 0 & \sin \alpha & 0 \\ 0 & 1 & 0 & 0 \\ -\sin \alpha & 0 & \cos \alpha & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} Ry(α)=⎝⎜⎜⎛cosα0−sinα00100sinα0cosα00001⎠⎟⎟⎞ (注意负号的位置)
绕 z z z 轴旋转: R z ( α ) = ( cos α − sin α 0 0 sin α cos α 0 0 0 0 1 0 0 0 0 1 ) \mathbf{R}_{z}(\alpha) = \begin{pmatrix} \cos \alpha & -\sin \alpha & 0 & 0 \\ \sin \alpha & \cos \alpha & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} Rz(α)=⎝⎜⎜⎛cosαsinα00−sinαcosα0000100001⎠⎟⎟⎞
绕过原点的 n \mathbf{n} n 轴,旋转 α \alpha α 角度:(其中 I \mathbf{I} I 是单位阵)
R ( n , α ) = cos ( α ) I + ( 1 − cos ( α ) ) n n T + sin ( α ) ( 0 − n z n y n z 0 − n x − n y n x 0 ) ⏟ N \mathbf{R}(\mathbf{n}, \alpha)=\cos (\alpha) \mathbf{I}+(1-\cos (\alpha)) \mathbf{n n}^{T}+\sin (\alpha) \underbrace{\begin{pmatrix} 0 & -n_{z} & n_{y} \\ n_{z} & 0 & -n_{x} \\ -n_{y} & n_{x} & 0 \end{pmatrix}}_{\mathbf{N}} R(n,α)=cos(α)I+(1−cos(α))nnT+sin(α)N ⎝⎛0nz−ny−nz0nxny−nx0⎠⎞
MVP:
定义相机:
容易得到相机的右方向是 g ^ × t ^ \hat{g} \times \hat{t} g^×t^
把相机固定到原点,并且向上方向为 y y y 轴方向,看向 − z -z −z 轴的方向(观察方向)。让物体跟着相机走。
使用矩阵 M v i e w M_{view} Mview 来完成这一变换:
简单的理解正交投影(直观理解):
实际上的做法:
把一个长方体 [ l , r ] × [ b , t ] × [ f , n ] \left [ l,r \right ]\times \left [ b,t \right ]\times \left [ f,n \right ] [l,r]×[b,t]×[f,n] map(映射) 到 标准视体 [ − 1 , 1 ] 3 \left [ -1,1 \right ]^{3} [−1,1]3
M o r t h o = [ 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ] [ 1 0 0 − r + l 2 0 1 0 − t + b 2 0 0 1 − n + f 2 0 0 0 1 ] = [ 2 r − l 0 0 l + r l − r 0 2 t − b 0 b + t b − t 0 0 2 n − f f + n f − n 0 0 0 1 ] M_{ortho}=\begin{bmatrix} \frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{n-f} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}\begin{bmatrix} 1 & 0 & 0 & -\frac{r+l}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1 \end{bmatrix}= \begin{bmatrix} \frac{2}{r-l} & 0 & 0 & \frac{l + r}{l -r}\\ 0 & \frac{2}{t-b} & 0 & \frac{b + t}{b -t}\\ 0 & 0 & \frac{2}{n-f} & \frac{f + n}{f-n}\\ 0 & 0 & 0 & 1 \end{bmatrix} Mortho=⎣⎢⎢⎡r−l20000t−b20000n−f200001⎦⎥⎥⎤⎣⎢⎢⎡100001000010−2r+l−2t+b−2n+f1⎦⎥⎥⎤=⎣⎢⎢⎡r−l20000t−b20000n−f20l−rl+rb−tb+tf−nf+n1⎦⎥⎥⎤
注意: n > f n > f n>f (Looking at / along -Z is making near and far not intuitive(不符合直觉))
如何做透视投影: M p e r s p = M o r t h o M p e r s p → o r t h o M_{persp}=M_{ortho} M_{persp \rightarrow ortho} Mpersp=MorthoMpersp→ortho
求解 M p e r s p → o r t h o M_{persp \rightarrow ortho} Mpersp→ortho 的中心思想: 寻找变换后 点 ( x ’ , y ’ , z ’ ) (x’, y’, z’) (x’,y’,z’) 和变换前 点 ( x , y , z ) (x, y, z) (x,y,z) 的关系
在挤压的过程中,
求解出来得: M p e r s p → o r t h o = ( n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ) M_{persp \rightarrow ortho}=\begin{pmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\ 0 & 0 & 1 & 0 \end{pmatrix} Mpersp→ortho=⎝⎜⎜⎛n0000n0000n+f100−nf0⎠⎟⎟⎞
综上: M p e r s p = M o r t h o M p e r s p → o r t h o = M o r t h o ( n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ) = ( 2 n r − l 0 l + r l − r 0 0 2 n t − b b + t b − t 0 0 0 n + f n − f 2 f n f − n 0 0 1 0 ) \displaystyle M_{persp} \\ =M_{ortho} M_{persp \rightarrow ortho} \\ =M_{ortho} \begin{pmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\ 0 & 0 & 1 & 0 \end{pmatrix} \\ = \begin{pmatrix} \frac{2n}{r-l} & 0 & \frac{l+r}{l-r} & 0\\ 0 & \frac{2n}{t-b} & \frac{b+t}{b-t} & 0\\ 0 & 0 & \frac{n+f}{n-f} & \frac{2fn}{f-n}\\ 0 & 0 & 1 & 0 \end{pmatrix} Mpersp=MorthoMpersp→ortho=Mortho⎝⎜⎜⎛n0000n0000n+f100−nf0⎠⎟⎟⎞=⎝⎜⎜⎛r−l2n0000t−b2n00l−rl+rb−tb+tn−fn+f100f−n2fn0⎠⎟⎟⎞
参考:
Steve Marschner and Peter Shirley. Fundamentals of Computer Graphics. 第四版.
GAMES101. https://www.bilibili.com/video/BV1X7411F744?p=3.
变换(二维与三维)课件. https://sites.cs.ucsb.edu/~lingqi/teaching/resources/GAMES101_Lecture_03.pdf.
变换(模型、视图、投影)课件. https://sites.cs.ucsb.edu/~lingqi/teaching/resources/GAMES101_Lecture_04.pdf.