2D transformations

缩放 Scale

  • Transform: x=sxx  ;  y=syyx'=s_xx\;;\;y'=s_yy
  • Matrix: [xy]=[sx00sy][xy]\begin{bmatrix}x'\\y'\end{bmatrix}=\begin{bmatrix}s_x&0\\0&s_y\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}

Scale (Uniform)

Scale (Uniform)

Scale (Non-Uniform)

Scale (Non-Uniform)

Reflection Matrix

Reflection Matrix

Shear Matrix

Shear Matrix

旋转 Rotate

  • 默认绕 (0, 0) ,逆时针(Counterclockwise)旋转

Rotation Matrix

RθR_\theta 矩阵推导:

x=Rθxx'=R_\theta x,即 [xy]=[abcd][xy]\begin{bmatrix}x'\\y'\end{bmatrix}=\begin{bmatrix}a&b\\c&d\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}

由特殊点:
( cosθ, sinθ) ← (1, 0) 得 a = cosθ, c = sinθ ;
(-sinθ, cosθ) ← (0, 1) 得 b = -sinθ, d = cosθ 。

Linear Transforms = Matrices (of the same dimension)

x  =  ax  +  by          y  =  cx  +  dyx'\;=\;ax\;+\;by\;\;\;\;\;y'\;=\;cx\;+\;dy

[xy]=[abcd][xy]\begin{bmatrix}x'\\y'\end{bmatrix}=\begin{bmatrix}a&b\\c&d\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}

x=Mxx'=Mx

平移 Translation

Translation

x  =  x  +  tx          y  =  y  +  tyx'\;=\;x\;+\;t_x\;\;\;\;\;y'\;=\;y\;+\;t_y

[xy]  =  [abcd]  [xy]  +  [txty]\begin{bmatrix}x'\\y'\end{bmatrix}\;=\;\begin{bmatrix}a&b\\c&d\end{bmatrix}\;\begin{bmatrix}x\\y\end{bmatrix}\;+\;\begin{bmatrix}t_x\\t_y\end{bmatrix}

平移不能以矩阵形式表示,不是线性变换。但是我们不希望平移成为一种特殊情况。

是否有一个统一的方式来表示所有的变换?(代价是什么?)

齐次坐标 Homogeneous coordinates

添加第三个坐标:w

  • 2D point  = (x,y,1)T(x, y, 1)^T
  • 2D vector = (x,y,0)T(x, y, 0)^T

平移的矩阵表示: [xyw]  =  [10tx01ty001][xy1]  =  [x  +txy  +ty1]\begin{bmatrix}x'\\y'\\w'\end{bmatrix}\;=\;\begin{bmatrix}1&0&t_x\\0&1&t_y\\0&0&1\end{bmatrix}\cdot\begin{bmatrix}x\\y\\1\end{bmatrix}\;=\;\begin{bmatrix}x\;+\:t_x\\y\;+\:t_y\\1\end{bmatrix}

如果平移一个向量会怎样?
向量只关注长度、方向,经过平移之后保持不变。

w = 1,表示一个点 point,w = 0 表示一个向量 vector:

  • vector + vector = vector
  • vector - vector = vector + (-vector)
  • point + vector = point
  • point - vector = point + (-vector)
  • point + point = ???
  • point - point = vector

当 point + point 时,结果的 w = 2,我们规定在齐次坐标中:

(x,y,w)T  is  the  2D  point  (xw,yw,1)T,  w0(x, y, w)^T\;is\;the\;2D\;point\;(\frac xw, \frac yw, 1)^T,\;w \neq 0

所以齐次坐标中,两点相加得到的是两点的中点 point + point = (mid) point。

仿射变换 Affine Transformations

  • 先线性变换,再平移(Affine map = linear map + translation

[xy]=[abcd][xy]+[txty]\begin{bmatrix}x'\\y'\end{bmatrix}=\begin{bmatrix}a&b\\c&d\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}+\begin{bmatrix}t_x\\t_y\end{bmatrix}

  • 使用齐次坐标:

[xy1]  =  [abtxcdty001][xy1]\begin{bmatrix}x'\\y'\\1\end{bmatrix}\;=\;\begin{bmatrix}a&b&t_x\\c&d&t_y\\0&0&1\end{bmatrix}\cdot\begin{bmatrix}x\\y\\1\end{bmatrix}

2D Transformations using Homogeneous coordinates

逆变换 Inverse Transform

Inverse Transform

x=Ix=M1Mx=M1xx = Ix = M^{-1}Mx = M^{-1}x'

