第三章:多个坐标空间
本章提供一些用于图形和游戏的常用坐标空间示例,然后我们将讨论坐标空间如何嵌套在其他坐标空间中。
1. 为什么需要多个坐标空间
从理论上讲,所有点都可以使用单个“世界”坐标系来表达。但有些信息是有意义的或仅在特定上下文环境中可用(表述有点怪,但能理解意思就行),为此开发人员需要不同的坐标空间。
2. 一些有用的坐标空间
下面来看看一些常见坐标空间。
- 世界空间,也称为全局坐标空间或通用坐标空间。它为所有其他要指定的坐标系建立了一个“全局”参考系。
- 对象空间,也称为模型空间或体空间,是与特定对象关联的坐标空间。每个对象都有自己独立的对象空间。当一个对象移动或改变方向时,它也会随之移动或改变方向。
- 相机空间,是对象空间的一个特例,其是与用于渲染视点相关联的对象空间。
- 直立空间,本书提出的一个坐标空间,对象的直立空间可以看作是世界空间与其对象空间的“中间过渡”。
3. 基矢量和坐标空间转换
我们知道如何在一个坐标空间中表达一个点,我们需要在其他坐标空间中表达这个点。该计算的技术术语是坐标空间转换。在转换的过程中点的实际位置是没有变化的。
任意矢量\(\vec{v}\)可以扩展为基矢量的线性组合:
在这里\(\vec{p}\)、\(\vec{q}\)和\(\vec{r}\)是三维空间的基矢量。如果不太明白的话,就请想象:\(\vec{p}=\begin{bmatrix}1,0,0\end{bmatrix}\)、\(\vec{q}=\begin{bmatrix}0,1,0\end{bmatrix}\)和\(\vec{r}=\begin{bmatrix}0,0,1\end{bmatrix}\),是否想到了什么?这正是笛卡尔三维坐标系的三个相互垂直的轴向单位向量,它也算是一个基矢量,而且一组相互垂直的基矢量也被称为正交基。
上述情况是常见的,但基矢量不必保证垂直。这种情况下进行点积,就不能像上一章那样,通过与基矢量的点积来分解一个矢量了(因为此时坐标不是解耦的,当你试图只增加\(\vec{a_x}\)时,会发现\(\vec{a_y}\)也会变化)。
可以表示为基矢量的线性组合的矢量集被称为基矢量的跨度,上图所示的基向量的跨度是无限的二维平面,如果是三维向量的话(只要基向量没有平行,或者专业点叫线性相关)跨度就是三维空间内的任意平面。
用于描述基所跨越的空间的维数的术语是基的秩。跨越的维数与基矢量的元素数相同,就叫满秩。比如先前介绍的基矢量就是满秩的。如果有一组\(\vec{p}=\begin{bmatrix}1,0\end{bmatrix}\)、\(\vec{q}=\begin{bmatrix}-1,0\end{bmatrix}\),那它的秩是1<元素数2,非满秩。
4. 嵌套坐标空间
将对象分成具有嵌套坐标空间的分层组织的对象序列,程序员可以在单独的分量中计算运动,并相对容易地与线性代数工具结合。比如,我们像知道某只羊耳朵的世界坐标,就可先计算它身体所在的世界坐标,再计算它耳朵所在的体空间下的坐标。然后一“结合”,就可以得到想要的结果(“结合”过程就是以后要学习的内容了)。
5. 针对直立空间的再解释
也许你仍不打算区分世界空间和直立空间(我曾经也,那请假设一个情况,有一个float3数据类型,它既用来存储“点”,又用来存储“矢量”(这种情况在游戏行业的代码中很常见,因为很多高级着色器语言鼓励使用泛型float3类型)。
如果,有一个float3表示某物体在对象空间下的位置,我们想知道它在世界空间下的位置,要进行这个转换,我们势必会对它进行平移;而如果有一个float3表示某物体的正面朝向,我们想知道它在世界空间下的方向,那这个转换过程就不应该包含平移(矢量是没有位置的)。
也就是说,有些float3数据应该发生平移,而有些不行,但当它们写成代码时就不好区分了。所以为了让代码更易于理解和编写,这本书自创了直立空间,将它与“世界空间”区分开,这样可以更好的表达矢量在转换过程中的数学细节。