Games101-Lecture 04 Transformation Cont

重点归纳:

  1. 3D 变换 (以旋转为重点):
    • 绕 x, y, z 轴旋转矩阵的差别,循环对称性 (列向量顺序问题)
    • 旋转的分解以及欧拉角,Rodrigues' Rotation Formula(绕过原点的轴的旋转)
    • 四元数,主要为了旋转间的差值 (课程无), 因为旋转矩阵不太适合作差值,三角函数不是线性的,(15 + 25)/2 != 20
  2. Viewing 变换:
    • View(视图)/Camera 变换
    • 3D 到 2D 的投影变换 (Orthographic/Perspective, 正交/透视)
  3. View 变换
    • 标准相机位置的定义
    • 相机和模型的一起变换
  4. 投影变换
    • 正交投影,无近大远小
    • 简单的正交投影方法和常用的正交投影方法
    • 透视投影,平行线会相交,可以分解成"挤压"变换和正交投影变换
    • "挤压"变换的推导

一、3D 变换

1. 3D 缩放 (Scale)

S(sx,sy,sz)=(sx0000sy0000sz00001)\large \mathbf{S}\left(s_{x}, s_{y}, s_{z}\right)=\left(\begin{array}{cccc}s_{x} & 0 & 0 & 0 \\ 0 & s_{y} & 0 & 0 \\ 0 & 0 & s_{z} & 0 \\ 0 & 0 & 0 & 1\end{array}\right)

2. 3D 平移 (Translation)

T(tx,ty,tz)=(100tx010ty001tz0001)\large \mathbf{T}\left(t_{x}, t_{y}, t_{z}\right)=\left(\begin{array}{cccc}1 & 0 & 0 & t_{x} \\0 & 1 & 0 & t_{y} \\0 & 0 & 1 & t_{z} \\0 & 0 & 0 & 1\end{array}\right)

3. 3D 旋转

绕坐标轴旋转

(1) 绕 x 轴旋转

Rx(α)=(10000cosαsinα00sinαcosα00001)\large \mathbf{R}_{x}(\alpha)=\left(\begin{array}{cccc}1 & 0 & 0 & 0 \\ 0 & \cos \alpha & -\sin \alpha & 0 \\ 0 & \sin \alpha & \cos \alpha & 0 \\ 0 & 0 & 0 & 1\end{array}\right)

(2) 绕 y 轴旋转

Ry(α)=(cosα0sinα00100sinα0cosα00001)\large \mathbf{R}_{y}(\alpha)=\left(\begin{array}{cccc}\cos \alpha & 0 & \sin \alpha & 0 \\ 0 & 1 & 0 & 0 \\ -\sin \alpha & 0 & \cos \alpha & 0 \\ 0 & 0 & 0 & 1\end{array}\right)

(3) 绕 z 轴旋转

Rz(α)=(cosαsinα00sinαcosα0000100001)\large \mathbf{R}_{z}(\alpha)=\left(\begin{array}{cccc}\cos \alpha & -\sin \alpha & 0 & 0 \\ \sin \alpha & \cos \alpha & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1\end{array}\right)

Q: 只有绕 y 轴旋转时,二维旋转矩阵是转置形式,为什么?

A: 分析如下矩阵乘法,其在形式上与上面的绕 y 轴旋转一致

Rα[xz]=[cosαsinαsinαcosα][xz]\large \mathbf{R}_{-\alpha} \cdot \left[\begin{array}{l}x \\z\end{array}\right]=\left[\begin{array}{cc}\cos \alpha & \sin \alpha \\ -\sin \alpha & \cos \alpha\end{array}\right] \cdot \left[\begin{array}{l}x \\z\end{array}\right]

而其几何含义是对于 xz 平面上的点,将其沿 x 轴向 z 轴方向旋转α\large -\alpha 角度
即沿 z 轴向 x 轴方向旋转 α\large \alpha角度,也就是沿 y 轴旋转 α\large \alpha 角度;

反过来推导,想要表达绕 y 轴旋转 α\large \alpha 角度,就应该写成

Rα[zx]=[cosαsinαsinαcosα][zx]\large \mathbf{R}_{\alpha} \cdot \left[\begin{array}{l}z \\x\end{array}\right]=\left[\begin{array}{cc}\cos \alpha & -\sin \alpha \\ \sin \alpha & \cos \alpha\end{array}\right] \cdot \left[\begin{array}{l}z \\x\end{array}\right]