组合变换 Composing Transforms

Transform Ordering Matters!

  • 变换的顺序很重要,因为矩阵乘法没有交换律:

R45T(1,0)T(1,0)R45R_{45}\cdot T_{(1,0)}\neq T_{(1,0)}\cdot R_{45}

  • 注意变换矩阵是从右到左应用的:

T(1,  0)R45[xy1]=[101010001][cos45sin450sin45cos450001][xy1]T_{(1,\;0)}\cdot R_{45}\begin{bmatrix}x\\y\\1\end{bmatrix}=\begin{bmatrix}1&0&1\\0&1&0\\0&0&1\end{bmatrix}\begin{bmatrix}\cos45^\circ&-\sin45^\circ&0\\\sin45^\circ&\cos45^\circ&0\\0&0&1\end{bmatrix}\begin{bmatrix}x\\y\\1\end{bmatrix}

对仿射变换序列:A1,A2,A3,...,AnA_1, A_2, A_3, ..., A_n,由矩阵乘法组成:
Composing Transforms

矩阵乘法虽然没有交换律,但是有结合律,预乘 n 个矩阵以获得表示组合变换的单个矩阵,这对性能来说非常重要。

[xy1]=[10tx01ty001][ab0cd0001][xy1]=[abtxcdty001][xy1]\begin{bmatrix}x'\\y'\\1\end{bmatrix}=\begin{bmatrix}1&0&t_x\\0&1&t_y\\0&0&1\end{bmatrix}\begin{bmatrix}a&b&0\\c&d&0\\0&0&1\end{bmatrix}\begin{bmatrix}x\\y\\1\end{bmatrix}=\begin{bmatrix}a&b&t_x\\c&d&t_y\\0&0&1\end{bmatrix}\begin{bmatrix}x\\y\\1\end{bmatrix}

分解复杂的变换 Decomposing Complex Transforms

我们之前说的旋转,是绕原点 (0, 0),如何绕给定的点 c 旋转?

  1. 将点 c 平移至原点;
  2. 旋转;
  3. 将点 c 平移回去。

rotate around a given point c

3D Transforms

类比 2D 变换,使用齐次坐标:

  • 3D point  = (x,y,z,1)T(x, y, z, 1)^T
  • 3D vector = (x,y,z,0)T(x, y, z, 0)^T

In  general,  (x,y,z,w)T  is  the  3D  point  (xw,yw,zw,1)T,  w0In\;general,\;(x, y, z, w)^T\;is\;the\;3D\;point\;(\frac xw, \frac yw, \frac zw, 1)^T,\;w \neq 0

使用 4×4 矩阵进行仿射变换(先线性变换,再平移):

[xyz1]=[100tx010ty001tz0001][abc0def0ghi00001][xyz1]=[abctxdeftyghitz0001][xyz1]\begin{bmatrix}x'\\y'\\z'\\1\end{bmatrix}=\begin{bmatrix}1&0&0&t_x\\0&1&0&t_y\\0&0&1&t_z\\0&0&0&1\end{bmatrix}\cdot\begin{bmatrix}a&b&c&0\\d&e&f&0\\g&h&i&0\\0&0&0&1\end{bmatrix}\cdot\begin{bmatrix}x\\y\\z\\1\end{bmatrix}=\begin{bmatrix}a&b&c&t_x\\d&e&f&t_y\\g&h&i&t_z\\0&0&0&1\end{bmatrix}\cdot\begin{bmatrix}x\\y\\z\\1\end{bmatrix}

3D Transformations

3D Transformations

  • 绕 x 轴旋转,x 坐标不变,y×z=+x\overset\rightharpoonup y\times\overset\rightharpoonup z=+\overset\rightharpoonup x,在 y-z 平面旋转 θ,Rx(θ)R_x(\theta) 的 y, z 坐标矩阵与 2D 旋转矩阵 RθR_\theta 相同;

  • 绕 z 轴旋转,z 坐标不变,x×y=+z\overset\rightharpoonup x\times\overset\rightharpoonup y=+\overset\rightharpoonup z,在 x-y 平面旋转 θ,Rz(θ)R_z(\theta) 的 x, y 坐标矩阵与 2D 旋转矩阵 RθR_\theta 相同;

  • 绕 y 轴旋转,y 坐标不变,z×x=+y\overset\rightharpoonup z\times\overset\rightharpoonup x=+\overset\rightharpoonup y,在 z-x 平面旋转 θ,Ry(θ)R_y(\theta) 的 z, x 坐标矩阵与 2D 旋转矩阵 RθR_\theta 相同;
    但是因为我们矩阵坐标顺序为 x, y, z,所以实际是 Ry(θ)R_y(\theta) 的 x, z 坐标矩阵与 2D 旋转矩阵 Rθ1R_\theta^{-1} 相同。

