# Transformation(变换)

# 二维变换

# 缩放矩阵(Scale Matrix)

image-20220906162501304

image-20220906162642473

# 反射矩阵(Reflection Matrix)

image-20220906163039680

# 切变矩阵(Shear Matrix)

image-20220906163305246

# 旋转矩阵(Rotation Matrix)

image-20220909160412042

# 线性变换

image-20220909161024365

线性变换的一种描述是如果变换可以写成用一个矩阵乘以输入的坐标得到输出的坐标,那么我们就称这种变换为线性变换。

# 齐次坐标

为什么要提到其次坐标这个东西?首先让我们看看平移变换。

# 平移变换(Translation)

image-20220909161232739

这种变换我们还能写成上面那种矩阵相乘的形式吗?我们发现它顶多只能写成下面这种形式。

image-20220909161827846

所以我们可以得出一个结论:平移变换不是线性变换。那么有没有上面方法可以用一种通用的形式表示所有的变换呢?答案是有的,那就是引入齐次坐标。

# 解决方案:齐次坐标

image-20220909172011432

image-20220909172827036

在齐次坐标的定义下,一个点加上一个点表示的是这两个点的中点。

# 仿射变换

image-20220918094710001

所有的仿射变换都可以写成上面这种齐次坐标的表示形式。

image-20220918095135738

# 逆变换

image-20220918095340705

# 变换的组合

  • 复杂的变换可以通过一系列简单的变换得到
  • 变换的顺序是十分重要的

image-20220918100033811

image-20220918100108729

image-20220918100525429

# 变换的分解

image-20220918101749277

# 三维变换

image-20220918102239342

image-20220918102252789

三维变换于二维变换一样,也是先做线性变换再做平移,从而变换到正确的目标位置。

在旋转里面,旋转矩阵的逆就等于旋转矩阵的转置。

image-20220918104600482

image-20220918105702065

image-20220918105739089

仔细观察上面旋转矩阵,会发现绕 y 轴的旋转和其他两个轴的写法不一样。这是因为二维平面定义时,逆时针实际是在三维从 z 正向看,因此三维绕 y 旋转,逆时针实际是 z 向 x 转,但是旋转矩阵的行列对应关系是 x 向 z 转,取逆或者转置就得到了绕 y 轴旋转的矩阵。这个地方用到了三维坐标系中循环对称的性质。

# 三维旋转

image-20220918110912773

上面三个角度我们称之为欧拉角,通过观察飞机的旋转我们发现,复杂的绕任意轴的旋转都可以把它们分解成最简单的绕 xyz 轴旋转的组合。

# 罗德里格斯旋转公式(Rodrigues' Rotation Formula)

image-20220918112323231

这个地方默认沿着某个轴的方向旋转,其实就是认为这个轴是过原点的。那么它的起点就是在原点上,方向就是nn 这个方向,然后旋转角度是α\alpha

# 四元数

四元数这个概念的引入主要是为了旋转与旋转之间的插值这样的一个目的而做的。可以考虑在二维空间下的一个旋转,例如写一个旋转 15° 的矩阵,再写一个旋转 25° 的矩阵,如果把两个矩阵加起来求个平均,这个结果并不是旋转 20° 的结果。也就是说旋转矩阵这个东西写出来是不太适合做插值的,考虑到这一点,四元数在这一方面就得到了不错的应用。

# 观测变换(Viewing Transformation)

# 视图 / 相机变换(View/Camera Transformation)

image-20220918114623065

思考现实中获取到一张照片,实际上对应到图形学中,也是类似的,也就是 MVP 变换。

image-20220918115401704

要定义一次完整的视图变换首先我们要定义摄像机,我们需要知道相机的位置、相机的朝向,以及相机的向上方向。这是我们需要定义的一些东西。

image-20220918115847209

