3d到2d点转换

时间:2013-02-26 01:28:50

标签: c# 3d 2d point projection

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

同时我订购this book人们告诉我它会解决我的很多数学缺点......希望:)

2 个答案:

答案 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,其中
  • T = 翻译 - 即沿X,Y或Z轴滑动
  • R = 旋转 - 相对于轴转动模型
  • S = 缩放 - 沿着轴调整模型大小(保持其中的所有相对点)

我们将在这里轻松一点,并将我们的世界转换定义为身份矩阵 - 基本上,这意味着我们不希望它翻译,旋转或规模:

world = [
          1 0 0 0
          0 1 0 0
          0 0 1 0
          0 0 0 1
        ];

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

如此巧妙地跳过实际的矩阵乘法,我只是告诉你,乘以我们的"世界变换"我们的模型点再次以我们的模型点结束(虽然在这个有趣的新的4维向量表示中,我在这里没有触及)。

所以我们已经得到了我们的观点,而且我们已经将它们完全定位在“空间”中......现在是什么?

那么,我们从哪里来看?这导致View TransformationsCamera 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转换YZ坐标:

func(x, y, z) => new point2d(x + z, y + z);

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

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

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

一旦你获得了这些数字,就会创建一个名为" bounding frustum"的东西,它看起来有点像金字塔顶部的顶部:

\-----------------/
 \               /
  \             /
   \           /
    \         /
     \-------/

或者从前面:

 ___________________
|   _____________   |
|  |             |  |
|  |             |  |
|  |             |  |
|  |             |  |
|  |             |  |
|  |_____________|  |
|___________________|

我不会在这里进行矩阵计算,因为其他地方都很好地定义了 - 事实上,大多数库都有辅助方法,可以为你生成相应的矩阵 - 但是这里&#39 ;大致如何运作:

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

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

 ___________________
|   _____________   |
|  |             |  |
|  |             |  |
|o |             |  |
|^---- pt        |  |
|  |             |  |
|  |_____________|  |
|___________________|

注意它离开侧面,到目前为止它已经离开了近距离平面&#34;矩形 - 如果你&#34;看到&#34;它会是什么样子?金字塔的较小一端?

就像观察棱镜(或镜头)一样,重点是弯曲&#34;进入视图:

 ___________________
|   _____________   |
|  |             |  |
|  |             |  |
|>>>o <- pt is   |  |
|  |    shifted  |  |
|  |             |  |
|  |_____________|  |
|___________________|

换句话说,如果你的背后有一个明亮的光线 ,那么你的点的阴影会在哪里被投射&#34;在近剪裁场? (较小的矩形)所有投影都是 - 一个点到另一个点的映射,在这种情况下,移除Z分量并相应地改变X和Y,使得&#34;有意义&#34;我们的眼睛。

答案 1 :(得分:2)

您需要考虑视角。根据您的观点,情节点会有所不同。如果你想要一个正交透视图(基本上没有透视图),你可以运行它像这样的矩阵变换:

enter image description here

其中 a 表示您的3D点, b 表示您的2D点结果。 vector s 是任意比例因子, c 是任意偏移量

这是另一篇与此类似的帖子,答案很好:

  

Basic render 3D perspective projection onto 2D screen with camera (without opengl)

以下是更多信息

  

http://en.wikipedia.org/wiki/3D_projection