games101计算机图形学入门 (三)模型、视图、投影

本节课续上一课,上一课我们研究了2D平面的变换,这节课,我们转向到3D的情况,学习,视图(view),投影(projection),正交(orthographic),透视(perspective);

阅读材料:第 6 章(Transformation Matrices),第 6.2、6.4、6.5 节;第 7 章(Viewing)

变换

缩放

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

平移

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

三维之中的旋转

绕x轴

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

绕y轴

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

绕z轴

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

ps : 绕哪个轴转,哪个轴的对角线值为1

图片

对于一个任意旋转

​ 大家是否还记得上一节课,我们对于绕任意一点进行旋转的处理呢?

​ 没错,在这里,我们同样借用了上一节的思想,对于绕任意轴旋转这样复杂的变换,我们一定可以将其分解为绕xyz轴旋转矩阵的结合。这样,我们就得到了罗德里德斯旋转公式。

为什么只是简单定义一个向量来表示旋转轴呢?

因为对于任意轴,我们都可以将其平移到原点,在对他进行旋转,所以可以只用一个向量来表示旋转轴

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

罗德里德斯公式推导

ps本课不介绍四元数

​ 四元数在现在也在广泛应用,因为对于这样的一个旋转矩阵,我们是无法进行插值的,而在图形学中,为了将离散的数据连续化,我们会经常使用到插值,以及插值的思想,而四元数,是可以进行插值的

视图(view)

​ 回到我们的主题,学习这些变换,我们是为了处理图形投影之中的一些问题,思考 怎样拍一张照片?

  • 安排被拍照人员位置
  • 放好相机
  • 拍照

在图形学的成像过程,同样也是这样的三部,而第一步就是view(视图变换)

对相机进行定义
  • position 位置
\[
\vec{e}
\]
  • look at 观察的方向
\[
\hat{g}
\]
  • up direction 向上的方向
\[
\hat{t}
\]

图片

​ 对比物理之中的相对位置,如果2个物体一同移动了同样的位移,那么,2个物体是相对静止的,不变的。那么,我们可以不可以将相机永远放在一个位置?方便我们进行后续的计算。

图片

以此作为推论,我们假设让相机永远在原点,相机永远对着-z轴看,相机上方向永远为y轴正方向,那么要怎么操作呢?

  • 将相机移动到中心
\[
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]
\]
  • 将三个轴,分别旋转到x,y,z

大家可以设想一下,让t旋转到y,g旋转到-z方向,e自然就对到x

​ 很显然,这是可以实现的,但是却不是那么的好写出他的矩阵,我们不如回想一下前一节课的内容:对于二维图形的旋转,没错,我们不需要直接求出该旋转矩阵,我们只需要求出从x->e,y->t,-z->g,在对他进行转置,得到的就是我们需要的矩阵

\[
R_{v i e w}^{-1}=\left[\begin{array}{cccc}
x_{\hat{g} \times \hat{t}} & x_{t} & x_{-g} & 0 \\
y_{\hat{g} \times \hat{t}} & y_{t} & y_{-g} & 0 \\
z_{\hat{g} \times \hat{t}} & z_{t} & z_{-g} & 0 \\
0 & 0 & 0 & 1
\end{array}\right]
\] \[
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]
\]

至此,我们已经可以将摄像机从任意一点移回原点,并且规范化

投影 (projection)

正交投影(orthographic projection) 与 透视投影(perspective projection)

图片

本质 区别:正交投影不会带来近大远小的视觉效果

反应在数学上,我们应该怎么去理解这样的情况呢?

图片

正交投影

​ 对于正交投影,我们有简单粗暴的办法,直接将z值给去掉(用于理解)

​ 对于图形学,我们用更为直接的方式来实现,给我们一个空间中的长方体,立方体,我们都能对他进行操作,达成正则(规范)化成一个[-1,1]三次方的一个立方体

图片

​ 我们为了方便计算,使得x叉乘y要等于z,使用了右手系。这样带来了一些问题,对于这个图来说,z轴上,我们定义了远近,但是我们面向的是-z方向,z大的离我们进,z小的离我们远。

​ 实际操作的变换矩阵 : 移动到原点,再进行缩放

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

至此,我们实现了正交投影

透视投影

引入:在欧式几何里,我们都知道,平行线是永不相交的,但是,从图形中,我们看到了两条平行线出现了相交,这就是黎曼几何所研究的部分

图片


透视投影和平行投影有什么区别?

透视投影的远平面比近平面的大小是不一样的,而正交投影的远平面和近平面是一样的。

​ 那么我们是不是想办法先把透视投影转化为正交投影呢?答案是肯定的,只要使得近平面和远平面之间的空间进行挤压,那么我们就能得到透视投影

图片

​ 在得到矩阵前,我们先进行几个定义

  • 近平面永远不发生变化
  • 远平面的中心点变化后还在中心
  • 远平面的z值是不会发生变化的

​ 那么现在,我们就可以开始推导透视变换矩阵了

图片

​ 我们观察这个图形,可以,有2个值应该是能很快就可以计算得出的,既x,y的变换,是可以快速推导出的,这个三角形是一个相似三角形,由此推出

\[
y^{\prime}=\frac{n}{z} y \quad x^{\prime}=\frac{n}{z} x
\]

​ 目前,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)
\]

​ 我们还记得我们定义的运算可以得出

\[
\Rightarrow\left(\begin{array}{c}
n x \\
n y \\
\text { unknown } \\
z
\end{array}\right)
\]

​ 我们不如从得出的结果,来推导运算的矩阵
​ 第一,二,四行的推导相对容易,因为我们知道,对应的x,y,z的变换

\[
\left(\begin{array}{l}
x \\
y \\
z \\
1
\end{array}\right)\Rightarrow\left(\begin{array}{c}
n x \\
n y \\
\text { unknown } \\
z
\end{array}\right)
\]

​ 从而得到变换矩阵的对应位置

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

​ 同样的,第三行不好推导,我们参照定义
​ 因为近平面z是不变的,那么将n带入所以可以得到

\[
\left(\begin{array}{l}
x \\
y \\
n \\
1
\end{array}\right) \Rightarrow\left(\begin{array}{l}
x \\
y \\
n \\
1
\end{array}\right)==\left(\begin{array}{c}
n x \\
n y \\
n^{2} \\
n
\end{array}\right)
\]

​ 可以推导出

\[
\left(\begin{array}{llll}
0 & 0 & A & B
\end{array}\right)\left(\begin{array}{l}
x \\
y \\
n \\
1
\end{array}\right)=n^{2}
\]

​ 同时,对于远平面,处于中点的点进行变换后,仍然处于中点

\[
\left(\begin{array}{l}
0 \\
0 \\
f \\
1
\end{array}\right) \Rightarrow\left(\begin{array}{l}
0 \\
0 \\
f \\
1
\end{array}\right)==\left(\begin{array}{c}
0 \\
0 \\
f^{2} \\
f
\end{array}\right)
\]

​ 那么,对于一个近平面,对于远平面的中心点,我们可以得到这样一个方程组

\[
\begin{array}{l}
A n+B=n^{2} \\
A f+B=f^{2}
\end{array}
\]

​ 解方程组,我们可以得到最后的结果

\[
\begin{array}{l}
A=n+f \\
B=-n f
\end{array}
\]

​ 至此,我们就推导出了完整的一个透视变换矩阵

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

Thanks you

图片,课程来源:闫令琪老师的games101计算机图形学入门课程,欢迎大家前去了解