注意:
这是一堵巨大的文字墙,我完全忽略了很多重要的东西——但我在这里的意图只是一个概述……希望这里的一些术语/概念将引导你更好地在网上搜索合适的块。
如果您通过“生活作为一个点”走自己的路会有所帮助:
我们来了,一个漂亮的 3 维小点:
var happyPoint = new Point(0, 0, 0);
这是它的好友,与他的朋友有关:
var friendlyPoint = new Point(1, 0, 0);
现在,让我们将这两个点称为我们的“模型”——我们将使用术语“模型空间”来讨论点内单个三维结构(如房子、怪物等)。
模型并非生活在真空中,但是...通常更容易将“模型空间”和“世界空间”分开,以便更轻松地进行模型调整(否则,您的所有模型都需要位于相同的比例、相同的方向等等,再加上尝试在 3D 建模程序中处理它们是完全不可能的)
所以我们将为我们的“模型”定义一个“世界变换”(好的,2 点是一个蹩脚的模型,但它仍然是一个模型)。
什么是“世界变换”?简单地说:
- 世界变换
W = T X R X S,其中
- T = 平移 - 即沿 X、Y 或 Z 轴滑动
- R = 旋转 - 相对于轴转动模型
- S = 缩放 - 沿轴调整模型的大小(保留其中的所有相对点)
我们在这里放轻松,只需将我们的世界变换定义为 Identity 矩阵 - 基本上,这意味着我们不希望它平移、旋转或缩放:
world = [
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
];
我强烈建议你复习一下你的矩阵数学,尤其是乘法和向量->矩阵运算,它在 3D 图形中一直使用。
巧妙地跳过了实际的矩阵乘法,我只想告诉你,将我们的“世界变换”和我们的模型点相乘,最终会再次得到我们的模型点(尽管在这个有趣的新 4 维向量表示中,它这里我就不说了)。
所以我们得到了我们的观点,我们已经将它们完全定位在“空间”中......现在呢?
好吧,我们从哪里看它?这就引出了View Transformations 或Camera Projection 的概念——基本上,它只是另一个矩阵乘法——观察:
假设我们有一个点 X,在...哦,(4 2) 左右:
|
|
|
|
| X
|
------------------------
从原点 (0 0) 的角度来看,X 是 在 (4 2) - 但是假设我们将相机放在右边?
|
|
|
|
| X >-camera
|
------------------------
X 相对于相机的“位置”是什么?可能更接近 (0 9) 或 (9 0),具体取决于相机的“向上”和“正确”方向。这就是视图转换 - 将一组 3D 点映射到另一组 3D 点,这样它们从观察者的角度来看是“正确的”。在您使用自上而下的固定相机的情况下,您的观察者将位于天空中的某个固定位置,所有模型都会相应地进行转换。
让我们画画吧!
不幸的是,我们的屏幕还不是 3D 的,所以首先我们需要将这个点“投影”到 2D 表面上。投影是……嗯,它基本上是一个如下所示的映射:
(x, y, z) => (x, y)
可能的投影数量几乎是无限的:例如,我们可以将X 和Y 坐标移动Z:
func(x, y, z) => new point2d(x + z, y + z);
通常,您希望此投影模拟人类视网膜在观看 3D 场景时的投影,因此我们引入了视图投影的概念。有几种不同的视图投影,如 Orthographic、YawPitchRoll-defined 和 Perspective/FOV-defined;每一个都有一些关键数据,您需要正确构建投影。
例如,基于透视/FOV 的投影需要:
- “眼球”(即屏幕)的位置
- “眼球”能够聚焦多远(“远剪切平面”)
- 您的视场角(即伸出双臂,就在您的周边视觉边缘)
- 您正在查看的“镜头”的宽高比(通常是您的屏幕分辨率)
一旦你得到这些数字,你就可以创建一个叫做“边界平截头体”的东西,它看起来有点像一个顶部被截断的金字塔:
\-----------------/
\ /
\ /
\ /
\ /
\-------/
或者从前面:
___________________
| _____________ |
| | | |
| | | |
| | | |
| | | |
| | | |
| |_____________| |
|___________________|
我不会在这里进行矩阵计算,因为这在其他地方都已经很好地定义了 - 事实上,大多数库都有可以为您生成相应矩阵的辅助方法 - 但它的大致工作原理如下:
假设你的快乐点在于这个截锥体:
\-----------------/
\ /
\ o<-pt /
\ /
\ /
\-------/
___________________
| _____________ |
| | | |
| | | |
|o | | |
|^---- pt | |
| | | |
| |_____________| |
|___________________|
注意它偏向一边,以至于它超出了“近剪切平面”矩形 - 如果您“观察”金字塔的较小一端会是什么样子?
就像看棱镜(或镜头)一样,点会被“弯曲”到视野中:
___________________
| _____________ |
| | | |
| | | |
|>>>o <- pt is | |
| | shifted | |
| | | |
| |_____________| |
|___________________|
换一种说法,如果你有一个明亮的光背后平截头体,你的点的阴影会被“投射”到附近的剪裁场的什么地方? (较小的矩形)这就是所有投影 - 一个点到另一个点的映射,在这种情况下,移除 Z 分量并相应地改变 X 和 Y 以一种对我们的眼睛“有意义”的方式。