3D 变换 (3D Transformation)

3D 变换(3D Transformation)

符号

本 note 里使用的是狄拉克符号:|r\rangle 表示列向量(等同于记号 \vec{r} 或者 \bm{r} 或点的三维坐标),\langle r| 表示行向量,\langle r|s\rangle 表示 |r\rangle|s\rangle 的内积,不难看出,这也是 \langle r||s\rangle 的矩阵乘法。默认 3D 坐标的正交基为 |x\rangle,|y\rangle,|z\rangle

平移、放缩和旋转

平移变换(translation):

  • 点坐标 (x,y,z)\rightarrow (x+t_1,y+t_2,z+t_3)
  • 不改变向量

放缩变换(scaling):

  • 点坐标 (x,y,z)\rightarrow (s_1*x,s_2*y,s_3*z)
  • 向量 (x,y,z)^T\rightarrow (s_1*x,s_2*y,s_3*z)^T

旋转变换(rotation):

绕任意轴旋转的公式推导如下:

  • 求解向量 |r\rangle 绕单位向量 |n\rangle 旋转角度 \alpha 的变换矩阵:
    • 首先把向量 |r\rangle 分解为沿着 |n\rangle 方向的分量 |r_{n}\rangle 和垂直于 |n\rangle 方向的分量 |r_{\bot}\rangle。运算过程如下:
      • |r_n\rangle =\langle n|r\rangle|n\rangle=|n\rangle \langle n|r\rangle
      • |r_{\bot}\rangle=|r\rangle-|r_n\rangle=(I-|n\rangle\langle n|)|r\rangle
    • 显然只有垂直于 |n\rangle 的分量会被旋转改变。现在考虑 |n\rangle\frac{|r_{\bot}\rangle}{|||r_{\bot}\rangle||}\frac{1}{|||r_{\bot}\rangle||}|n\rangle\times |r_{\bot}\rangle=\frac{1}{|||r_{\bot}\rangle||}|n\rangle\times |r\rangle 构成的右手坐标系 C'。在坐标系 C' 下,|r_{\bot}\rangle 的坐标为 \left (0,|||r_{\bot}\rangle||, 0\right )^T,其绕 |n\rangle 的旋转 \alpha 后(旋转矩阵即为绕 x 轴的旋转矩阵)的坐标即为 \left (0,\cos(\alpha)|||r_{\bot}\rangle||, sin(\alpha)|||r_{\bot}\rangle||\right )^T,转换为原坐标系后向量为:\cos(\alpha) |r_{\bot}\rangle+\sin(\alpha) |n\rangle\times |r\rangle
    • 至此已经得到 |r\rangle 旋转后的向量为:
      • |r_n\rangle+\cos(\alpha)|r_{\bot}\rangle+\sin(\alpha)|n\rangle\times|r\rangle=
      • [\cos(\alpha)I+(1-\cos(\alpha))|n\rangle\langle n|]|r\rangle+\sin(\alpha)|n\rangle\times |r\rangle
    • 其中 |n\rangle\times |r\rangle=\begin{pmatrix}0&-n_z&n_y\\n_z&0&-n_x\\-n_y&n_x&0\\\end{pmatrix}|r\rangle。则得到旋转矩阵:
    • R(|n\rangle,\alpha)=\cos(\alpha)I+(1-\cos(\alpha))|n\rangle\langle n|+\sin(\alpha)\begin{pmatrix}0&-n_z&n_y\\n_z&0&-n_x\\-n_y&n_x&0\\\end{pmatrix}

x,y,z 轴的旋转矩阵很容易得到,这里就不证了。

\begin{aligned} R(|x\rangle,\alpha)=\begin{pmatrix}1&0&0\\0&\cos(\alpha)&-\sin(\alpha)\\0&\sin(\alpha)&\cos(\alpha)\\\end{pmatrix} \\ R(|y\rangle,\alpha)=\begin{pmatrix}\cos(\alpha)&0&\sin(\alpha)\\ 0&1&0\\-\sin(\alpha)&0&\cos(\alpha)\\\end{pmatrix} \\ R(|z\rangle,\alpha)=\begin{pmatrix}\cos(\alpha)&-\sin(\alpha)&0\\\sin(\alpha)&\cos(\alpha)&0\\ 0&0&1\\\end{pmatrix} \end{aligned}

仿射变换(Affine Transformation)

