Skip to content

Lecture 4: Transformation Continued

3D变换

复习上一节的齐次坐标,三维空间中的齐次坐标表示为四维向量。对于三维点,齐次坐标可以表示为 \((x, y, z, 1)^T\);对于三维向量,齐次坐标可以表示为 \((x, y, z, 0)^T\)

对于坐标\((x, y, z, w)\),代表的点为\((x/w, y/w, z/w)\)

使用四维矩阵可以表示三维空间中的变换:

\[ \begin{bmatrix}a & b & c & T_x \\d & e & f & T_y \\g & h & i & T_z \\ 0 & 0 & 0 & 1\end{bmatrix} \]

Scale可以表示为:

\[ \begin{bmatrix}S_x & 0 & 0 & 0 \\ 0 & S_y & 0 & 0 \\ 0 & 0 & S_z & 0 \\ 0 & 0 & 0 & 1\end{bmatrix} \]

Translate可以表示为:

\[ \begin{bmatrix}1 & 0 & 0 & T_x \\ 0 & 1 & 0 & T_y \\ 0 & 0 & 1 & T_z \\ 0 & 0 & 0 & 1\end{bmatrix} \]

绕x, y, z轴的旋转可以表示为:

\[ \begin{bmatrix}1 & 0 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta & 0 \\ 0 & \sin\theta & \cos\theta & 0 \\ 0 & 0 & 0 & 1\end{bmatrix}, \quad \begin{bmatrix}\cos\theta & 0 & \sin\theta & 0 \\ 0 & 1 & 0 & 0 \\ -\sin\theta & 0 & \cos\theta & 0 \\ 0 & 0 & 0 & 1\end{bmatrix}, \quad \begin{bmatrix}\cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta & \cos\theta & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1\end{bmatrix} \]

绕y轴旋转时,-sinθ和sinθ的符号和其他两个轴的旋转相反。

组合三种旋转可以得到:

\[ R_{xyz}(\theta_x, \theta_y, \theta_z) = R_x(\theta_x) R_y(\theta_y) R_z(\theta_z) \]

Rodrigues' rotation formula:

\[ R(n, \alpha) = \cos(\alpha)I + (1 - \cos(\alpha))nn^T + \sin(\alpha)\begin{bmatrix}0 & -n_z & n_y \\n_z & 0 & -n_x \\-n_y & n_x & 0 \end{bmatrix} \]

其中\(n\)是旋转轴的单位向量,\(\alpha\)是旋转角度。

罗德里格旋转公式推导 (AI生成)

目标

推导一个向量 \(\mathbf{v}\) 绕一个单位向量旋转轴 \(\mathbf{n}\) 旋转角度 \(\alpha\) 后的新向量 \(\mathbf{v}_{\text{rot}}\) 的计算公式,并最终表示为旋转矩阵 \(\mathbf{R}\) 的形式。

最终的矩阵形式为:

\[ \mathbf{R}(\mathbf{n}, \alpha) = \cos(\alpha)\mathbf{I} + (1 - \cos(\alpha))\mathbf{n}\mathbf{n}^T + \sin(\alpha)(\mathbf{n})_{\times} \]

其中 \([\mathbf{n}]_{\times}\)\(\mathbf{n}\) 的斜对称叉积矩阵。


核心思想:向量分解

推导此公式最直观的方法,是先将向量 \(\mathbf{v}\) 分解为两个相互正交(垂直)的分量:

  1. 平行于旋转轴 \(\mathbf{n}\) 的分量,记为 \(\mathbf{v}_{\parallel}\)
  2. 垂直于旋转轴 \(\mathbf{n}\) 的分量,记为 \(\mathbf{v}_{\perp}\)

很显然,我们有:

\[ \mathbf{v} = \mathbf{v}_{\parallel} + \mathbf{v}_{\perp} \]

在旋转过程中,只有垂直分量 \(\mathbf{v}_{\perp}\) 会发生改变,而平行分量 \(\mathbf{v}_{\parallel}\) 将保持不变。


