3D Mathematics 03 - Transform
# 概述
在3D图形引擎架构中,经常需要将一组向量从一个坐标空间转换到另一个坐标空间。例如,模型的顶点坐标通常存储在对象空间中,但是在渲染模型之前,我们需要将其转换到摄像机空间。这些行为被统称为 变换 (Transform) 。
变换可以划分为互不冲突的三种: 平移 (Translation) , 旋转 (Rotation) 和 缩放 (Scale) 。这三种变换均可用矩阵形式表示,由此可以将复杂的变换问题转换为纯粹的矩阵运算问题,为三维空间的坐标变换提供了极大的便利。
# 平移
# 定义
设 是三维空间中的一点, 在坐标系 下的坐标为 ,在坐标系 下的坐标为 ,则两个局部坐标存在形如下式的关系:
这构成了从 到 的 线性变换 (linear transformation) ,即 平移 (translation) ,可以用矩阵形式来表示:
我们可以认为坐标值 是点 从坐标系 的原点出发沿着 的坐标轴正方向行进的距离,坐标值 类似。那么向量 表示的是从 的原点到 的原点的平移量,矩阵 表示的是从 变换到 时坐标轴如何变化。
假设变换是可逆的,那么从 到 的线性变换为:
多个线性变换可以连接组合为一个线性变换。例如,顶点坐标可能需要从对象空间转换到世界空间,然后从世界空间转换到摄像机空间。如果将这两个转换组合成一个转换,得到的就是从对象空间直接转换到摄像机空间的变换矩阵。
# 正交矩阵
计算机图形应用中出现的大多数 的矩阵都是正交矩阵。 正交矩阵 (orthogonal matrix) 的逆矩阵等于其转置矩阵,即:
正交矩阵的一个重要性质是,当变换矩阵是一个正交矩阵时,变换会保持被变换向量的长度和角度大小。
如果变换矩阵 保持长度大小,那么对于任意向量 满足:
如果变换矩阵 保持角度大小,那么对于任意向量 满足:
而如果 是正交矩阵,那么容易推出上述二式均成立。
由于正交矩阵保持长度和角度的大小,因此它可以保持坐标系的整体结构,因此正交矩阵可以仅表示旋转和反射的组合。旋转将在下一节介绍; 反射 (reflection) 指的是对某个点沿着某个方向进行镜像的操作。
例如,下列矩阵是横跨 平面对 坐标的反射:
# 手性
在三维空间中,由三维向量 给出的坐标系的基 具有一种被称为 手性 (handness) 的属性。
一个右手坐标系的基满足 ,也就是说, 和 之间的夹角是锐角。
特别地,如果是一个 右手正交基 (orthonormal right-handed basis) ,则 。
类似地,一个左手坐标系的基满足 。
进行奇数次的反射变换可以改变基的手性。
偶数次的反射变换总是等价于某种旋转变换,因此任何一系列的反射变换总是可以被视为一个旋转变换跟上零或一个反射变换。
可以通过检查行列式的值来确定一个 的矩阵 内是否存在反射。如果 ,那么 保持手性不变。如果 ,则存在反射,并且由 变换的任何一组基向量的手性都会反转。
注意,正交矩阵的行列式值总是 或 。
# 旋转
# 定义
旋转 (Rotation) 就是将一个向量沿着某一个旋转轴旋转一个角度。通常我们认为,角度为正值表示的方向,是旋转轴指向我们时进行逆时针旋转的方向。
三维空间的旋转可以用矩阵来表示,但它看起来没有平移或是缩放那么直观。为便于理解,我们从二维平面的旋转开始,先推导二维世界的 的旋转矩阵,再推广到三维世界的 的旋转矩阵。
# 二维平面上的旋转
在二维 坐标系中,设二维向量 ,我们将 逆时针旋转 ,得到向量 ,那么 。
注意到 和 构成了另外一组正交基,因此我们可以用 和 来表示平面内的任意一个向量。设向量 是由 逆时针旋转 角度得到的,那么有:
也就是说:
将其转换为矩阵表示形式,即:
这个 的矩阵,以及后续在三维空间中的那些 的矩阵,被称为 旋转矩阵 (rotation matrix) 。
# 绕正交坐标轴的旋转
现在我们从二维平面推广到三维空间,你可以想象从 平面延伸出一条过 点的垂线作为 轴,那么显然,我们在二维平面上的旋转事实上就是在三维空间中绕 轴的旋转, 值变化而 值不变。
因此我们可以立即得到绕 轴旋转 角度的旋转矩阵,记为 。
类似地,我们可以得到 和 ,读者可自行尝试推导。
# 绕任意轴的旋转
现在我们将问题一般化:给定一个任意的向量 ,我们要将其绕向量 旋转 角度。为方便起见,设 是一个单位向量,因为我们显然只需要关心旋转轴的方向而不是长度。
我们将 分解为相对于 的投影分量 和垂直分量 ,可以发现,在绕 轴旋转的时候 是不变的,因此我们只需要考虑 的旋转即可。
因为 是单位向量,所以投影和垂直分量的表达式可以简化为:
设 和 之间的夹角为 ,那么 。
我们考虑 的旋转,可以发现,叉积的结果 可以和 构成一组正交基。
类似于二维平面上的方法,我们可以得到 绕 旋转 角度的表达式:
由于旋转后的 和 具有相同的投影分量,在等式两侧加上投影分量 即可得到:
将 转换为矩阵表示形式:
将整个表达式转换为矩阵表示形式:
设绕 轴旋转 角度的旋转矩阵为 ,即 ,对上式求和即可得到:
# 缩放
缩放 (Scale) 远比平移和旋转要简单得多,但也没有那么单纯。对一个向量进行缩放,例如将向量 缩放 倍,是一件很简单的事情:
我们可以用矩阵来表示缩放:
这样的缩放被称为 统一缩放 (uniform scale) 。
矩阵的表示形式是非常有用的,因为有时我们希望沿 轴对向量进行不同比例的缩放,如图所示,那么直接给向量乘上一个标量就不行了。
但是此时我们仍然可以使用类似的矩阵来表示:
这样的缩放被称为 非统一缩放 (nonuniform scale) 。
有时我们还会希望沿三个任意轴对向量进行非统一缩放,例如我们希望沿着 方向分别缩放 倍,那么我们可以先假定向量位于以 为基的坐标系,将向量从以 为基的坐标系转换到以 为基的坐标系,进行缩放后,再将其转换回去。这个过程可以用下列矩阵运算来表示:
事实上这是一个简化的公式,因为标准正交基 的矩阵表示是一个单位矩阵,在上式中已被省略。实际上完整的表达式是这样的:
其中 为 的矩阵表示, 为任意缩放矩阵,只是因为乘以 或 可以被省略而已。
# 齐次坐标
# 齐次变换矩阵
我们知道,一系列的旋转和缩放变换可以表示为若干个变换矩阵的连乘,并且这些矩阵都是可逆的,所以我们可以轻松简洁地处理旋转和缩放变换,但是平移变换却并非如此。通过简单地添加偏移向量,坐标系的原点会在空间中平移,而不会改变轴的方向或缩放比例,因而平移操作不能用一个 的矩阵直接表示。因此,为了将点 从一个坐标系变换到另一个坐标系,我们通常会发现自己正在执行形如下式的计算:
其中 是一个变换矩阵,而 是一个用以表示偏移量的向量。这意味着,如果存在一系列的平移变换,级联的结果是这样的:
级联的变换次数越多看起来就越糟糕:
可以发现,每一次平移都需要考虑到之前已经经历的轴向相关的变换。当变换次数很多时,你理所当然地会觉得这个越来越长的表达式非常丑陋,并且它确实会给我们带来不便。
比如说,仅仅是最简单的若干次变换的级联, 个变换矩阵 的应用很容易可以缩写成 ,但现在却只能缩写成 ,看起来就很令人不适,并且它的逆变换写出来显得更加令人不适,远不如 方便。如果是一些更加复杂的计算,还会有更多的麻烦出现。
幸运的是,有一种紧凑而优雅的方式可以在单个数学实体中表示这些变换,从而消除这样的不快。
我们将所有的三维向量 扩展到四维向量,并将它们的第四维坐标设为 ,这种表示方式称为四维 齐次坐标 (homogeneous coordinates) 。
这样一来,我们就有办法用 的矩阵来表示所有的平移、旋转、缩放变换,称该矩阵为齐次变换矩阵:
将齐次变换矩阵 乘以 的齐次坐标,可以对 进行正确的变换,并保持 不变:
更重要的是,我们的这一变换必须可逆,就像原来那样:
我们尝试构造齐次变换矩阵的逆矩阵:
并证明 成立:
到此,我们就得到了仅用矩阵乘法表示一切变换的方法。这种方法被广泛应用于3D变换中,具有无可替代的重要性。
# 齐次坐标下的点和方向
以前我们用三维向量表示一个点的位置或一个方向,并且无需严格区分它们,但是在齐次坐标下,我们必须将点和方向区分开来。
如果要表示一个点,我们应当设 ,但是如果要表示一个方向,我们应当设 。基于两个理由:
设 可以将 的第四列,也就是偏移量 的影响消除,因为方向显然没有偏移一说。
设 符合齐次坐标的点之间的差运算的结果,因为方向可以由两点的坐标之差得到,那么得到的方向向量理所应当地会有 。
# 坐标 的几何解释
之前,我们通过在添加坐标 将三维点扩展到四维空间,现在我们定义一个在反方向工作的映射。设四维空间中一点 ,其中 ,我们定义 在三维空间中的投影为:
如图所示,三维空间中的点 对应于四维空间中从原点 到 的连线与三维空间的“交点”,在这里 。图中省略了 轴以便于令四维空间可视化。
因此,四维向量 的任何标量倍数表示三维空间中的同一点。
# 对法向量的变换
对于多边形模型中的顶点而言,除了它的空间坐标之外,它通常还带有一些关于它如何适合周围表面的附加信息。例如,顶点可以具有切向量和与其相关联的法向量。因此,当我们对模型进行变换时,不仅需要变换顶点位置,还需要变换这些附加的向量信息。
由于切向量和法向量都是表示方向的,不受偏移量 的影响,所以为了方便起见,我们仅考虑 的变换矩阵而不是齐次变换矩阵。
切向量 (tangent vector) 通常可以通过取一个顶点和另一个顶点之间的差来计算,因此变换后的切向量可以表示为两个变换后的点之间的差异。如果 是我们变换顶点坐标的 的矩阵,则可以使用相同的矩阵 正确地对该顶点处的切向量进行变换。
但是 法向量 (normal vector) 则不同,当变换矩阵 不是正交矩阵时,变换后的法向量通常指向不垂直于变换表面的方向。也就是说,直接使用相同的矩阵 对法向量进行变换并不总是能得到一个正确的结果。
设点 的切向量为 ,法向量为 。显然切向量和法向量是相互垂直的关系,即 。我们必须保证变换后的切向量 和法向量 仍然满足 。
设点 的空间坐标的变换矩阵为 ,我们知道 ,那么我们现在需要求出法向量的变换矩阵 ,即 ,满足:
根据点积的性质有:
因为 ,所以 当且仅当 ,由此可得:
必须以这种方式变换的向量(例如法向量)称为 协变向量 (covariant vectors) ,而使用矩阵 以常规方式变换的向量(例如点和切向量)被称为 逆变向量 (contravariant vectors) 。
特别地,如果 是正交矩阵,那么 ,则 ,因此当 是正交矩阵时我们可以直接用 对法向量进行正确的变换。
(下面是废弃文字)
这样一来,我们就有办法用 的矩阵来表示所有的平移、旋转、缩放变换,称该矩阵为齐次变换矩阵:
将齐次变换矩阵 乘以 的齐次坐标,可以对 进行正确的变换,并保持 不变:
更重要的是,我们的这一变换必须可逆,就像原来那样:
我们尝试构造齐次变换矩阵的逆矩阵:
并证明 成立:
到此,我们就得到了仅用矩阵乘法表示一切变换的方法。这种方法被广泛应用于3D变换中,具有无可替代的重要性。
- 01
- Reading Papers - Kernel Concurrency06-01
- 02
- Linux Kernel - Source Code Overview05-01
- 03
- Linux Kernel - Per-CPU Storage05-01