3d到2d点转换

Mar*_*ger 1 c# 3d 2d point projection

我正在尝试将3D点绘制到2D表面上(我目前正在使用SDL.NET作为我的"游戏引擎").表面尺寸为800x400像素,3d坐标范围为-4000到4000.我的视图将始终是一个自上而下的视图,并且不会有任何相机移动.有人可以提供一些原生的c#,伪代码或简单的解释,将三维空间中的坐标转换为二维曲面?

同时我订购了这本书,人们告诉我它将解决我的许多数学缺点....希望:)

Jer*_*all 11

注意:这是一个很大的文本墙,我完全瞥了很多重要的东西 - 但我的意图只是一个概述...希望这里的一些术语/概念将引导你更好的谷歌搜索适当的块上网页.

如果你走过"生活为点",它会有所帮助:

我们在这里,一个很好的小三维点:

var happyPoint = new Point(0, 0, 0);
Run Code Online (Sandbox Code Playgroud)

以下是与其朋友有关的朋友:

var friendlyPoint = new Point(1, 0, 0);
Run Code Online (Sandbox Code Playgroud)

现在,让我们叫这两点我们的"模式" -我们将使用术语"模型空间"谈点一个单一的三维结构(如房子,怪物等).

模型不是真空,但是......通常更容易将"模型空间"和"世界空间"分开,以便更容易进行模型调整(否则,所有模型都需要具有相同的比例,有相同的方向等等,加上尝试在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
        ];
Run Code Online (Sandbox Code Playgroud)

我强烈建议你刷新你的Matrix数学,特别是乘法和Vector-> Matrix操作,它在3D图形中使用了所有的快速时间.

如此巧妙地跳过实际的矩阵乘法,我只会告诉你,将我们的"世界变换"与我们的模型点相乘只会再次得到我们的模型点(尽管在这个有趣的新的四维矢量表示中,我赢了'触摸这里).

所以我们得到了我们的观点,我们绝对将它们放在"太空"中......现在怎么样?

好吧,我们从哪里来看?这导致了概念View TransformationsCamera Projection- 基本上,它只是另一个矩阵乘法 - 观察:

假设我们有一个点X,在...哦,(4 2)左右:

 |
 |
 |
 |    
 |    X
 |
 ------------------------
Run Code Online (Sandbox Code Playgroud)

从原点(0 0)的角度来看,X (4 2) - 但是我们说我们的相机偏向右边?

 |
 |
 |
 |    
 |    X         >-camera
 |
 ------------------------
Run Code Online (Sandbox Code Playgroud)

相对于相机,X的"位置"是什么?可能更接近(0 9)或(9 0),取决于相机的"向上"和"向右"方向.这就是视图转换 - 将一组3D点映射到另一组3D点,使得它们从观察者的角度来看是"正确的".在你自上而下的固定摄像机的情况下,你的观察者将在天空中的某个固定位置,所有模型将相应地进行转换.

让我们画画!

不幸的是,我们的屏幕不是3D(还),所以首先我们需要将这个点"投影"到2D表面上.投影是......好吧,它基本上是一个看起来像的映射:

(x, y, z) => (x, y)
Run Code Online (Sandbox Code Playgroud)

可能的投影数量是近无限的:例如,我们可以通过以下方式移动XY坐标Z:

func(x, y, z) => new point2d(x + z, y + z);
Run Code Online (Sandbox Code Playgroud)

通常,您希望此投影模仿人类视网膜在观看3D场景时所做的投影,但是,我们引入了View Projection的概念.有一些不同的视图投影,如Orthographic,YawPitchRoll-definedPerspective/FOV-defined ; 这些中的每一个都有一些正确构建投影所需的关键数据.

例如,基于透视/ FOV的投影需要:

  • 你的"眼球"(即屏幕)的位置
  • 你的"眼球"能够聚焦的距离有多远("远剪裁平面")
  • 您的角度视野(即,伸出双臂,只是在周边视野的边缘)
  • 您正在查看的"镜头"的宽高比(通常是您的屏幕分辨率)

一旦你得到这些数字,你就会创建一个叫做"边界平截头体"的东西,看起来有点像金字塔顶部的顶部:

\-----------------/
 \               /
  \             /
   \           /
    \         /
     \-------/
Run Code Online (Sandbox Code Playgroud)

或者从前面:

 ___________________
|   _____________   |
|  |             |  |
|  |             |  |
|  |             |  |
|  |             |  |
|  |             |  |
|  |_____________|  |
|___________________|
Run Code Online (Sandbox Code Playgroud)

我不会在这里进行矩阵计算,因为它在其他地方都已经很好地定义了 - 实际上,大多数库都有辅助方法,它们会为你生成相应的矩阵 - 但这里大概是如何工作的:

让我们说你的快乐小点在于这个截头体:

\-----------------/
 \               /
  \ o<-pt       /
   \           /
    \         /
     \-------/

 ___________________
|   _____________   |
|  |             |  |
|  |             |  |
|o |             |  |
|^---- pt        |  |
|  |             |  |
|  |_____________|  |
|___________________|
Run Code Online (Sandbox Code Playgroud)

注意它离开了一边,到目前为止,它已经超出了"近剪裁平面"矩形 - 如果你"调查"金字塔的较小一端会是什么样子?

就像观察棱镜(或镜头)一样,这一点将"弯曲"到视野中:

 ___________________
|   _____________   |
|  |             |  |
|  |             |  |
|>>>o <- pt is   |  |
|  |    shifted  |  |
|  |             |  |
|  |_____________|  |
|___________________|
Run Code Online (Sandbox Code Playgroud)

换句话说,如果你在平截头体后面有一道明亮的光线,那么你的点的阴影会在附近的剪切场上被"施放"?(较小的矩形)这是所有投影 - 一个点到另一个点的映射,在这种情况下,移除Z分量并相应地以对我们的眼睛"有意义"的方式改变X和Y.

  • 这值得更多的赞成!! (2认同)