【问题标题】:3d to 2d point conversion [closed]3d到2d点转换[关闭]
【发布时间】:2013-02-11 08:26:44
【问题描述】:

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

与此同时,我订购了this book,人们告诉我这将解决我的许多数学缺点....希望 :)

【问题讨论】:

  • 您的 3D 坐标都是 -4000 到 +4000 吗?您想在 800x400 网格上显示整个地图还是移动窗口?
  • 我刚刚将 3-D 坐标转换为 2-D 表面,并想分享我的方法,因为它与下面的答案有很大不同。我的数学技能不是最好的,所以我相信我的解决方案虽然简单,但可能有助于某人理解这种转换(使用 10 年级数学)。

标签: c# 3d 2d point projection


【解决方案1】:

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

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

我们来了,一个漂亮的 3 维小点:

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

这是它的好友,与他的朋友有关:

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

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

模型并非生活在真空中,但是...通常更容易将“模型空间”和“世界空间”分开,以便更轻松地进行模型调整(否则,您的所有模型都需要位于相同的比例、相同的方向等等,再加上尝试在 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
        ];

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

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

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

好吧,我们从哪里看它?这就引出了View TransformationsCamera 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 场景时的投影,因此我们引入了视图投影的概念。有几种不同的视图投影,如 OrthographicYawPitchRoll-definedPerspective/FOV-defined;每一个都有一些关键数据,您需要正确构建投影。

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

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

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

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

或者从前面:

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

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

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

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

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

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

就像看棱镜(或镜头)一样,点会被“弯曲”到视野中:

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

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

【讨论】:

  • 哇,真是一个答案,非常感谢,我现在对理论有了更好的理解。我将开始构建我的“转换器”并在今天晚些时候在这里发布代码,看看我是否做得对,干杯 m8!
  • 这值得更多的支持!!
【解决方案2】:

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

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

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

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

这里有更多信息

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 2023-03-08
    • 2011-06-30
    • 1970-01-01
    • 2020-02-16
    相关资源
    最近更新 更多