坐标系简介
坐标系在图形渲染管道中起着至关重要的作用。它们并不复杂;坐标是我们在学校学习几何的第一件事。而且,学习一些关于坐标系的知识会使理解矩阵变得更容易。
在上一章中,我们提到了点和向量(如CG中使用的)用三个实数表示。但这些数字是什么意思?每个数字表示从线的原点到该线上点的位置的有符号距离。例如,考虑画一条线并在中间做一个标记。我们将把这个标记称为原点。这个标记成为我们的参考点:我们将从这个位置测量到任何其他点的距离。如果一个点位于原点的右侧,我们将带符号的距离取为大于零(正值)。另一方面,如果它在原点的左侧,则该值将为负值(负值)。
我们假设这条线在原点的两边都是无穷远的。因此,这条线上两点之间的距离可以取无限大。然而,这带来了一个问题:在计算机的世界里,一个数字的值是有限制的(这取决于我们用来编码这个数字的位数)。值得庆幸的是,这个最大值通常足够大,可以构建我们想要渲染的大多数3D场景;无论如何,我们在CG中处理的所有值都是有界的。话虽如此,但现在我们不要太担心这种计算限制。
现在我们有了一条线和一个原点,我们在原点的每一侧以规则的间隔(单位长度)添加一些额外的标记,有效地将我们的线变成了一把尺子。建立标尺后,我们可以从原点测量点的坐标(“坐标”是表示从原点到点的有符号距离的另一种方式)。在计算机图形学和数学中,标尺定义了我们所说的坐标轴。
图1:点的位置定义为从点的位置到坐标轴原点的(有符号的)距离。坐标轴从负无穷大延伸到正无穷大。
假设我们感兴趣的点不在坐标轴上。在这种情况下,我们仍然可以通过使用垂线将点投影到坐标轴上来找到点的坐标(通常,我们使用垂直于坐标轴的线)。从原点到这条垂直线与坐标的交点的距离是该点相对于该坐标轴的坐标。我们刚刚学会了定义一个点沿轴的坐标。
尺寸和笛卡尔坐标系
我们称呼水平轴为x轴。我们可以在x轴的原点画另一把垂直于x轴的标尺。我们称之为y轴。对于任何一点,我们都可以通过在每个轴上绘制垂直线并测量从这些交点到原点的距离来确定x和y坐标(与上述过程相同)。我们现在可以为任意点找到两个数字或两个坐标:一个用于x轴,一个用于y轴。因此,我们通过放置两个轴来定义一个称为平面的二维空间。
例如,考虑在一张纸上画几个点。这张纸占据了一个二维空间,即一个平面。我们可以再次绘制两个轴:每个维度一个轴。如果我们使用相同的x轴和y轴来测量纸上画的每个点,那么这两个轴就可以定义一个坐标系。如果这两个轴彼此垂直,那么它们表示笛卡尔坐标系。
请注意,我们通常使用一种称为有序对的简洁表示法来书写点的坐标。有序对就是用逗号分隔的两个数字。对于笛卡尔坐标系,通常先写水平x坐标,然后写竖直y坐标。因此,例如,我们将为x坐标为2.5,y坐标为2.25的点写(2.5,2.25)(见图2)。但是,不要让这件事吓到你。请记住,我们总是可以将这些有序对解释为两个有符号的距离:点在原点右侧2.5个单位,在原点上方2.25个单位。在接下来的课程中,我们将使用这种方式来书写点的坐标。
图2:二维笛卡尔坐标系由两个垂直的直角轴定义(由图中间的灰色方块表示)。每个轴被划分为单位长度的规则间隔。计算2D点的坐标只是将1D情况(如图1所示)扩展到2D情况。我们在x和y方向上从点到坐标系原点的有符号距离。
在本课的这一点上,我们现在知道如何创建二维笛卡尔坐标系,并定义该坐标系中二维点的坐标。请注意,在坐标系中定义的点的坐标是唯一的。这意味着同一点不能同时用一个系统中的两组不同的坐标表示。然而,我们必须注意,我们可以选择任何(其它的)坐标系。
我们可以选择在一个平面上定义无限多个这样的坐标系。为了简单起见,让我们假设我们在一张纸上只画了两个这样的笛卡尔坐标系。根据我们考虑的两个坐标系中的哪一个,该点的坐标会有所不同。例如,在图3中,点P在坐标系A中的坐标为(-1,3),在坐标系B中的坐标是(2,4)。然而,这是同一点;这个点和我们第一次画的时候在同一个地方。
图3:同一点在两个坐标系中定义。我们可以通过将值(3,1)加到红色坐标系(A)中的点的坐标值上来将其转换为绿色坐标系(B)。译者注:
点P在红色坐标系中的坐标是(-1,3),将该值加红色坐标系原点在绿色坐标系的位置(3,1),结果等于(2,4),就是P在绿色坐标系中的坐标值
图4:缩放(以蓝色显示)或平移一个点(以绿色显示)会修改其坐标。缩放是点的坐标与某个值的乘积。平移是将一些值添加到点的坐标上。
那么,如果你知道P在坐标系A中的坐标,你需要做什么才能找到同一点P在另一个坐标系B中的坐标?这代表了CG(以及一般数学)中的一个基本运算。我们很快就会了解为什么,以及如何找到将点的坐标从一个坐标系转换到另一个坐标系统的映射。
现在,让我们考虑图3中的例子。注意,按坐标方向将值(3,1)相加到坐标(-1,3),得到坐标(2,4)。因此,将(3,1)与A中P的坐标相加,得到B中P的坐标。将(-3,-1)与(2,4)相加,得到(-1,3)。这将P在B中的坐标转换为P在A中的坐标。需要注意的是,(-3,-1)只是(3,1)的逆变换。这是显而易见,因为它们可以被认为是在相反的方向上改变一个点的坐标:在从A到B的一个方向上添加(3,1)个坐标,而在从B到A的相反的方向添加(-3,-1)个坐标。译者注:A是红色坐标系,B是绿色坐标系
另一个常见的操作是将坐标系A中的点移动到同一坐标系中的另一个位置。这被称为平移,毫无疑问这是你可以对点进行的最基本的操作之一。请注意,所有线性运算符都可以应用于点坐标。例如,一个实数与一个点的坐标相乘会产生一个缩放(图4)。缩放会将P沿着穿过点P和原点的线移动(因为当我们变换点时,我们变换从原点到点的向量)。稍后将详细介绍这一切。
第三个维度
三维坐标系是二维情况的简单扩展。我们将添加一个与x轴和y轴正交的第三个轴,称为z轴(表示深度)。x轴指向右侧,y轴指向上方,z轴指向后方(当x轴指向右方时,它会以某种方式出现在屏幕外)。虽然可以使用其他约定(请参阅以下段落),但我们将仅在整个Scratchapixel中使用此约定。在几何学中,这个三维坐标系定义了更正式的欧几里得空间。
图5:三维坐标系。三个坐标定义一个点,每个轴一个坐标。
我们在本章结束时为那些对更正式的坐标系定义感兴趣的人写了一段话。在线性代数中,三个轴(在1D和2D情况下分别为一个或两个)构成了我们所说的坐标系的基础。基是一组线性独立的向量,在线性组合中,可以表示给定向量空间(坐标系)中的每个向量(或点)。一个集合中的向量被称为线性独立的,当且仅当该集合中的任何向量都不能被写成该集合中其他向量的线性组合(译者注:线性独立的概念)。改变基准,或改变坐标系,是数学和图形管道中常见的操作。
左手坐标系与右手坐标系
不幸的是,由于各种不同的用手习惯,坐标系更加复杂。这个问题可以在下图中说明。当y轴(也称为“向上”矢量)指向上方,x轴(也称“向右”矢量)向右(如下图所示)时,z轴(也称为前向或向下矢量)可以指向屏幕内或您。把你的屏幕想象成XY平面。然后向前矢量(z轴)将垂直于屏幕。将z轴视为指示深度的方向。
为了区分这两种约定,我们将第一个坐标系称为左侧坐标系,另一个称为右侧坐标系。物理学家约翰·安布罗斯·弗莱明(John Ambrose Fleming)引入了左右规则,很容易区分这两种惯例。
我们稍后将解释它与手的关系。但首先,让我们定义这两个系统之间的区别。x轴指向右侧,y轴指向上方,如果z轴指向远离您的方向,则为左手坐标系。如果它指向你的方向,那么它就是一个右手坐标系。
要记住每个坐标系的方向,请将x、y和z轴分别指定给拇指、食指和中指。这非常简单,因为这是我们自然展开手指的顺序。用你的左手和右手做这个。然后将拇指向右,食指向上,中指将指示z轴的方向。
左手:远离你。
右手:朝你。
这个助记符需要一点手的扭曲,但它是让它一直“正确”的最好方法。现在你明白了为什么我们把这些系统称为左手和右手坐标系,或者称为坐标系的旋向性。
图6:如图所示,调整左手或右手的方向,以找出分别使用左手或右手坐标系时z轴指向的方向。手工3D模型由Artem Manuilov提供。
拇指向上(y轴),食指(z轴)远离你,在左侧坐标系中,中指(x轴)指向右侧;在右侧坐标系中,它指向左侧。
这里,左手和右手只是用来计算x轴指向哪个方向,假设拇指表示向上矢量,食指表示向前矢量,它确实指向前方(相对于观看者)。有了这个助记符,当使用左手时,x轴(或第三矢量)指向右边(当使用右手时指向左边)。我们知道,这里的左右术语指的是你左手或右手的使用,而不是x轴的方向。不得不说,你的中指指向左侧坐标系中的右侧是违反直觉的。这就是为什么我们更喜欢上面提到的XYZ拇指-食指-中指助记符。
尽管如此,我们之所以提到它,是因为您可能会在其他文档中发现它的使用(事实上,Scratchapixel最初就是这样解释这两个系统之间的差异的)。
坐标系的旋向性也在从多边形面的边缘线计算出的法线方向中发挥作用。 例如,如果方向是右旋,则其顶点按逆时针顺序指定的多边形将面向前方。 这将在渲染多边形对象的课程中解释。
图7:CG中使用的最流行的约定将向上向量定义为y轴(a)。然而,在许多与CG相关的论文(尤其是与着色技术相关的论文)中,通常会发现坐标系,其中向上向量被定义为z轴(b)。一些作者声称这个约定来自于物理学和数学中常用的符号。该图中绘制的两个坐标系均为右旋坐标系。
三个垂直的单位长度向量只定义了笛卡尔坐标系。 关于数学符号,这个坐标系需要更多地传达这三个轴的含义。 开发人员是决定如何解释这些轴的人。 因此,必须明确区分坐标系的旋向性和用于标记相应轴的惯例。
向上矢量称为 z 轴还是 y 轴? 让我们使用图 7b 中的约定,并假设 x 轴是向右的向量。 关于这个坐标系的旋向性,我们能说些什么呢? 这是一个右手坐标系(将右手的中指定位在 x 轴上,并检查其他两个手指是否指向向上和向前矢量)。 如您所见,我们采用右手或左手坐标系并标记轴 x、y 和 z。 命名约定(如何标记这些轴)与坐标系的惯用手性无关。 了解这种差异至关重要。 许多人经常认为,由于某些系统使用向上矢量标记为 z 轴的约定(而不是更流行的 y 轴约定),因此一个系统是左手的,而另一个是右手的。 这是不正确的。
唯一定义坐标系的旋向性的是左(或右)向量相对于向上和向前向量的方向,不管这些轴代表什么。 关于轴名称的惯用习惯和约定是两件不同的事情。
在处理渲染器或任何其他 3D 应用程序时,了解坐标系使用哪种约定也很重要。 目前,行业标准倾向于右手 XYZ 坐标系,其中 x 指向右侧,y 向上,z 向外(从屏幕出来)。 Maya 和 OpenGL 等程序和 3D API 使用右手坐标系,而 DirectX、PBRT 和 PRMan 使用左手坐标系。 请注意,Maya 和 PRMan 使用的坐标系,其中向上矢量称为 y 轴,向前矢量称为 z 轴。 这意味着一个系统中某个点的 z 坐标为 3,而在另一个系统中为 -3。 出于这个原因,我们可能需要在将几何体导出到渲染器时反转对象的 z 坐标的符号。 坐标系旋向性的选择对两个向量的旋转和叉积也起着至关重要的作用。 我们将在接下来的几章中更多地讨论这一点。 从一个坐标系转到另一个坐标系很容易(但很痛苦)。 所需要的只是按 (1, 1, -1) 缩放点坐标和相机到世界矩阵。
现在,请注意 Scratchapixel 使用右手坐标系主要是为了与 Maya 保持兼容,因为它已经成为事实上的行业标准(我们希望每个人都使用相同的约定)。
世界坐标系
我们已经了解到,点和向量的坐标与笛卡尔坐标系的原点有关,该坐标系由三个垂直的单位向量(构成一个基)定义。 我们还解释了我们可以根据需要创建任意多个坐标系,并且点和向量在每个坐标系中都有唯一的坐标。 然而,在大多数 3d 应用程序中,每种类型的坐标系都是相对于称为世界坐标系的主坐标系定义的。 它表示由所有其他坐标系定义的原点和主要 x、y 和 z 轴。 世界坐标系是渲染管道中所有不同坐标系中最重要的。 这些包括对象、局部(用于着色)、相机和屏幕坐标系。 我们将在接下去课程中解释所有这些。
我们需要记住的事情
我们意识到大多数读者不需要解释这些概念。 然而,这里重要的不是基本几何知识,而是熟悉所有 CG 文献中使用的术语。 在本章中,重要的术语是坐标、轴和笛卡尔坐标系。 我们还引入了线性算子(缩放和平移)的概念来变换点和向量。 该章要记住的基本思想是点的坐标与坐标系相关,可以定义多个坐标系,并且一个点在每个坐标系中都有唯一的坐标。 确定您使用的坐标系(在您的程序中或在您用于渲染图像的 API 中)是左手坐标系还是右手坐标系也很重要。 保持坐标系的旋向性用于标记不同的坐标轴是必不可少的。