algorithm - "false 3D"棱镜墙的渲染顺序

标签 algorithm 3d geometry 2d rendering

我正在使用 Python 和 pygame 开发“伪 3D”游戏。 gfx 仅包含使用不同尺寸和颜色的 2D 图元创建的棱镜:

enter image description here

游戏的 gfx 是如何工作的:

enter image description here

问题出现在第 4 点,当我想在渲染队列中以正确的顺序对墙壁进行排序时(决定哪一个是最接近的并且必须首先渲染,哪个是第二个,哪个是最后一个等)。

目前,为了对墙壁进行排序,我移除了所有不可见的墙壁并测量了 playerwall 之间的最短距离。它有效……但只有当场景中只有一个多边形时。示例(2 个多边形):

enter image description here

我可以处理这种特定类型的问题,但我不知道将来是否还会有其他问题。我的问题:是否有任何算法(有效...)可以按正确的顺序对我的墙壁进行排序,并且我能够面带微笑地渲染它们?

最佳答案

我猜我们可以假设多边形不相交。如果是这种情况,我们不需要拆分任何东西。然而,找到正确的顺序在计算上仍然很繁重。尽管人们可能会想出一种增量方法,即逐帧更新必要的内容。

事情是这样的。在您的 2 多边形示例中,基于一条线的两个最近点的顺序显然不起作用,因为它们具有不同的 View 方向。但是如果你选择具有相同视角方向的点(在它们重叠的区域),你会清楚地看到 A 在 B 的前面。那么,我们需要做什么:

首先找到所有可见的墙。我们将为这些墙创建可见性图。因此,创建一个图表,其中每面墙都由一个节点表示。最后,您将计算此图的拓扑排序以获得绘制顺序。现在,我们如何找到边缘,即关于哪堵墙在另一堵墙前面的信息?为此,首先找到重叠的墙对(挤压墙)。您可能希望使用像 AABB 树这样的加速数据结构来加快速度。

然后我们需要 View 方向的一维参数化。方向和 x 轴之间的角度可能工作得很好 (a = atan2(lineY - playerY, lineX - playerX)),尽管它具有您需要处理的烦人的周期性。我们现在将只考虑两堵墙的原始多边形边(不是拉伸(stretch)的墙)。找出两条线的一维间隔(例如,线 1 在 10° 和 35° 之间,线 2 在 20° 和 135° 之间)。如果这两个间隔不重叠,您可以跳过这对,因为它们的相对顺序无关紧要。如果他们这样做,找到重叠间隔中的任何点(例如 25°),找到相应的 View 方向(x = playerX + cos(25°), y = playerY + sin(25°))以及线上对应于该方向的点(例如,通过计算线与视线的交点)。然后,简单地计算两条线沿这条射线的距离。选择重叠间隔中的哪个点并不重要,因为线是线性的并且原始多边形不相交。如果到第 1 行的距离小于到第 2 行的距离,则将第 1 行到第 2 行的有向边添加到可见性图中(意味着第 1 行在第 2 行的前面),否则添加反向边。

最后,计算图形的拓扑顺序,您就有了绘图顺序。

选项 2

这是上述方法的替代方法,对于动态渲染可能更有效。这个想法是基于this publication .

首先对您的场景进行三角测量,即用三角形填充空隙(这只需要完成一次)。然后,我们的可见性图存储三角形(而不是边)。对于从内部看到的每个三角形边,将三角形的边添加到入射到该边的相邻三角形。最后,再次计算拓扑排序并按该顺序绘制墙壁(跳过空三角形)。

动态情况下的效率来自这样一个事实,即您只需对图表进行少量更新。对于每条边,您要确定是从前面还是从后面看到它们。因此,只有当视点穿过边指定的无限直线时,边的方向才会反转。如果您找到所有这些边(自上一帧以来改变了方向),您可以更新图表并进行相应排序。

关于algorithm - "false 3D"棱镜墙的渲染顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53218413/

相关文章:

android - 在 Android 应用程序中导入并显示 WRL 文件中的模型

algorithm - 如何检测椭圆是否与圆相交(相撞)

elasticsearch - 将 GeoJSON 字符串转换为 Elasticsearch 几何

c++ - 什么是opencv中的V4L/AVLD?

python - 检查通过元素的 + 和 - 的任意组合,数组总和是否为零

string - 什么更好地在运行时生成随机 ID 或之前将它们放在手边?

algorithm - 0/1 背包动态规划优化,从2D矩阵到1D矩阵

algorithm - 将 XY 平面实体转换为任意平面

performance - 获得 10000+ 个唯一的随机数(性能)

Java 3D 几何库