我们通常用平面的法向量表示平面。包含平移的变换称为仿射变换,3D 中的仿射变换无法使用 的矩阵实现,而是使用 矩阵。
旋转 Rotation
二维旋转
线性变换不包含平移,因此绕原点的 2D 旋转只有一个参数,即角度 ,它定义旋转量。
//
//
3D 绕基轴旋转
旋转围绕轴而不是点进行,术语“轴”具有更常见的含义,即物体绕其旋转的线。旋转轴不一定必须是基本 x、 y 或 z 轴之一。
//
//
3D 绕任意轴旋转
我们将 定义为绕轴的旋转量。该轴将由单位向量 定义。 我们希望导出矩阵 ,以便当我们将向量 乘以 时,得到向量 是围绕 围绕 旋转角度 的结果:
为了帮助我们计算 ,构造一个 和 形成一个 2D 坐标空间。
//
最终求得:
缩放 Scale
等比缩放会导致整个对象均匀增大或减小,如果希望"拉伸"或“挤压”对象,我们可以在不同方向上应用不同的缩放因子,从而导致缩放不均匀。 定义 k 作为缩放因子,
- 如果 k小于1 则对象在该方向上变得更短
- 如果 k大于1 则对象在该方向上变得更长
- 如果 k等于0 得到一个正交投影
- 如果 k小于0 则拥有一个反射
沿基轴缩放
基向量 和 独立地受到相应比例因子的影响
从这些基向量构造二维尺度矩阵 ,我们得到:
对于 3D 矩阵,可得到
将任意向量乘以该矩阵,每个分量都会按适当的比例因子进行缩放:
任意方向缩放
将 定义为关于直线(2D)或平面(3D)应用的比例因子通过原点并垂直于 。我们沿着 进行缩放。
//
由此推导出缩放矩阵
在 3D 中,基向量的值由以下公式计算
正交投影 Orthographic Projection
"投影"指的是在某个方向上使用零比例因子的降维操作。当原始点到对应点的线都是平行的,这种投影被称为正交投影,也叫平行投影。而另外一种类型被叫做"透视投影"。
投影到基轴或平面上
当 3D 物体投影到 2D 平面上时,就会发生如下情况。
//
投影到基轴或平面上最常发生的不是实际变换,而是简单地丢弃其中一个坐标,同时将数据分配给较小维度的变量。 投影到基轴或坐标平面的转换矩阵如下:
在表示平面时我们通常使用的是平面法向量的表示方式,三维空间公式中平面 指代的是垂直于反射平面的向量。
投影到任意直线或平面上
由于我们不考虑平移,因此直线或平面必须经过原点。投影将由垂直于直线或平面的单位向量 定义。 通过沿任意方向应用零比例因子来导出要在任意方向上投影的矩阵。在二维中,我们有
在 3D 中,我们投影到垂直于 的平面上:
反射 Reflection
反射(也称为镜像)是一种围绕直线(2D)或平面(3D)“翻转”对象的变换。
//
反射可以通过应用比例因子 −1来完成。令 为 2D 单位向量。然后,围绕穿过原点并垂直于 的反射轴执行反射的矩阵由下式给出
在 3D 中,我们有一个反射平面而不是轴。为了使变换是线性的,平面必须包含原点,在这种情况下,执行反射的矩阵是。
剪切 Shearing
剪切是一种“倾斜”坐标空间、不均匀拉伸坐标空间的变换。角度不保留,但是面积或体积却不变。基本思想是将一个坐标的倍数与另一个坐标相加。 在 2D 中,我们可能采用 的倍数并将其添加到 ,以便 。 参数 控制剪切的量和方向, 所以另一个矩阵表示为 在 3D 中,我们可以采用一个坐标并将该坐标的不同倍数添加到其他两个坐标中。符号 表示 和 坐标移动了另一个坐标 。为了完整性,我们提出这些矩阵:
剪切是一种很少使用的变换。它也称为倾斜变换。组合剪切和缩放(均匀或非均匀)创建的变换与包含旋转和非均匀缩放的变换没有区别。
组合变换
获取一系列变换矩阵并将它们组合(或连接)为一个变换矩阵。这个新矩阵表示按顺序应用所有原始变换的累积结果。这实际上很容易。应用矩阵 的变换,然后应用矩阵 的变换所产生的变换具有矩阵 。也就是说,矩阵乘法是我们如何组合表示为矩阵的变换。 渲染是一个常见的例子,我们将获取对象的顶点并将其从对象空间转换到世界空间,这种变换被称为模型变换 ,视图变换 将世界空间顶点变换到相机空间,总体表示如下
变换的类别
讨论转换时,我们使用同义词映射或函数,通过编写 来表示映射 将 映射到 。
线性变化 Linear Transformations
如果映射满足以下等式,则表明映射是线性变化的。
任何可以通过矩阵乘法完成的变换都是线性变换。线性变换不包含平移。
仿射变换 Affine Transformations
仿射变换是线性变换后进行平移。因此,仿射变换集是线性变换集的超集:任何线性变换都是仿射变换,但并非所有仿射变换都是线性变换。 形式的任何变换都是仿射变换。
可逆变换 Invertible Transformations
如果存在相反的变换(称为 的逆变换),即“撤消”原始变换,则变换是可逆的。换句话说,如果存在逆映射 ,则映射 是可逆的,使得
处投影之外的所有原始变换都是可逆的(投影会丢失维度信息,无法恢复)。 由于任何线性变化都可以表示为矩阵乘法,因此求线性变化的逆就相当于求矩阵的逆。如果矩阵没有逆矩阵,我们就说它是奇异的,并且变换不可逆,可逆矩阵的行列式不为零。
保角变换 Angle-Preserving Transformations
如果变换后两个向量之间的角度在大小或方向上都没有改变,则变换是保角的。只有平移、旋转和均匀缩放是保角变换。保角矩阵保留比例。反射并非保角变换,反射后的角度可能是相反的。 所有保角变换都是仿射且可逆的。保角变化多用于热力学和流体力学中。
正交变换 Orthogonal Transformations
平移、旋转和反射是唯一的正交变换。所有正交变换都是仿射且可逆的。
刚体变换 Rigid Body Transformations
刚体变换是一种改变对象的位置和方向,但不改变其形状的变换。刚体变换又称为欧式变换、齐次变换。所有角度、长度、面积和体积均被保留。平移和旋转是唯一的刚体变换。反射不被视为刚体变换。
不同引擎的差别
矩阵左乘,其实就是矩阵放到乘号左边乘的,矩阵右乘则相反。
在 HLSL 和 GLSL 中,当一个矩阵和向量相乘时,如果向量放在右边,会将该向量视为列向量,如果向量在左边,会将该向量视为行向量,这些都是自动完成的。
在 DirectX/HLSL 中,我们习惯使用矩阵右乘。在 OpenGL/GLSL 中,我们习惯使用矩阵左乘。
在实际写代码时,使用左乘和右乘都是可以的,左乘更加符合数学习惯,右乘更能能体现从左往右依次实现变换的顺序。在 Unity 中,基本都是遵循 OpenGL 的风格,因此尽管是使用 HLSL 作为 Shader 语法,但是依然是使用矩阵左乘。
本书中公式推导普遍使用的矩阵右乘,从左往右进行乘法计算。
Unity 中使用矩阵左乘,但也不必担心,其结果与下面等同