“完成方式”是使用同质变换和坐标。你在空间中取一个点并且:
- 使用模型矩阵相对于相机定位它。
- 使用投影矩阵以正交方式或透视方式对其进行投影。
- 应用视口变换将其放置在屏幕上。
这变得相当模糊,但我会尝试涵盖重要的部分,并将其中一些留给您。我假设您了解矩阵数学的基础知识:)。
齐次向量、点、变换
在 3D 中,同质点是 [x, y, z, 1] 形式的列矩阵。最后一个分量是“w”,一个缩放因子,对于向量来说是 0:这会导致你无法平移向量,这在数学上是正确的。我们不会去那里,我们正在讨论要点。
齐次变换是 4x4 矩阵,使用它们是因为它们允许将转换表示为矩阵乘法,而不是加法,这对于您的显卡来说既方便又快捷。也很方便,因为我们可以通过将它们相乘来表示连续的变换。我们通过执行变换*点来将变换应用于点。
主要有 3 种齐次变换:
- 翻译, http://www.riemers.net/eng/ExtraReading/homogenous_matrices.php
-
回转, http://knol.google.com/k/matrices-for-3d-applications-translation-rotation# and
- Scaling. http://www.riemers.net/eng/ExtraReading/homogenous_matrices.php
还有其他一些值得探索的转变,特别是“观看”转变。然而,我只想给出一个简短的列表和一些链接。对点进行的移动、缩放和旋转的连续应用统称为模型变换矩阵,并将它们相对于相机放置在场景中。重要的是要认识到我们正在做的事情类似于在相机周围移动物体,而不是相反。
正交和透视
要将世界坐标转换为屏幕坐标,您首先需要使用投影矩阵,它通常有两种形式:
- 正交,常用于 2D 和 CAD。
- 透视,适合游戏和 3D 环境。
正交投影矩阵构造如下:
其中参数包括:
-
Top:可见空间上边缘的 Y 坐标。
-
Bottom:可见空间下边缘的 Y 坐标。
-
Left:可见空间左边缘的X坐标。
-
Right:可见空间右边缘的X坐标。
我认为这很简单。您所建立的是一个将出现在屏幕上的空间区域,您可以对其进行剪辑。这里很简单,因为可见空间的区域是一个矩形。透视剪裁更为复杂,因为出现在屏幕或观看体积上的区域是一个frustrum http://en.wikipedia.org/wiki/Frustum.
如果您在维基百科上的透视投影方面遇到困难,这里是构建合适矩阵的代码,由 geeks3D 提供 http://www.geeks3d.com/20090729/howto-perspective-projection-matrix-in-opengl/
void BuildPerspProjMat(float *m, float fov, float aspect,
float znear, float zfar)
{
float xymax = znear * tan(fov * PI_OVER_360);
float ymin = -xymax;
float xmin = -xymax;
float width = xymax - xmin;
float height = xymax - ymin;
float depth = zfar - znear;
float q = -(zfar + znear) / depth;
float qn = -2 * (zfar * znear) / depth;
float w = 2 * znear / width;
w = w / aspect;
float h = 2 * znear / height;
m[0] = w;
m[1] = 0;
m[2] = 0;
m[3] = 0;
m[4] = 0;
m[5] = h;
m[6] = 0;
m[7] = 0;
m[8] = 0;
m[9] = 0;
m[10] = q;
m[11] = -1;
m[12] = 0;
m[13] = 0;
m[14] = qn;
m[15] = 0;
}
变量是:
-
fov:视野,pi/4 弧度是一个很好的值。
-
aspect:高度与宽度的比率。
-
近、远:用于剪辑,我会忽略这些。
生成的矩阵是列主矩阵,在上面的代码中索引如下:
0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15
视口变换、屏幕坐标
这两种变换都需要另一个矩阵矩阵将事物放入屏幕坐标中,称为视口变换。这就是这里描述的,我不会介绍它(非常简单) http://www.songho.ca/opengl/gl_transform.html.
因此,对于点 p,我们会:
- 执行模型变换矩阵*p,得到pm。
- 执行投影矩阵 * pm,结果为 pp。
- 根据观看量剪裁 pp。
- 执行视口变换矩阵 * pp,结果为 ps:屏幕上的点。
Summary
我希望这涵盖了大部分内容。上面有漏洞,有些地方含糊不清,有问题可以在下面留言。这个主题通常值得在教科书中用整整一章来写,我已尽我最大的努力来提炼这个过程,希望对您有利!
我链接到了上面的内容,但我强烈建议您阅读此内容并下载二进制文件。它是一个很好的工具,可以帮助您进一步了解这些转换以及它如何在屏幕上获得分数:
http://www.songho.ca/opengl/gl_transform.html http://www.songho.ca/opengl/gl_transform.html
就实际工作而言,您需要实现用于齐次变换的 4x4 矩阵类以及可以与其相乘以应用变换的齐次点类(请记住,[x, y, z, 1])。您需要按照上面和链接中的描述生成转换。一旦你理解了这个过程,一切就不再那么困难了。祝你好运:)。