为什么是 Rθ1R_\theta^{-1}

上面我们提到逆变换 Inverse Transform,不难看出,在 z-x 平面逆时针旋转 θ 的角度,相当于在 x-z 平面顺时针旋转 θ 的角度,也就是逆时针旋转 -θ 的角度,自然是一个逆变换。

Inverse Transform

Rθ=[cosθsinθsinθcosθ]R_\theta=\begin{bmatrix}\cos\theta&-\sin\theta\\\sin\theta&\cos\theta\end{bmatrix}

Rθ=[cos(θ)sin(θ)sin(θ)cos(θ)]=[cosθsinθsinθcosθ]=RθTR_{-\theta}=\begin{bmatrix}\cos(-\theta)&-\sin(-\theta)\\\sin(-\theta)&\cos(-\theta)\end{bmatrix}=\begin{bmatrix}\cos\theta&\sin\theta\\-\sin\theta&\cos\theta\end{bmatrix}=R_\theta^T

Rθ=Rθ1    (by  definition)R_{-\theta}=R_\theta^{-1}\;\;(by\;definition)

可以得到,旋转矩阵的逆等于旋转矩阵的转置,Rθ1=RθTR_\theta^{-1}=R_\theta^T,这在后面会用到。

另外在数学上,如果一个矩阵的逆等于它的转置,我们称之为正交矩阵

3D Rotations

RxR_xRyR_yRzR_z 组成任何 3D 旋转:

Rxyz(α,β,γ)=Rx(α)Ry(β)Rz(γ){\boldsymbol R}_{xyz}(\alpha,\beta,\gamma)={\boldsymbol R}_x(\alpha){\boldsymbol R}_y(\beta){\boldsymbol R}_z(\gamma)

也就是把任意旋转都写成绕 x,绕 y,绕 z 轴旋转的组合,旋转的角度分别是 α,β,γ 角,这三个角又被称作欧拉角

三个轴可以对应飞机的运动:横滚 roll、俯仰 pitch、偏航 yaw,可以看出确实任意旋转都可以分解为绕三个轴旋转的组合。
roll, pitch, yaw

罗德里格斯旋转公式 Rodrigues’ Rotation Formula

绕 n 轴(用单位向量 n^\widehat n表示,起点为原点,方向是 n 轴的方向),旋转角度 α 的旋转矩阵:

Rodrigues’ Rotation Formula

如何绕任意轴旋转?变换分解:将轴起点平移到原点;旋转;再移回去。

但是 R(n,  α)+R(n,  β)R(n,  α+β2)R(\boldsymbol n,\;\alpha)+R(\boldsymbol n,\;\beta)\neq R(\boldsymbol n,\;\frac{\alpha+\beta}2),因为三角函数并不是线性的,也就是说旋转矩阵不适合作差值,四元数可以解决这个问题。

GAMES101没有讲关于四元数,这里先不写了,以后再找一下欧拉角、旋转矩阵、四元数之间的转换。
留个问题,旋转矩阵转欧拉角作差值可以吗?

推导

参考百度百科的过程简单梳理一下:

v\overset\rightharpoonup v 是一个三维空间向量,k^\widehat k是旋转轴的单位向量,则 v\overset\rightharpoonup v 在右手螺旋定则意义下绕旋转轴 k^\widehat k旋转角度 θ 得到的向量可以由三个不共面的向量 v\overset\rightharpoonup v , k^\widehat kk^×v\widehat k\times\overset\rightharpoonup v 表示:

vrot=cosθv+(1cosθ)(vk^)k^+sinθk^×v\overset\rightharpoonup{v_{rot}}=\cos\theta\overset\rightharpoonup v+(1-\cos\theta)(\overset\rightharpoonup v\cdot\widehat k)\widehat k+\sin\theta\widehat k\times\overset\rightharpoonup v

向量形式