那么写成和绕 x、z 轴旋转一样的形式,就相当于沿 x 轴向 z 轴方向旋转α\large -\alpha 角度,也就是上面的样子;

以上体现了循环对称性,x -> yz, y->zx, z->xy , 可以看到只有 y -> zx 和列向量 (x,y,z)T\large (x, y, z)^T 的顺序是反的,所以旋转矩阵也是逆变换

任意旋转都可以分解成绕 x、y、z 轴的旋转

Rxyz(α,β,γ)=Rx(α)Ry(β)Rz(γ)\large R_{x y z}(\alpha, \beta, \gamma)=R_{x}(\alpha) R_{y}(\beta) R_{z}(\gamma)

  • 四元数就是这种形式
  • 本课程不会涉及四元数
  • 四元数的旋转表示,主要为了作旋转间的差值,因为旋转矩阵不太适合作差值,三角函数不是线性的,15 度的旋转矩阵 + 25 度的旋转矩阵 / 2 != 20 度的旋转矩阵

绕过原点的任意轴旋转 (Rodrigues' Rotation Formula, R(n,α)\large R(\vec{n},\alpha))

R(n,α)=cos(α)I+(1cos(α))nnT+sin(α)(0nznynz0nxnynx0)N\large \mathbf{R}(\mathbf{n}, \alpha)=\cos (\alpha) \mathbf{I}+(1-\cos (\alpha)) \mathbf{n} \mathbf{n}^{T}+\sin (\alpha) \underbrace{\left(\begin{array}{ccc}0 & -n_{z} & n_{y} \\n_{z} & 0 & -n_{x} \\ -n_{y} & n_{x} & 0\end{array}\right)}_{\mathbf{N}}

为了表示任意的旋转,可以:

平移到原点 -> 绕过原点的任意轴旋转 -> 平移回去

二、Viewing(观测) 变换

老师将 Viewing 中文翻译成观测

分为两个步骤:

(1) View(视图)/Camera(相机) 变换 (2) 3D 到 2D 的投影变换

Orthographic/Perspective Projection, 正交/透视投影

  • MVP 变换:Model -> View -> Projection
  • Model -> View 合称 ModelView Transformation, 因为 View 变换实际上是对相机和模型一起的变换
  • View -> Projection 合称 Viewing 变换

1. 视图 (View)/相机 (Camera) 变换

(1) 定义相机的位置 e\large \vec{e}、朝向 (Look-at/gaze) g^\large \hat{g} 以及向上方向 t^\large \hat{t}

向上方向是为了确定相机的正倒

(2) 将相机和 Model 同时移动到标准位置,Mview=RviewTview\large M_{view}=R_{view}T_{view}

你动我也动相当于没动

  • 相机标准位置:up at Y , look at -Z

    这个标定位置是约定俗成的,OpenGL 用的也是这个位置

  • 先平移到原定,Tview\large T_{view}:

Tview =[100xe010ye001ze0001]\large T_{\text {view }}=\left[\begin{array}{cccc}1 & 0 & 0 & -x_{e} \\0 & 1 & 0 & -y_{e} \\0 & 0 & 1 & -z_{e} \\0 & 0 & 0 & 1\end{array}\right]

  • 再旋转,Rview\large R_{view}:

Rview =[xg^×t^yg^×t^zg^×t^0xtytzt0xgygzg00001]\large R_{\text {view }}=\left[\begin{array}{cccc}x_{\hat{g} \times \hat{t}} & y_{\hat{g} \times \hat{t}} & z_{\hat{g} \times \hat{t}} & 0 \\x_{t} & y_{t} & z_{t} & 0 \\x_{-g} & y_{-g} & z_{-g} & 0 \\0 & 0 & 0 & 1\end{array}\right]

Mview\large M_{view}的推导:
旋转 (g^×t^)\large (\hat{g} \times \hat{t}) to X\large \vec{X}, t^\large \hat{t} to Y\large \vec{Y}, g^\large -\hat{g} to Z\large \vec{Z}
由于相机坐标系矩阵是一个正交矩阵,所以其逆等于转置

2. 投影 (Projection) 变换

正交 (Orthographic) 投影

(1) 直接去掉 z 轴 (实际上不用这种方法)

(2) 确定一个视野范围,然后把该范围变换 (标准化) 为原点的一个 2 x 2 x 2 的立方体

Mortho =[2rl00002tb00002nf00001][100r+l2010t+b2001n+f20001]\large M_{\text {ortho }}=\left[\begin{array}{cccc}\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{array}\right]\left[\begin{array}{cccc}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{array}\right]

  • 先平移再缩放
  • 正交投影变换的过程会使物体被拉伸,后面的还有视口变换

透视 (Perspective) 投影

  • 透视投影变换可以先把四棱台"挤压"成一个长方体,再使用正交投影变换得到标准化的立方体
  • 这个"挤压"操作要保证两点:
    • 近、远平面的 z 轴不会变
    • 远平面的中心不会变
    • 近平面的每个点都不变
  • 注意四棱台上的点的 z 轴在"挤压"过程中是会变化的

这个"挤压"变换可以定义成 Mpersp>ortho\large M_{persp->ortho}, 则投影变换为 Mpersp=MorthoMpersp>ortho\large M_{persp}=M_{ortho}M{persp->ortho}

重点就是推导这个"挤压"操作的变换矩阵,Mpersp>ortho\large M_{persp->ortho}

推导:
Mpersp>ortho(x,y,z,1)T=(x,y,z,1)T\large M_{persp->ortho} \cdot (x, y, z, 1)^T=(x^{\prime}, y^{\prime}, z^{\prime}, 1)^T
为了得到Mpersp>ortho\large M_{persp->ortho}, 就需要知道 x\large xx\large x^{\prime}, y\large yy\large y^{\prime} , z\large zz\large z^{\prime}的关系
前两者的关系根据相似三角形很容易得到 (下图中手画的两个点,上方的是"挤压"前的位置 (x,y)\large (x, y), 下方的是"挤压"后的位置 (x,y)\large (x^{\prime}, y^{\prime})) 写成齐次坐标

(xyz1)(nx/zny/z unknown 1)==(nxny still unknown z)\left(\begin{array}{l}x \\y \\z \\1\end{array}\right) \Rightarrow\left(\begin{array}{c}n x / z \\n y / z \\ \text{ unknown } \\1\end{array}\right)==\left(\begin{array}{c}n x \\n y \\ \text{ still unknown } \\z\end{array}\right)

然后可以推得

Mpersp  ortho =(n0000n00????0010)\large M_{\text {persp } \rightarrow \text { ortho }}=\left(\begin{array}{cccc}n & 0 & 0 & 0 \\0 & n & 0 & 0 \\ ? & ? & ? & ? \\0 & 0 & 1 & 0\end{array}\right)

利用远平面上中点不变,和近平面上各点不变可得 (后面我就直接放 ppt 的图了) > >

Q :"挤压"操作究竟是让 z 变小还是变大

A : 答案是 z 会向 f 面靠近

上面推导了透视投影的"挤压"矩阵:

Mpersp  ortho =(n0000n0000n+fnf0010)\large M_{\text {persp } \rightarrow \text { ortho }}=\left(\begin{array}{cccc}n & 0 & 0 & 0 \\0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\0 & 0 & 1 & 0\end{array}\right)

故有:

Mpersp  ortho (xyz1)=(n0000n0000n+fnf0010)(xyz1)=(nxny(n+f)znfz)\large M_{\text {persp } \rightarrow \text { ortho }} \cdot \left(\begin{array}{l}x \\y \\z \\1\end{array}\right) =\left(\begin{array}{cccc}n & 0 & 0 & 0 \\0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\0 & 0 & 1 & 0\end{array}\right) \cdot \left(\begin{array}{l}x \\y \\z \\1\end{array}\right) = \left(\begin{array}{c}nx \\ ny \\ (n+f)z-nf \\ z \end{array}\right)

那么,比较 (n+f)znfz\large \frac{(n+f)z - nf}{z}z\large z 的大小即可,又因为

fzn<0\large f \leq z \leq n < 0

z(n+f)znfz>0\large z - \frac{(n+f)z - nf}{z} > 0

则说明变换后 z 值更靠近 f 面,离原点变远了,上式变形得

z2(n+f)z+nfz>0\large \frac{z^2 - (n+f)z + nf}{z} > 0

z2(n+f)z+nf<0\large z^2 - (n+f)z + nf < 0

(zn)(zf)<0\large (z-n)(z-f) < 0

(zn)(zf)\large (z-n)(z-f) 是小于等于 0 的,所以挤压变换后 z 会靠近 f 面

Games101-Lecture 05 Rasterization 1 (Triangles)
Games101-Lecture 03 Transformation