物理中我们有相对运动,既然如此,我们便可以把相机永远固定在坐标轴原点,永远认为是其他物体在运动。并且相机永远朝着负 Z 方向看,相机永远以 Y 轴为向上方向。那么,原本在任意位置的相机我们把它移动到固定位置上,其他物体同样随着相机这么运动,最后得到的结果一定也是一样的。为什么要这么做是因为可以让后续的操作得到进一步简化。

image-20220919144055330

image-20220919144447084

将摄像机的的轴向旋转到对应的原点坐标轴的方向的矩阵不太好写,但是我们可以写出它的逆变换,而旋转矩阵是正交矩阵,所以旋转矩阵的逆就是它的转置。这样便可以得到RviewR_{view} 所对应的矩阵。再配合上一开始的平移矩阵,得到的矩阵MviewM_{view} 就是我们的视图变换。相机要移动到这个固定位置上去,其他物体也都要跟着做这样的一个变换,以保证相对性。

# 投影变换(Projection Transformation)

image-20220919145745727

image-20220919150119299

# 正交投影

image-20220919151717264

image-20220919152757867

image-20220919152818849

image-20220919152903576

f、n 代表远近平面;t、l 代表上下平面;l、r 代表左右平面;

image-20220919152927397

由于摄像机是沿着 - Z 方向看的,所以近处的值大于远处的值,这就是为什么 OPenGL 会使用左手坐标系,因为可以保证摄像机是朝着 Z 方向看的。

# 透视投影

image-20220919165242184

image-20220919165428751

透视投影是使用的最广泛的一种投影,在各种各样的图形学应用当中几乎都会用到这种投影。满足近大远小的性质,它所带来的一种视觉效果就是平行线看起来不再平行了。在欧氏几何中,平行线被定义为永不相交的两条线。但观察上面的叠轨,我们发现看起来并不是这样。是欧氏几何错了吗?其实,是描述的方式不一样。在同一个平面里面,两条平行线确实是不会相交的。但是在透视投影的情况下,一个平面相当于被投影到了另外的一个平面上去,在这种情况下,他就不再是平行线了,这也是透视投影所带来的不同的一些地方。

image-20220919170626673

在齐次坐标中,一个坐标点乘以一个不为零的数仍然表示的是一个相同的点,这一点很重要,后面会用到。

image-20220919173607729

image-20220919174406018

image-20220919175642238

通过上面相似三角形的性质,我们很容易得以得到yy'xx' 的值,并且我们知道这些点之后都会变成上述的形式。

image-20220919180407627

实际上,我们只要知道了 X 轴和 Y 轴上点的变化,就已经可以推出矩阵中的大量元素了。

image-20220919181230803

image-20220919182221839

image-20220919182939948

那么我们该怎么推出矩阵第三行的值呢?通过细微的观察我们会发现:近平面上面所有的点在变换之后都不会变,而远平面上 z 轴的值也不会变,并且原平面的中心点不会变。利用这样的一个性质,我们得到了两个等式。

image-20220919183124509

有了这两个等式,我们便可以求出 A 和 B 的值了。于是我们终于写出来了透视投影到正交投影的变换矩阵。再结合上正交矩阵归一化的矩阵后,我们便得到透视投影的矩阵。

image-20220919195343577

现在,我们知道了这个归一化的空间是怎么得到的,在这之前,我们的视锥到底是怎么定义的呢?我们定义了它的宽高比还有它的 FOV。这是我们用来定义透视投影的视锥所需要的两个概念。

image-20220919201147077

正常情况下,要定义一个视锥,我们只需要定义一个垂直的可视角度,定义一个宽高比,其他的这些我们都可以把它转换到我们定义正交投影的远近、左右、上下的概念上去。

# 屏幕映射(Canonical Cube to Screen)

image-20220919202302097

image-20220919202906956

image-20220919203143861

有了屏幕坐标的定义之后,我们便可以把归一化的的设备坐标映射到屏幕坐标,此处我们先忽略 Z 轴坐标,那么我们很容易就能得到视口变换的矩阵。

image-20220919204251507

下一步,我们将进行光栅化。