最爱午后红茶

View transformations

日期图标
2023-04-14

我们前面所学的各种变换的目的,就是要把三维的物体变成一张照片。而给定一个三维场景,如果从不同方向看,看到的画面是不一样的。这跟我们真实生活中用相机拍照是类似的。而用相机拍照通常需要经过这三个步骤:

  • 找一个好地方并安排好被拍的人或物(Model transformation)
  • 找一个合适的位置和角度摆放好相机(View transformation)
  • “茄子”(Projection transformation)

其中摆放相机这个步骤就是我们所说的视图变换(View transformation),这三个步骤对应到图形学中是完全一样的,简称为 MVP 变换。而确定一个相机,需要确定三个变量:

  • 位置(Position):用 e\overrightarrow{e} 表示。
  • 朝向(Look-at/gaze direction):用 g^\hat{g} 表示方向。
  • Y 轴朝向(Up direction):用 t^\hat{t} 表示方向。确定位置和朝向后,可以通过旋转相机控制 Y 轴朝向,同时该轴要跟 Look-at 垂直。
相机的视图变换(View transformation)
图一:相机的视图变换

通常我们为了简化计算,会把相机固定在原点 (0, 0, 0) 的位置,同时使 Up-direction 对应 yy 轴,Look-at 朝向 zz方向(也就是 z-z 方向):

相机在三维坐标中的定义(Camera view)
图二:相机在三维坐标中的定义

如果相机不在原点,那我们需要先把相机转换到原点后才能继续后面的操作。而要使相机转换前后所拍摄到的场景保持不变,根据相对运动,我们需要把整个场景都做相应的转换。相机的转换对应到数学中分为以下几个过程:

  • 把代表位置的 e\overrightarrow{e} 平移到原点
  • 把朝向 g^\hat{g} 旋转到 z-z 方向
  • 把代表 Up-direction 的 t^\hat{t} 旋转到 yy
  • g×tg \times t 的方向自然也就对应到 xx
相机坐标转换(Camera mapping)
图三:相机坐标转换

我们记整个场景转换到原点的变换为 MviewM_{view},则有:

  • Mview=RviewTviewM_{view} = R_{view}T_{view}

注意这里顺序是先执行右边的平移变换 TviewT_{view},再执行旋转变换 RviewR_{view}。我们很容易得出齐次坐标下平移变换的矩阵:

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

而旋转矩阵 RviewR_{view} 要做的事情是把 g^\hat{g} 方向旋转到 z-z 轴,把 t^\hat{t} 方向旋转到 yy 轴,把 g×tg \times t 方向旋转到 xx 轴。直接求解 RviewR_{view} 不太好求,但如果把这个过程反过来,那就是把 xx 轴旋转到 g×tg \times t 方向,把 yy 轴旋转到 t^\hat{t} 方向,把 zz 轴旋转到 g^-\hat{g} 方向(这里不理解可以动笔画一画)。这个反过程的旋转矩阵是很好求解的,我们假设 xx 轴上的向量 X=(1,0,0)X = (1, 0, 0) 经过旋转矩阵 RiR_i 的变换后落在 g×tg \times t 方向上,假设是 Xg×t=(xg×t,yg×t,zg×t)X_{g \times t} = (x_{g \times t}, y_{g \times t}, z_{g \times t}),也就是 Xg×t=RiXX_{g \times t} = R_iX。我们很容易得出它们在齐次坐标下的表示:

  • [xg×tyg×tzg×t0]=[xg×t??0yg×t??0zg×t??00001][1000]\left[\begin{matrix}x_{g \times t}\\y_{g \times t}\\z_{g \times t}\\0\end{matrix}\right] = \left[\begin{matrix}x_{g \times t} & ? & ? & 0\\y_{g \times t} & ? & ? & 0\\ z_{g \times t} & ? & ? & 0\\ 0 & 0 & 0 & 1\end{matrix}\right]\left[\begin{matrix}1\\0\\0\\0\end{matrix}\right]

同样的,我们假设 yy 轴上的向量 Y=(0,1,0)Y = (0, 1, 0) 经过旋转矩阵 RiR_i 的变换后落在 t^\hat{t} 方向上,假设是 Yt=(xt,yt,zt)Y_t = (x_t, y_t, z_t),也就是 Yt=RiYY_t = R_iY。它们在齐次坐标下的表示是:

  • [xtytzt0]=[?xt?0?yt?0?zt?00001][0100]\left[\begin{matrix}x_t\\ y_t\\ z_t\\0\end{matrix}\right] = \left[\begin{matrix}? & x_t & ? & 0\\? & y_t & ? & 0\\? & z_t & ? & 0\\ 0 & 0 & 0 & 1\end{matrix}\right]\left[\begin{matrix}0\\1\\0\\0\end{matrix}\right]

最后,我们假设 zz 轴上的向量 Z=(0,0,1)Z = (0, 0, 1) 经过旋转矩阵 RiR_i 的变换后落在 g^-\hat{g} 方向上,假设是 Zg=(xg,yg,zg)Z_{-g} = (x_{-g}, y_{-g}, z_{-g}),也就是 Zg=RiZZ_{-g} = R_iZ。它们在齐次坐标下的表示是:

  • [xgygzg0]=[??xg0??yg0??zg00001][0010]\left[\begin{matrix}x_{-g}\\ y_{-g}\\ z_{-g}\\0\end{matrix}\right] = \left[\begin{matrix}? & ? & x_{-g} & 0\\? & ? & y_{-g} & 0\\? & ? & z_{-g} & 0\\ 0 & 0 & 0 & 1\end{matrix}\right]\left[\begin{matrix}0\\0\\1\\0\end{matrix}\right]

因为 RiR_i 要同时满足三个轴上的变换,所以有:

  • Ri=[xg×txtxg0yg×tytyg0zg×tztzg00001]R_i = \left[\begin{matrix}x_{g \times t} & x_t & x_{-g} & 0\\y_{g \times t} & y_t & y_{-g} & 0\\ z_{g \times t} & z_t & z_{-g} & 0\\ 0 & 0 & 0 & 1\end{matrix}\right]

RiR_i 的这个推导包含了我自己的理解,如果后面发现有错误再修正。我们知道 RviewR_{view}RiR_i 的反向(逆向)旋转,而从 2D transformations 中关于旋转那块描述我们知道,旋转矩阵是正交矩阵,因此 Rview=Ri1=RiTR_{view} = {R_i}^{-1} = {R_i}^T。所以求解出:

  • Rview=[xg×tyg×tzg×t0xtytzt0xgygzg00001]R_{view} = \left[\begin{matrix}x_{g \times t} & y_{g \times t} & z_{g \times t} & 0\\ x_t & y_t & z_t & 0\\ x_{-g} & y_{-g} & z_{-g} & 0\\ 0 & 0 & 0 & 1\end{matrix}\right]

所以有:

  • Mview=RviewTview=[xg×tyg×tzg×t0xtytzt0xgygzg00001][100xe010ye001ze0001]M_{view} = R_{view}T_{view} = \left[\begin{matrix}x_{g \times t} & y_{g \times t} & z_{g \times t} & 0\\ x_t & y_t & z_t & 0\\ x_{-g} & y_{-g} & z_{-g} & 0\\ 0 & 0 & 0 & 1\end{matrix}\right]\left[\begin{matrix}1 & 0 & 0 & -x_e\\0 & 1 & 0 & -y_e\\0 & 0 & 1 & -z_e\\0 & 0 & 0 & 1\end{matrix}\right]
* 未经同意不得转载。