1

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

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

4

2 回答 2

12

注意:这是一堵巨大的文字墙,我完全忽略了很多重要的东西——但我在这里的意图只是一个概述……希望这里的一些术语/概念将引导你更好地在谷歌上搜索适当的块网。

如果您通过“生活作为一个点”走自己的路,它会有所帮助:

这是一个不错的 3 维小点:

var happyPoint = new Point(0, 0, 0);

这是它的伙伴,根据他的朋友定义:

var friendlyPoint = new Point(1, 0, 0);

现在,让我们将这两个点称为“模型”——我们将使用“模型空间”一词来讨论单个 3 维结构(如房子、怪物等)内的点。

然而,模型并不存在于真空中……通常更容易将“模型空间”和“世界空间”分开,以使模型调整更容易(否则,您的所有模型都需要具有相同的比例,具有相同的方向等,等等,再加上尝试在 3D 建模程序中对它们进行处理将是不可能的)

所以我们将为我们的“模型”定义一个“世界变换”(好的,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
        ];

我强烈建议您复习一下您的矩阵数学,尤其是乘法和向量-> 矩阵运算,它一直在 3D 图形中使用。

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

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

那么,我们从哪里看呢?这导致了View Transformationsor的概念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)

可能的投影数量几乎是无限的:例如,我们可以将XY坐标移动Z

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

通常,您希望此投影模拟人类视网膜在查看 3D 场景时所做的投影,因此我们引入了View Projection的概念。有几种不同的视图投影,例如OrthographicYawPitchRoll-definedPerspective/FOV-defined;其中每一个都有一些关键数据,您需要正确构建投影。

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

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

一旦你得到了这些数字,你就可以创建一个叫做“边界平截头体”的东西,它看起来有点像一个顶部被截断的金字塔:

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

或者从前面:

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

我不会在这里进行矩阵计算,因为这在其他地方都有很好的定义——事实上,大多数库都有帮助方法,可以为你生成相应的矩阵——但大致是它的工作原理:

假设您的快乐小点在于这个截锥体:

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

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

请注意,它偏向一边,以至于它超出了“近剪切平面”矩形 - 如果您“查看”金字塔的较小端会是什么样子?

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

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

换句话说,如果你在截锥体后面有一盏明亮的灯,你的点的阴影会在哪里“投射”到附近的剪裁场上?(较小的矩形)这就是所有投影 - 一个点到另一个点的映射,在这种情况下,移除 Z 分量并相应地改变 X 和 Y 以对我们的眼睛“有意义”的方式。

于 2013-02-26T02:35:36.643 回答
2

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

在此处输入图像描述

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

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

使用相机将 3D 透视投影基本渲染到 2D 屏幕(无 opengl)

这是更多信息

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

于 2013-02-26T01:35:31.820 回答