首先,不难看出旋转和放缩都是线性的操作,故均可以表示为矩阵,而平移是非线性的(对于 position 点)。因此这三种操作的组合,即仿射变换需要写成 线性变换 + 平移项 的格式:

\begin{aligned} |r'\rangle=T_{linear}|r\rangle+|t\rangle \end{aligned}

齐次坐标(Homogenous Coordinates)

为了去掉仿射变换中的平移项,将这三种变换统一表示为矩阵形式,引入齐次坐标可以去除该平移项。将原本的坐标 (x,y,z)^T 扩展为 (x,y,z,w)^T 四维。w=0 时表示 3D 向量坐标 (x,y,z)^Tw\neq 0 时表示位置坐标 (x/w,y/w,z/w)^T。则仿射变换可以写成 4×4 的线性变换矩阵:

\begin{aligned} \begin{pmatrix} T_{linear} & |t\rangle \\ 0 & 1\\ \end{pmatrix} \end{aligned}

此处 T_{linear} 是 3×3 的矩阵。0 表示子矩阵元素全为 0。

观测变换(Viewing Transformation)

视图变换(View Transformation)

又可以叫相机变换(Camera Transformation),即把相机从当前位置 |e\rangle 移动到原点并调整方向,使得镜头朝向 |g\rangle(look-at direction)变得与 Z 轴负方向一致,且镜头向上方向 |t\rangle(up direction)与 Y 轴一致。

[图片]

不难看出,相机变换的矩阵为一个平移与旋转的组合:

\begin{aligned} M_{view} &=R_{view}T_{view} \\ T_{view} &= \begin{pmatrix}I & -|e\rangle\\ 0 & 1\end{pmatrix} \\ R_{view} &= |y\rangle\langle t|-|z\rangle\langle g|-|x\rangle(\langle t|\times \langle g|) \\ &=\begin{pmatrix}(\langle g|\times \langle t|)_x&(\langle g|\times \langle t|)_y&(\langle g|\times \langle t|)_z&0 \\t_x&t_y&t_z&0\\-g_x&-g_y&-g_z&0\\0&0&0&1\\\end{pmatrix} \end{aligned}

投影变换(Projection Transformation)

将物体从 3D 空间投影到 2D 画面,有正交投影(orthographic projection)和透视投影(perspective projection)两种。

[图片]

正交投影(Orthographic Projection)

  • 相机在原点,向-Z 轴看,up direction 为 Y
  • 物体 Z 轴被去掉
  • 平移缩放物体到范围(即 x 和 y 轴范围在-1 和 1 之间)

通常做法:将 [l,r]\times [b,t]\times [f,n] 范围的立方体,平移缩放到 [-1,1]^3 的标准立方体上。

\begin{aligned} M_{ortho}=\begin{pmatrix}\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{pmatrix} \begin{pmatrix}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{pmatrix} \end{aligned}

透视投影(Perspective Projection)

[图片]

相比正交投影,先多一步变换 M_{persp\rightarrow ortho}:把视锥体(frustum)"挤压"成立方体,并保证近平面上任意一点不变,远平面上 z 坐标不变(但是之间的平面 z 坐标会改变),不难看出该变换的作用是 (x,y,z)^T\rightarrow (nx/z,ny/z,z)^T,这种变换在 3D 坐标下不是线性的,无法写成矩阵。但引入齐次坐标后,(nx/z,ny/z,z,1)^T\Leftrightarrow (nx,ny,z^2,z)^T ,可以计算 M_{persp\rightarrow ortho}(x,y,z,1)^T=(nx,ny,z^2,z)^T 得到 M_{persp\rightarrow ortho} 的矩阵形式:

\begin{aligned} 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} \end{aligned}

通过 fovYaspect\_ratio 得到 l,r,b,t

之前使用 l(左边沿的 x 坐标),r(右边沿的 x 坐标),b(下边沿的 y 坐标),t(上边沿的 y 坐标)来表示近平面,此外我们还可以用垂直可视角度(field-of-view)fovY 和宽高比 aspect\_ratio 来表示。

[图片]

明显有:

\begin{aligned} t&=|n|\tan(\frac{fovY}{2}) \\ r&=t*aspect\_ratio \\ b&=-t,l=-r \end{aligned}
2 操作
mooncak 在 2025-09-17 08:39:40 更新了该帖
mooncak 在 2025-09-16 22:32:26 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...