思路:对于与旋转轴 k^\widehat k呈任意角度的向量 v\overset\rightharpoonup v,可以通过正交分解,把被旋转向量转化为与旋转轴平行的分量 v\overset\rightharpoonup{v_\parallel} 和与旋转轴垂直的分量 v\overset\rightharpoonup{v_\perp},其中 v\overset\rightharpoonup{v_\parallel} 在旋转中是不变的,而 v\overset\rightharpoonup{v_\perp} 则恰好旋转了角度 θ,把 v\overset\rightharpoonup{v_\perp} 旋转后的向量 vrot\overset\rightharpoonup{v_{\perp rot}}v\overset\rightharpoonup{v_\parallel} 相加,即可得到旋转以后的向量 vrot=v+vrot\overset\rightharpoonup{v_{rot}}=\overset\rightharpoonup{v_\parallel}+\overset\rightharpoonup{v_{\perp rot}}

罗德里格旋转公式

Step 1:
对向量 v\overset\rightharpoonup v 正交分解:v=v+v\overset\rightharpoonup v=\overset\rightharpoonup{v_\parallel}+\overset\rightharpoonup{v_\perp}
利用向量投影公式,可得 v\overset\rightharpoonup{v_\parallel},其中设 k^\widehat kv\overset\rightharpoonup v 夹角为 α,且 k^\widehat k为单位向量,k^=1\left|\widehat k\right|=1

v=proj(v,  k^)=(vcosα)k^=(vk^k^)k^=(vk^)k^\overset\rightharpoonup{v_\parallel}=proj(\overset\rightharpoonup v,\;\widehat k)=(\left|\overset\rightharpoonup v\right|\cos\alpha)\widehat k=(\frac{\overset\rightharpoonup v\cdot\widehat k}{\left|\widehat k\right|})\widehat k=(\overset\rightharpoonup v\cdot\widehat k)\widehat k

通过向量减法,可得 v=vv=v(vk^)k^\overset\rightharpoonup{v_\perp}=\overset\rightharpoonup v-\overset\rightharpoonup{v_\parallel}=\overset\rightharpoonup v-(\overset\rightharpoonup v\cdot\widehat k)\widehat k

Step 2:
首先得到 v\overset\rightharpoonup{v_\perp} 对应的单位向量 v^=normalize(v)=vv\widehat{v_\perp}=normalize(\overset\rightharpoonup{v_\perp})=\frac{\overset\rightharpoonup{v_\perp}}{\left|\overset\rightharpoonup{v_\perp}\right|}

利用叉乘得到与 k^\widehat kv^\widehat{v_\perp} 都垂直的单位向量 w^\widehat w

w^=k^×v^=k^×vv=k^×(v(vk^)k^)v=k^×v0v=k^×vv\widehat w=\widehat k\times\widehat{v_\perp}=\frac{\widehat k\times\overset\rightharpoonup{v_\perp}}{\left|\overset\rightharpoonup{v_\perp}\right|}=\frac{\widehat k\times(\overset\rightharpoonup v-(\overset\rightharpoonup v\cdot\widehat k)\widehat k)}{\left|\overset\rightharpoonup{v_\perp}\right|}=\frac{\widehat k\times\overset\rightharpoonup v-\overset\rightharpoonup0}{\left|\overset\rightharpoonup{v_\perp}\right|}=\frac{\widehat k\times\overset\rightharpoonup v}{\left|\overset\rightharpoonup{v_\perp}\right|}

此时 k^\widehat kv^\widehat{v_\perp}w^\widehat w组成一个右手坐标系。
为什么令 w^=k^×v^\widehat w=\widehat k\times\widehat{v_\perp} 而不是 w^=v^×k^\widehat w=\widehat{v_\perp}\times\widehat k?

个人理解是方便计算:
因为逆时针旋转,一般假设旋转角度 θ  (0θ180)\theta\;(0\leq\theta\leq180^\circ),正交分解时计算方便,否则要处理负号;后面由 vrot\overset\rightharpoonup{v_{rot}} 推导旋转矩阵时也容易提取 v\overset\rightharpoonup v

当然令 w^=v^×k^\widehat w=\widehat{v_\perp}\times\widehat k也完全 OK,只是某些部分会多一个负号,这只是我们推导的中间过程,最终结果是一样的,因为有 a×b=b×a\overset\rightharpoonup a\times\overset\rightharpoonup b=-\overset\rightharpoonup b\times\overset\rightharpoonup a

Step 3:
然后可以对旋转 θ 角度之后的 vrot\overset\rightharpoonup{v_{\perp rot}} 作正交分解:

vrot=(vrotcosθ)v^+(vrotsinθ)w^\overset\rightharpoonup{v_{\perp rot}}=(\left|\overset\rightharpoonup{v_{\perp rot}}\right|\cos\theta)\widehat{v_\perp}+(\left|\overset\rightharpoonup{v_{\perp rot}}\right|\sin\theta)\widehat w

