「现代计算机图形学入门」矩阵变换
1. 2D变换矩阵
缩放矩阵(Scale) \[ \begin{bmatrix}x' \\ y'\end{bmatrix} = \begin{bmatrix}s_x & 0\\0 & s_y\end{bmatrix} \begin{bmatrix}x \\ y\end{bmatrix} \] 反射矩阵(Reflection) \[ \begin{bmatrix}x' \\ y'\end{bmatrix} = \begin{bmatrix}-1 & 0\\0 & -1\end{bmatrix} \begin{bmatrix}x \\ y\end{bmatrix} \] 切变矩阵(Shear) \[ \begin{bmatrix}x' \\ y'\end{bmatrix} = \begin{bmatrix}1 & a\\0 & 1\end{bmatrix} \begin{bmatrix}x \\ y\end{bmatrix} \] 旋转矩阵(Rotate):以(0,0)为中心,逆时针旋转 \[ \begin{bmatrix}x' \\ y'\end{bmatrix} = \begin{bmatrix}cos\theta & -sin\theta\\sin\theta & cos\theta\end{bmatrix} \begin{bmatrix}x \\ y\end{bmatrix} \] 平移矩阵(Translation):==平移变换不是线性变换!== \[ \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} \]
2. 齐次坐标
为了用统一的方式表示所有的变换,故引入齐次坐标。
增加一个维度下,二维点坐标:\((x, y, 1)\)、二维向量:\((x, y, 0)\)
对于增加的一个维度的有效操作:
- 向量 + 向量 = 向量
- 点 - 点 = 点
- 点 + 向量 = 点
- 点 + 点 = 两个点的中点
齐次坐标表示变换矩阵:
缩放矩阵 \[ S(s_x, s_y) = \begin{pmatrix}s_x & 0 & 0\\0 & s_y & 0 \\ 0 & 0 & 1\end{pmatrix} \] 旋转矩阵 \[ R(\alpha) = \begin{pmatrix}cos\alpha & -sin\alpha & 0\\sin\alpha & cos\alpha & 0 \\ 0 & 0 & 1\end{pmatrix} \] 平移矩阵 \[ T(t_x, t_y) = \begin{pmatrix}1 & 0 & t_x\\0 & 1 & t_y\\ 0 & 0 & 1\end{pmatrix} \] 组合变换(Composite):矩阵的应用从右到左 \[ A_n(...A_2(A_1(x))) = A_n \cdots A_2 · A_1 · \begin{pmatrix}x\\y\\1\end{pmatrix} \]
3. 三维旋转
组合 \(R_x, R_y, R_z\) 得到3D旋转:\(R_xyz(\alpha, \beta, \gamma) = R_x(\alpha)R_y(\beta)R_z(\gamma)\)。
这三个角被称为「欧拉角」,被飞机中称为:翻滚、俯仰、偏航。
罗德里格斯旋转公式:绕任意轴 \(n\) 旋转 \(\alpha\) 角,轴 \(n\) 过原点 \[ R(n, \alpha) = cos(\alpha)I + (1-cos(\alpha))nn^T + sin(\alpha) \underbrace{\begin{pmatrix}0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0\end{pmatrix}}_{N} \]
4. MVP变换
以照相为例,想想如何拍一张照:
- 找到一个地方和安置照相的对象(模型变换)
- 找到一个角度放置照相机(视图变换)
- 按下快门(投影变换)
4.1 视图变换
定义一个相机的参数:位置 \(\vec e\)(Position)、看的方向 \(\hat g\)(Look-at direction)、向上方向 \(\hat t\)(Up direction)
约定,将相机放置在原点,向上方向为 Y轴,看的方向为 -Z,其他物体随着相机一起进行相应的移动。
通过 \(M_{view}\) 矩阵将相机进行相应的变换:平移至原点,旋转 g 至 -Z,旋转 t 至 Y,旋转(g × t) 至 X。 \[ M_{view} = R_{view}T_{view}, \quad 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} \] 对于旋转矩阵 \(R_{view}\),由于直接写出太难,考虑其逆变换: X 至 (g × t),Y 至 t,Z 至 -g。 \[ R_{view}^{-1} = \begin{bmatrix}x_{\hat g × \hat t}&x_t&x_{-g}&0\\y_{\hat g × \hat t}&y_t&y_{-g}&0\\z_{\hat g × \hat t}&z_t&z_{-g}&0\\0&0&0&1 \end{bmatrix} \implies R_{view} = (R_{view}^{-1})^T \] 因为,旋转矩阵是正交矩阵,正交矩阵的逆等于其转置。
4.2 投影变换
正交投影
把一个立方体 \([l,r]×[b,t]×[f,n]\) 映射到规范立方体 \([-1,1]^3\)
注意,由于Camera看向 -Z 的原因,使得更近的物体Z值越大,\(n > f\) \[ M_{ortho} = \begin{bmatrix}\dfrac{2}{r-l} & 0 & 0 & 0\\ 0 & \dfrac{2}{t-b} & 0 & 0\\ 0 & 0 & \dfrac{2}{n-f} & 0\\0 & 0 & 0 & 1\end{bmatrix} \begin{bmatrix}1 & 0 & 0 & -\dfrac{r+l}{2} \\ 0 & 1 & 0 & -\dfrac{t+b}{2}\\ 0 & 0 & 1 & -\dfrac{n+f}{2}\\ 0 & 0 & 0 & 1\end{bmatrix} \]![](\images\orthoProject.png)
图1 归一化到单位立方体
透视投影
如何做透视投影?
第一步:把左边棱体挤成右边的立方体;
第二步:做正交投影;
![](\images\frustum_to_cuboid.png)
图2 将frustum挤成cuboid
规定几点,在挤的过程中:
- 近平面永远不变
- 远平面的Z值不会变化,中心不会变化
为了找到将棱体挤压成立方体的变换矩阵,我们要找到经过变换后的点 \((x',y',z')\) 和 原来的点 \((x,y,z)\) 之间的关系。
![](\images\transformPoints.png)
图3 寻找点之间的变换关系
同理,有 \(x' = \dfrac{n}{z}y\),在齐次坐标系中,原来的点经过变换后变为: \[ \begin{pmatrix}x\\y\\z\\1\end{pmatrix}=\begin{pmatrix}nx/z\\ny/z\\unknown\\1\end{pmatrix}==\begin{pmatrix}nx\\ny\\still\ unknown\\z\end{pmatrix} \] 故变换矩阵 \(M_{persp\rightarrow ortho}\) 做出如下变换: \[ M_{persp\rightarrow ortho}\begin{pmatrix}x\\y\\z\\1\end{pmatrix}=\begin{pmatrix}nx\\ny\\unknown\\z\end{pmatrix} \implies M_{persp\rightarrow ortho} = \begin{pmatrix}n&0&0&0\\0&n&0&0\\?&?&?&?\\0&0&1&0\end{pmatrix} \] 经规定我们知道,在挤压过程中有不会变的:
- 在近平面上的任何点不会改变
\[ \begin{pmatrix}x\\y\\z\\1\end{pmatrix} \Rightarrow \begin{pmatrix}x\\y\\n\\1\end{pmatrix} == \begin{pmatrix}nx\\ny\\n^2\\n\end{pmatrix} \]
所以,\(M_{persp\rightarrow ortho}\) 第三行一定是 \((0\ 0\ A\ B)\) 这种形式。即: \[ \begin{pmatrix}0 & 0 & A & B\end{pmatrix} \begin{pmatrix}x\\y\\n\\1\end{pmatrix} = n^2 \tag{1} \]
- 在远平面上的任何点的Z值不会改变
\[ \begin{pmatrix}0\\0\\f\\1\end{pmatrix} \Rightarrow \begin{pmatrix}0\\0\\f\\1\end{pmatrix} == \begin{pmatrix}0\\0\\f^2\\f\end{pmatrix} \]
故有: \[ \begin{pmatrix}0 & 0 & A & B\end{pmatrix} \begin{pmatrix}0\\0\\f\\1\end{pmatrix} = f^2 \tag{2} \] 联立(1)和(2)式可以解出: \[ A = n + f \\ B = -nf \] 定义透视投影的两个概念:fovY(field-of-view 垂直的可视角度) 和 aspect ratio (长宽比)
![](\images\fov_aspect.png)