我正在尝试将 3D 点绘制到 2D 表面上(我目前正在使用 SDL.NET 作为我的“游戏引擎”)。表面大小为 800x400 像素,3d 坐标范围为 -4000 到 4000。我的视图将始终是自上而下的视图,并且不会有任何相机移动。有人可以提供一些本机 c#、伪代码或简单的解释来将 3-D 空间中的坐标转换为 2-D 表面吗?
与此同时,我订购了这本书,人们告诉我它会解决我的许多数学缺点……希望 :)
注意:这是一堵巨大的文字墙,我完全忽略了很多重要的东西——但我在这里的意图只是一个概述……希望这里的一些术语/概念将引导你更好地在谷歌上搜索适当的块网。
如果您通过“生活作为一个点”走自己的路,它会有所帮助:
这是一个不错的 3 维小点:
var happyPoint = new Point(0, 0, 0);
这是它的伙伴,根据他的朋友定义:
var friendlyPoint = new Point(1, 0, 0);
现在,让我们将这两个点称为“模型”——我们将使用“模型空间”一词来讨论单个 3 维结构(如房子、怪物等)内的点。
然而,模型并不存在于真空中……通常更容易将“模型空间”和“世界空间”分开,以使模型调整更容易(否则,您的所有模型都需要具有相同的比例,具有相同的方向等,等等,再加上尝试在 3D 建模程序中对它们进行处理将是不可能的)
所以我们将为我们的“模型”定义一个“世界变换”(好的,2 点是一个蹩脚的模型,但它仍然是一个模型)。
什么是“世界变换”?简单的说:
W = T X R X S
,在哪里我们将在这里放轻松,只需将我们的世界变换定义为单位矩阵 - 基本上,这意味着我们不希望它平移、旋转或缩放:
world = [
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
];
我强烈建议您复习一下您的矩阵数学,尤其是乘法和向量-> 矩阵运算,它一直在 3D 图形中使用。
如此巧妙地跳过了实际的矩阵乘法,我只想告诉你,将我们的“世界变换”和我们的模型点相乘最终会再次得到我们的模型点(尽管在这个有趣的新 4 维向量表示中,我赢了'触摸这里)。
所以我们得到了我们的观点,我们已经将它们完全定位在“空间”中......现在呢?
那么,我们从哪里看呢?这导致了View Transformations
or的概念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 场景时所做的投影,因此我们引入了View Projection的概念。有几种不同的视图投影,例如Orthographic、YawPitchRoll-defined和Perspective/FOV-defined;其中每一个都有一些关键数据,您需要正确构建投影。
例如,基于 Perspective/FOV 的投影需要:
一旦你得到了这些数字,你就可以创建一个叫做“边界平截头体”的东西,它看起来有点像一个顶部被截断的金字塔:
\-----------------/
\ /
\ /
\ /
\ /
\-------/
或者从前面:
___________________
| _____________ |
| | | |
| | | |
| | | |
| | | |
| | | |
| |_____________| |
|___________________|
我不会在这里进行矩阵计算,因为这在其他地方都有很好的定义——事实上,大多数库都有帮助方法,可以为你生成相应的矩阵——但大致是它的工作原理:
假设您的快乐小点在于这个截锥体:
\-----------------/
\ /
\ o<-pt /
\ /
\ /
\-------/
___________________
| _____________ |
| | | |
| | | |
|o | | |
|^---- pt | |
| | | |
| |_____________| |
|___________________|
请注意,它偏向一边,以至于它超出了“近剪切平面”矩形 - 如果您“查看”金字塔的较小端会是什么样子?
就像观察棱镜(或镜头)一样,这一点将被“弯曲”到视野中:
___________________
| _____________ |
| | | |
| | | |
|>>>o <- pt is | |
| | shifted | |
| | | |
| |_____________| |
|___________________|
换句话说,如果你在截锥体后面有一盏明亮的灯,你的点的阴影会在哪里“投射”到附近的剪裁场上?(较小的矩形)这就是所有投影 - 一个点到另一个点的映射,在这种情况下,移除 Z 分量并相应地改变 X 和 Y 以对我们的眼睛“有意义”的方式。
你需要考虑视角。根据您的观点,情节点会有所不同。如果你想要一个正交透视(本质上没有透视),你可以像这样运行它的矩阵变换:
其中a代表您的 3D 点,b代表您的 2D 点结果。向量s是任意比例因子,c是任意偏移量
这是另一个与此类似的帖子,答案很好:
这是更多信息