显然,有 vrot=v\left|\overset\rightharpoonup{v_{\perp rot}}\right|=\left|\overset\rightharpoonup{v_\perp}\right|,所以:

vrot=cosθv+sinθk^×v=cosθ(v(vk^)k^)+sinθk^×v\overset\rightharpoonup{v_{\perp rot}}=\cos\theta\overset\rightharpoonup{v_\perp}+\sin\theta\widehat k\times\overset\rightharpoonup v=\cos\theta(\overset\rightharpoonup v-(\overset\rightharpoonup v\cdot\widehat k)\widehat k)+\sin\theta\widehat k\times\overset\rightharpoonup v

最终得到旋转后的向量表达式 vrot\overset\rightharpoonup{v_{rot}}

vrot=v+vrot=(vk^)k^+cosθ(v(vk^)k^)+sinθk^×v\overset\rightharpoonup{v_{rot}}=\overset\rightharpoonup{v_\parallel}+\overset\rightharpoonup{v_{\perp rot}}=(\overset\rightharpoonup v\cdot\widehat k)\widehat k+\cos\theta(\overset\rightharpoonup v-(\overset\rightharpoonup v\cdot\widehat k)\widehat k)+\sin\theta\widehat k\times\overset\rightharpoonup v

即为:

vrot=cosθv+(1cosθ)(vk^)k^+sinθk^×v\overset\rightharpoonup{v_{rot}}=\cos\theta\overset\rightharpoonup v+(1-\cos\theta)(\overset\rightharpoonup v\cdot\widehat k)\widehat k+\sin\theta\widehat k\times\overset\rightharpoonup v

矩阵形式

在计算机图形学中,罗德里格向量旋转公式通常被用来填写旋转矩阵 R(k,θ)R(k, \theta)

旋转以后的向量可以表示为:vrot=R(k,  θ)v\overset\rightharpoonup{v_{rot}}=R(k,\;\theta)\overset\rightharpoonup v

只需从向量表达式中提取出一个右乘(点乘)的 v\overset\rightharpoonup v,即可得:

R(k,  θ)=cosθI+(1cosθ)k^k^T+sinθKR(k,\;\theta)=\cos\theta I+(1-\cos\theta)\widehat k\widehat k^T+\sin\theta K

其中,II 为 3 阶单位矩阵(也有用 EE 表示的),KK 为单位向量 k^\widehat k的矩阵表示:k^×v=Kv\widehat k\times\overset\rightharpoonup v=K\overset\rightharpoonup v

假设:k^=(kxkykz)T,      v=(vxvyvz)T\widehat k=\begin{pmatrix}k_x&k_y&k_z\end{pmatrix}^T,\;\;\;\overset\rightharpoonup v=\begin{pmatrix}v_x&v_y&v_z\end{pmatrix}^T,则:

R(k,  θ)=cosθI+(1cosθ)(kxkykz)(kxkykz)+sinθ(0kzkykz0kxkykx0)R(k,\;\theta)=\cos\theta I+(1-\cos\theta)\begin{pmatrix}k_x\\k_y\\k_z\end{pmatrix}\begin{pmatrix}k_x&k_y&k_z\end{pmatrix}+\sin\theta\begin{pmatrix}0&-k_z&k_y\\k_z&0&-k_x\\-k_y&k_x&0\end{pmatrix}

观测变换 Viewing transformation