第一步:计算向量分量

  • 平行分量 \(\mathbf{v}_{\parallel}\)

    该分量是向量 \(\mathbf{v}\) 在单位轴向量 \(\mathbf{n}\) 上的投影。根据向量投影的定义:

    \[ \mathbf{v}_{\parallel} = (\mathbf{v} \cdot \mathbf{n}) \mathbf{n} \]

    其中 \((\mathbf{v} \cdot \mathbf{n})\) 是一个标量。

  • 垂直分量 \(\mathbf{v}_{\perp}\)

    该分量可以由原始向量减去平行分量得到:

    \[ \mathbf{v}_{\perp} = \mathbf{v} - \mathbf{v}_{\parallel} = \mathbf{v} - (\mathbf{v} \cdot \mathbf{n}) \mathbf{n} \]

第二步:旋转垂直分量

现在,我们需要将 \(\mathbf{v}_{\perp}\) 在垂直于 \(\mathbf{n}\) 的平面内旋转角度 \(\alpha\),得到旋转后的向量 \(\mathbf{v}_{\perp, \text{rot}}\)

在这个旋转平面内,我们需要一组正交基来描述旋转。我们已经有了 \(\mathbf{v}_{\perp}\),还需要一个与它垂直且长度相等的向量。我们可以通过叉积巧妙地构造出这个向量:

\[ \mathbf{w} = \mathbf{n} \times \mathbf{v} \]

这个向量 \(\mathbf{w}\) 位于旋转平面内,且与 \(\mathbf{v}_{\perp}\) 垂直。它的长度 \(|\mathbf{w}| = |\mathbf{n}| |\mathbf{v}| \sin(\theta) = |\mathbf{v}_{\perp}|\) (其中 \(\theta\)\(\mathbf{n}\)\(\mathbf{v}\) 的夹角),与 \(\mathbf{v}_{\perp}\) 的长度相等。

注:这里用 \(\mathbf{n} \times \mathbf{v}\) 而非 \(\mathbf{n} \times \mathbf{v}_{\perp}\) 是因为二者结果相同且前者更直接。因为 \(\mathbf{n} \times \mathbf{v} = \mathbf{n} \times (\mathbf{v}_{\parallel} + \mathbf{v}_{\perp}) = (\mathbf{n} \times \mathbf{v}_{\parallel}) + (\mathbf{n} \times \mathbf{v}_{\perp})\),而 \(\mathbf{n} \times \mathbf{v}_{\parallel} = \mathbf{0}\)

有了旋转平面内的一对正交基 \(\mathbf{v}_{\perp}\)\(\mathbf{w}\),我们可以利用标准的二维旋转公式来表示旋转后的向量:

\[ \mathbf{v}_{\perp, \text{rot}} = \cos(\alpha) \mathbf{v}_{\perp} + \sin(\alpha) \mathbf{w} \]

\(\mathbf{w} = \mathbf{n} \times \mathbf{v}\) 代入,我们得到:

\[ \mathbf{v}_{\perp, \text{rot}} = \cos(\alpha) \mathbf{v}_{\perp} + \sin(\alpha) (\mathbf{n} \times \mathbf{v}) \]

第三步:合并分量得到向量公式

最终的旋转向量 \(\mathbf{v}_{\text{rot}}\) 是旋转后平行分量与垂直分量的和。由于平行分量不变,即 \(\mathbf{v}_{\parallel, \text{rot}} = \mathbf{v}_{\parallel}\),我们有:

\[ \mathbf{v}_{\text{rot}} = \mathbf{v}_{\parallel, \text{rot}} + \mathbf{v}_{\perp, \text{rot}} = \mathbf{v}_{\parallel} + \mathbf{v}_{\perp, \text{rot}} \]

将前面推导出的表达式代入:

\[ \mathbf{v}_{\text{rot}} = (\mathbf{v} \cdot \mathbf{n}) \mathbf{n} + \cos(\alpha) \mathbf{v}_{\perp} + \sin(\alpha) (\mathbf{n} \times \mathbf{v}) \]

再将 \(\mathbf{v}_{\perp} = \mathbf{v} - (\mathbf{v} \cdot \mathbf{n}) \mathbf{n}\) 代入:

\[ \mathbf{v}_{\text{rot}} = (\mathbf{v} \cdot \mathbf{n}) \mathbf{n} + \cos(\alpha) \left( \mathbf{v} - (\mathbf{v} \cdot \mathbf{n}) \mathbf{n} \right) + \sin(\alpha) (\mathbf{n} \times \mathbf{v}) \]

展开并重新组合各项,得到罗德里格旋转公式的 向量形式:

\[ \mathbf{v}_{\text{rot}} = \cos(\alpha)\mathbf{v} + (1 - \cos(\alpha))(\mathbf{v} \cdot \mathbf{n})\mathbf{n} + \sin(\alpha)(\mathbf{n} \times \mathbf{v}) \]

第四步:转换为矩阵形式

我们的目标是找到一个旋转矩阵 \(\mathbf{R}\),使得 \(\mathbf{v}_{\text{rot}} = \mathbf{R}\mathbf{v}\)。为此,我们将向量形式公式中的每一项都改写为矩阵与向量 \(\mathbf{v}\) 的乘积。

  1. 第一项:

    \[ \cos(\alpha)\mathbf{v} = (\cos(\alpha)\mathbf{I})\mathbf{v} \]

    其中 \(\mathbf{I}\) 是 3x3 单位矩阵。

  2. 第二项:

    \[ (1 - \cos(\alpha))(\mathbf{v} \cdot \mathbf{n})\mathbf{n} = (1 - \cos(\alpha))(\mathbf{n}\mathbf{n}^T)\mathbf{v} \]

    这里利用了 \((\mathbf{v} \cdot \mathbf{n}) = \mathbf{n}^T \mathbf{v}\),所以 \((\mathbf{v} \cdot \mathbf{n})\mathbf{n} = \mathbf{n}(\mathbf{n}^T\mathbf{v}) = (\mathbf{n}\mathbf{n}^T)\mathbf{v}\)。其中 \(\mathbf{n}\mathbf{n}^T\) 是一个 3x3 矩阵 (外积)。

  3. 第三项:

    \[ \sin(\alpha)(\mathbf{n} \times \mathbf{v}) = (\sin(\alpha)(\mathbf{n})_{\times})\mathbf{v} \]

    叉积运算 \(\mathbf{n} \times \mathbf{v}\) 可以等价地表示为一个斜对称矩阵 \([\mathbf{n}]_{\times}\) 左乘向量 \(\mathbf{v}\)。该矩阵定义为:

    \[ [\mathbf{n}]_{\times} = \begin{bmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \end{bmatrix} \]

现在,将这三项的矩阵形式代回 \(\mathbf{v}_{\text{rot}}\) 的表达式中:

\[ \mathbf{v}_{\text{rot}} = (\cos(\alpha)\mathbf{I})\mathbf{v} + \left( (1 - \cos(\alpha))\mathbf{n}\mathbf{n}^T \right)\mathbf{v} + (\sin(\alpha)(\mathbf{n})_{\times})\mathbf{v} \]

从右侧提出公因子 \(\mathbf{v}\):

\[ \mathbf{v}_{\text{rot}} = \left[ \cos(\alpha)\mathbf{I} + (1 - \cos(\alpha))\mathbf{n}\mathbf{n}^T + \sin(\alpha)(\mathbf{n})_{\times} \right] \mathbf{v} \]

因此,我们得到了最终的旋转矩阵 \(\mathbf{R}\):

\[ \mathbf{R}(\mathbf{n}, \alpha) = \cos(\alpha)\mathbf{I} + (1 - \cos(\alpha))\mathbf{n}\mathbf{n}^T + \sin(\alpha)\begin{bmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \end{bmatrix} \]

证明完毕。

视图变换和投影变换

View/Camera Transformation

相机的定义:

  • 相机位置:\(e = (e_x, e_y, e_z)\)
  • 相机方向:\(g = (g_x, g_y, g_z)\)
  • 相机上方方向:\(t = (t_x, t_y, t_z)\)

将相机位置和方向固定在原点和特定方向上,可以简化变换。(如朝向-z轴,向上为y轴)

投影变换

正交投影

正交投影是将三维物体投影到二维平面上的一种方法。它保留了物体的形状和大小,但不保留深度信息。

先把模型包围盒映射到标准立方体[-1, 1],然后丢弃z坐标。

映射使用的矩阵为:

\[ 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} \]

透视投影

透视投影是将三维物体投影到二维平面上的另一种方法。它保留了物体的深度信息,但会改变物体的形状和大小,基本特点是近大远小。

需要一个矩阵\(M_{persp->ortho}\)将透视投影转换为正交投影:

\[ M_{persp->ortho} = \begin{bmatrix}n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n + f & -nf \\ 0 & 0 & 1 & 0\end{bmatrix} \]

其中n是近平面,f是远平面。