我正在尝试将3D点绘制到2D表面上(我目前正在使用SDL.NET作为我的“游戏引擎”)。表面尺寸为800x400像素,3d坐标范围为-4000到4000.我的视图将始终是一个自上而下的视图,不会有任何相机移动。有人可以提供一些原生的c#,伪代码或一个简单的解释,用于将三维空间中的坐标转换为二维表面吗?
同时我订购this book人们告诉我它会解决我的很多数学缺点......希望:)
答案 0 :(得分:10)
注意: 这是一个很大的文本墙,我完全瞥了很多重要的东西 - 但我的意图只是一个概述...希望这里的一些术语/概念将引导你更好地搜索网上适当的块。
如果你一路走过" Life as a point":
,这会有所帮助我们在这里,一个不错的小三维点:
var happyPoint = new Point(0, 0, 0);
以下是与其朋友有关的朋友:
var friendlyPoint = new Point(1, 0, 0);
现在,让我们将这两点称为" model" - 我们将使用术语"模型空间"谈论 中的点一个三维结构(如房子,怪物等)。
模特不会生活在真空中,但是......通常更容易将模型空间分开。#34;模型空间"和#34;世界空间"使模型调整更容易(否则,所有模型都需要具有相同的比例,具有相同的方向等,再加上尝试在3d建模程序中处理它们将是不可能的)
因此,我们将定义一个" World Transform"对于我们的"模型" (好吧,2分是一个蹩脚的模型,但它仍然是一个模型)。
什么是"世界变革"?简单地说:
W = T X R X S
,其中我们将在这里轻松一点,并将我们的世界转换定义为身份矩阵 - 基本上,这意味着我们不希望它翻译,旋转或规模:
world = [
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
];
我强烈建议你刷新你的Matrix数学,特别是乘法和Vector->矩阵运算,它在3D图形中使用了所有的时间。
如此巧妙地跳过实际的矩阵乘法,我只是告诉你,乘以我们的"世界变换"我们的模型点再次以我们的模型点结束(虽然在这个有趣的新的4维向量表示中,我在这里没有触及)。
所以我们已经得到了我们的观点,而且我们已经将它们完全定位在“空间”中......现在是什么?
那么,我们从哪里来看?这导致View Transformations
或Camera Projection
的概念 - 基本上,它只是另一个矩阵乘法 - 观察:
说我们得到了一个点X,在...哦,(4 2)左右:
|
|
|
|
| X
|
------------------------
从原点(0 0)的角度来看,X 是 at(4 2) - 但是我们说我们把相机放到了右边?
|
|
|
|
| X >-camera
|
------------------------
什么是"位置" X,相对于相机?可能更接近(0 9)或(9 0),取决于你的相机" up"和"对"方向是。这就是视图转换 - 将一组3D点映射到另一组3D点,使得它们是正确的#34;从观察者的角度来看。在你自上而下的固定摄像机的情况下,你的观察者将在天空中的某个固定位置,所有模型将相应地进行转换。
所以,让我们画画吧!
不幸的是,我们的屏幕还没有3D(还),所以首先我们需要"投射"这一点到2D表面上。投影是......好吧,它基本上是一个看起来像的映射:
(x, y, z) => (x, y)
可能的投影数量是近无限的:例如,我们可以通过X
转换Y
和Z
坐标:
func(x, y, z) => new point2d(x + z, y + z);
通常,您希望此投影模仿人类视网膜在观看3D场景时所做的投影,但是,我们引入了 View Projection 的概念。有一些不同的视图投影,例如正交, YawPitchRoll定义和透视/ FOV定义;其中每一项都有一些正确构建投影所需的关键数据。
例如,基于透视/ FOV的投影需要:
一旦你获得了这些数字,就会创建一个名为" bounding frustum"的东西,它看起来有点像金字塔顶部的顶部:
\-----------------/
\ /
\ /
\ /
\ /
\-------/
或者从前面:
___________________
| _____________ |
| | | |
| | | |
| | | |
| | | |
| | | |
| |_____________| |
|___________________|
我不会在这里进行矩阵计算,因为其他地方都很好地定义了 - 事实上,大多数库都有辅助方法,可以为你生成相应的矩阵 - 但是这里&#39 ;大致如何运作:
让我们说你快乐的小点在于这个截头的:
\-----------------/
\ /
\ o<-pt /
\ /
\ /
\-------/
___________________
| _____________ |
| | | |
| | | |
|o | | |
|^---- pt | |
| | | |
| |_____________| |
|___________________|
注意它离开侧面,到目前为止它已经离开了近距离平面&#34;矩形 - 如果你&#34;看到&#34;它会是什么样子?金字塔的较小一端?
就像观察棱镜(或镜头)一样,重点是弯曲&#34;进入视图:
___________________
| _____________ |
| | | |
| | | |
|>>>o <- pt is | |
| | shifted | |
| | | |
| |_____________| |
|___________________|
换句话说,如果你的背后有一个明亮的光线 ,那么你的点的阴影会在哪里被投射&#34;在近剪裁场? (较小的矩形)所有投影都是 - 一个点到另一个点的映射,在这种情况下,移除Z分量并相应地改变X和Y,使得&#34;有意义&#34;我们的眼睛。
答案 1 :(得分:2)
您需要考虑视角。根据您的观点,情节点会有所不同。如果你想要一个正交透视图(基本上没有透视图),你可以运行它像这样的矩阵变换:
其中 a 表示您的3D点, b 表示您的2D点结果。 vector s 是任意比例因子, c 是任意偏移量
这是另一篇与此类似的帖子,答案很好:
Basic render 3D perspective projection onto 2D screen with camera (without opengl)
以下是更多信息