视图变换 View/Camera transformation

  1. 什么是视图变换?思考如何拍一张照片:
    • 找一个好的地方安排人站位(模型变换 Model Transformation)
    • 找一个好的角度安置相机(视图变换 View Transformation)
    • 茄子!(投影变换 Projection Transformation)
  2. 如何进行视图变换?
    • 首先定义相机
      • 位置 Position e\overset\rightharpoonup e
      • 视线方向 Look-at / gaze direction g^\widehat g
      • 向上方向 Up direction t^\widehat t(想象飞机的翻滚 roll
        Define the camera
    • 如果相机和所有的物体一起移动,“照片”将是相同的(相对静止
      relatively still
    • 如果我们总是变换相机到:
      • The origin, up at Y, look at -Z
      • 并让物体跟着相机一起变换
        fixed camera position
    • 利用视图变换矩阵 MviewM_{view} 变换相机
      • 使其 located at origin, up at Y, look at -Z
    • MviewM_{view} in math?
      • Mview=RviewTviewM_{view}=R_{view}T_{view}(先平移,再旋转
      • Translate e\overset\rightharpoonup e to origin

        Tview=[100xe010ye001ze0001]T_{view}=\begin{bmatrix}1&0&0&-x_e\\0&1&0&-y_e\\0&0&1&-z_e\\0&0&0&1\end{bmatrix}

      • Rotate g^\widehat g to -Z, t^\widehat tto Y, g^×t^\widehat g\times\widehat tto X
      • 考虑它的逆旋转 Inverse rotation:X to g^×t^\widehat g\times\widehat t, Y to t^\widehat t, Z to g^-\widehat g
        inverse rotation

为什么要考虑逆旋转?如果直接计算 RviewR_{view}

  • Rotate g^\widehat g to -Z, t^\widehat tto Y, g^×t^\widehat g\times\widehat tto X
    设旋转矩阵 RviewR_{view}

    Rview=[abc0def0ghi00001]R_{view}=\begin{bmatrix}a&b&c&0\\d&e&f&0\\g&h&i&0\\0&0&0&1\end{bmatrix}

    X,Y,Z 方向分别用单位向量 x^\widehat xy^\widehat yz^\widehat z表示:

    x^=(1000)      y^=(0100)      z^=(0010)\widehat x=\begin{pmatrix}1\\0\\0\\0\end{pmatrix}\;\;\;\widehat y=\begin{pmatrix}0\\1\\0\\0\end{pmatrix}\;\;\;\widehat z=\begin{pmatrix}0\\0\\1\\0\end{pmatrix}

    g^\widehat gt^\widehat tg^×t^\widehat g\times\widehat t分别为:

    g^=(xg^yg^zg^0)      t^=(xt^yt^zt^0)      g^×t^=(xg^×t^yg^×t^zg^×t^0)\widehat g=\begin{pmatrix}x_{\widehat g}\\y_{\widehat g}\\z_{\widehat g}\\0\end{pmatrix}\;\;\;\widehat t=\begin{pmatrix}x_{\widehat t}\\y_{\widehat t}\\z_{\widehat t}\\0\end{pmatrix}\;\;\;\widehat g\times\widehat t=\begin{pmatrix}x_{\widehat g\times\widehat t}\\y_{\widehat g\times\widehat t}\\z_{\widehat g\times\widehat t}\\0\end{pmatrix}

    则有:z^=Rviewg^-\widehat z=R_{view}\widehat gy^=Rviewt^\widehat y=R_{view}\widehat tx^=Rviewg^×t^\widehat x=R_{view}\widehat g\times\widehat t,但是这样计算 RviewR_{view} 确实有点困难。

  • 考虑它的逆旋转 Inverse rotation:X to g^×t^\widehat g\times\widehat t, Y to t^\widehat t, Z to g^-\widehat g
    设旋转矩阵 Rview1R_{view}^{-1}

    Rview1=[abc0def0ghi00001]R_{view}^{-1}=\begin{bmatrix}a&b&c&0\\d&e&f&0\\g&h&i&0\\0&0&0&1\end{bmatrix}

    则有:g^×t^=Rview1x^\widehat g\times\widehat t=R_{view}^{-1}\widehat xt^=Rview1y^\widehat t=R_{view}^{-1}\widehat yg^=Rview1z^-\widehat g=R_{view}^{-1}\widehat z,可以很容易计算出:

    Rview1=[xg^×t^xt^xg^0yg^×t^yt^yg^0zg^×t^zt^zg^00001]R_{view}^{-1}=\begin{bmatrix}x_{\widehat g\times\widehat t}&x_{\widehat t}&x_{-\widehat g}&0\\y_{\widehat g\times\widehat t}&y_{\widehat t}&y_{-\widehat g}&0\\z_{\widehat g\times\widehat t}&z_{\widehat t}&z_{-\widehat g}&0\\0&0&0&1\end{bmatrix}

    前面我们提到,正交矩阵的逆等于它的转置,所以 Rview=(Rview1)1=(Rview1)TR_{view}=(R_{view}^{-1})^{-1}=(R_{view}^{-1})^T

Rview=[xg^×t^yg^×t^zg^×t^0xt^yt^zt^0xg^yg^zg^00001]R_{view}=\begin{bmatrix}x_{\widehat g\times\widehat t}&y_{\widehat g\times\widehat t}&z_{\widehat g\times\widehat t}&0\\x_{\widehat t}&y_{\widehat t}&z_{\widehat t}&0\\x_{-\widehat g}&y_{-\widehat g}&z_{-\widehat g}&0\\0&0&0&1\end{bmatrix}

  1. 总结 Summary
    • Transform objects together with the camera
    • Until camera at the origin, up at Y, look at -Z
  • 视图/相机变换 View/Camera Transformation,也称为模型视图变换 ModelView Transformation
  • 我们需要它用于投影变换 Projection Transformation。

这样只需要对物体应用视图变换,相机就固定在默认位置上(The origin, up at Y, look at -Z)。从世界坐标系转到相机坐标系?

投影变换 Projection transformation

  • 计算机图形学中的投影
    • 3D to 2D
    • 正交投影 Orthographic projection
    • 透视投影 Perspective projection(近大远小
      projection
  • 正交投影与透视投影的对比
    Perspective projection vs. orthographic projection

正交投影 Orthographic projection

  • 一种简单的理解方式
    • 相机位于原点,看向 -Z,向上方向 Y(视图变换中的默认相机位置
    • 去掉 Z 轴(映射到 z = 0 的 x-y 平面,3D to 2D
    • 将生成的矩形画面平移并缩放到 [1,1]2[-1, 1]^2
      a simple projection
  • 通常情况下(规定/默认操作,方便后续计算
    • 我们想要将长方体 [l, r] x [b, t] x [f, n] 映射到特定的 “canonical(正则、规范、标准)” 立方体 [1,1]3[-1, 1]^3

    [left, right] → [-1, 1];   [bottom, top] → [-1, 1];   [far, near] → [-1, 1]

  • 以简单的方式:
    • 移动 translate 长方体的中心 center 到原点 origin
    • 缩放 scale 到 “规范 canonical” 立方体
      Orthographic Projection
  • 变换矩阵
    • Translate (center to origin) first, then scale (length/width/height to 2)

    Mortho=[2rl00002tb00002nf00001][100r+l2010t+b2001n+f20001]M_{ortho}=\begin{bmatrix}\frac2{r-l}&0&0&0\\0&\frac2{t-b}&0&0\\0&0&\frac2{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}

  • 注意事项
    • 看向 -Z 方向会使近处 near 和远处 far 反直觉/不直观(n > f)

    从坐标来说,直觉应该是近处坐标小,远处坐标大,而这里是 “近大远小”

    • 仅供参考:这就是 OpenGL(图形 API)使用左手坐标的原因

将长方体映射到规范立方体,不是等比例压缩,很可能造成拉伸,这没关系,后面还有变换处理。

透视投影 Perspective projection

  • 最常见于计算机图形学、艺术、视觉系统
  • 更远的物体更小(近大远小
  • 视觉效果:平行线不平行,收敛到单点
    perspective projection
  • 如何进行透视投影?
    • 首先将四角棱台/锥台 frustum (视锥体 viewing frustum) “挤压” 变成长方体 cuboid
      这样就将透视投影转换成正交投影 Mpersp>orthoM_{persp->ortho}
    • 然后进行正交投影(我们前面已经准备好 MorthoM_{ortho}
      Perspective to Orthographic

    这里我们规定 “挤压” 操作以确保做法唯一:

    • 近平面 (z = n) 上的任意点都不会改变
    • 远平面 (z = f) 上的任意点的 z 坐标不会改变
    • 远平面 (z = f) 上的中心点也不会改变

    (frustum 内部的点坐标会发生变化,包括 z 坐标

  • 如何 “挤压” ?寻找一种变换 transformation
    • 寻找变换后的点 (x,y,z)(x', y', z') 和原始点 (x,y,z)(x, y, z) 之间的关系(相似三角形
      由相似三角形的成比例关系,可以得到 frustum 中任意点的 x, y 坐标的变换:x=nx/z,  y=ny/zx'=nx/z,\;y'=ny/z
      但是 z 坐标的变换仍是未知的,暂且写为 unknown
      the key idea to find a transformation
    • 在齐次坐标 homogeneous coordinates 中:
      (x', y', z') <= (x, y, z)

      回想之前讲过的齐次坐标的性质:
      (wx,wy,wz,w),  w0(wx, wy, wz, w),\;w\neq 0(x,y,z,1)(x, y, z, 1) 表示的是 3D 中的同一点 (x,y,z)(x, y, z)
      例如:(1, 0, 0, 1) 和 (2, 0, 0, 2) 都表示 (1, 0, 0)
      所以我们可以同时乘上一个 z (mult. by z):(x,y,z,1)(x, y, z, 1) to (xz,yz,zz,z)(xz, yz, zz, z)

      • 所以 “挤压”(透视到正交)投影可以做到这一点:

      Mpersportho(4×4)(xyz1)=(nx/zny/zunknown1)=(nxnyunknownz)M_{persp\rightarrow ortho}^{(4\times4)}\begin{pmatrix}x\\y\\z\\1\end{pmatrix}=\begin{pmatrix}nx/z\\ny/z\\unknown\\1\end{pmatrix}=\begin{pmatrix}nx\\ny\\unknown\\z\end{pmatrix}

    • 根据已知信息,已经足以弄清楚 Mpersp>orthoM_{persp->ortho} 的一部分:

      Mpersportho=(n0000n00????0010)M_{persp\rightarrow ortho}=\begin{pmatrix}n&0&0&0\\0&n&0&0\\?&?&?&?\\0&0&1&0\end{pmatrix}

    • 显然,变换矩阵的第三行负责的是 z 坐标
      • 近平面 (z = n) 上的任意点都不会改变:(x, y, n, 1) to (x, y, n, 1)
        Any point on the near plane will not change

        所以第三行一定是 (00AB)\begin{pmatrix}0&0&A&B\end{pmatrix} 的形式
        the form of the third row

        同时,已知:An+B=n2An+B=n^2

      • 远平面 (z = f) 上的任意点的 z 坐标不会改变:(x,y,f,1)(x, y, f, 1) to (x,y,f,1)(x', y', f, 1)
        取远平面的中心点:(0,0,f,1)(0, 0, f, 1) to (0,0,f,1)(0, 0, f, 1)
        可得 Af+B=f2Af+B=f^2
        the transformation of (0, 0, f, 1)

      • 求解 A 和 B:
        Solve for A and B

    • 最终,得到 MpersporthoM_{persp\rightarrow ortho}

      Mpersportho=(n0000n0000n+fnf0010)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}

    • 接下来?
      • 进行正交投影 MorthoM_{ortho}
      • Mpersp=MorthoMpersporthoM_{persp}=M_{ortho}M_{persp\rightarrow ortho}

Mpersportho=[2rl00002tb00002nf00001][100r+l2010t+b2001n+f20001](n0000n0000n+fnf0010)M_{persp\rightarrow ortho}=\begin{bmatrix}\frac2{r-l}&0&0&0\\0&\frac2{t-b}&0&0\\0&0&\frac2{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{pmatrix}n&0&0&0\\0&n&0&0\\0&0&n+f&-nf\\0&0&1&0\end{pmatrix}

最后的小问题:frustum 中间平面 z=n+f2z = \frac{n+f}{2} 的点,经过 “挤压” 后会变得更远还是更近?

我们只关注 z 坐标的变化,可以观察中间平面的中心点 (00n+f21)\begin{pmatrix}0&0&\frac{n+f}2&1\end{pmatrix}
记该点为 V 点,坐标系原点为 O 点,v=OV\overset\rightharpoonup v=\overset\rightharpoonup{OV}
则有:vpersportho=Mpersporthov\overset\rightharpoonup v_{persp\rightarrow ortho}=M_{persp\rightarrow ortho}\overset\rightharpoonup v

vpersportho=(n0000n0000n+fnf0010)(00n+f21)=(00n+f2nfn+f1)\overset\rightharpoonup v_{persp\rightarrow ortho}=\begin{pmatrix}n&0&0&0\\0&n&0&0\\0&0&n+f&-nf\\0&0&1&0\end{pmatrix}\begin{pmatrix}0\\0\\\frac{n+f}2\\1\end{pmatrix}=\begin{pmatrix}0\\0\\n+f-\frac{2nf}{n+f}\\1\end{pmatrix}

比较 zpersportho=n+f2nfn+fz_{persp\rightarrow ortho}=n+f-\frac{2nf}{n+f}z=n+f2z=\frac{n+f}{2} 的大小:
假设 =zpersporthoz\triangle=z_{persp\rightarrow ortho}-z

=n+f22nfn+f=(n+f)24nf2(n+f)=(nf)22(n+f)\triangle=\frac{n+f}2-\frac{2nf}{n+f}=\frac{(n+f)^2-4nf}{2(n+f)}=\frac{(n-f)^2}{2(n+f)}

因为相机位置在原点,看向 -Z,应该有:f < n < 0,则 <0\triangle<0
也就是 zpersportho<zz_{persp\rightarrow ortho}<z,所以是变远了

事实上,对远近平面中间的任意点,可以类似以上证明得出结论:“挤压” 后都会变远。
[GAMES101] 投影变换和模型变换