Opengl 如何在一个单位立方体世界里做面部除皱?

Opengl 如何在一个单位立方体世界里做面部除皱?,opengl,3d,rendering,minecraft,Opengl,3d,Rendering,Minecraft,重要提示:这个问题不是关于几何体剔除(平截体剔除、背面剔除、遮挡剔除或其任何朋友)。这个问题是关于设置时的几何体剔除,早在我们开始剔除和渲染之前 在一个单位立方体渲染的世界(la MineCraft)中,我试图找到如何从我的几何体列表中删除那些从任何角度都看不到的面(无论相机在哪里)的算法 例如,想象两个正方形: +----+ +----+ | | | | | | | | +----+ +----+ 很明显,有8条可见边(每个正方

重要提示:这个问题不是关于几何体剔除(平截体剔除、背面剔除、遮挡剔除或其任何朋友)。这个问题是关于设置时的几何体剔除,早在我们开始剔除和渲染之前

在一个单位立方体渲染的世界(la MineCraft)中,我试图找到如何从我的几何体列表中删除那些从任何角度都看不到的面(无论相机在哪里)的算法

例如,想象两个正方形:

+----+      +----+
|    |      |    |
|    |      |    |
+----+      +----+
很明显,有8条可见边(每个正方形上有4条)。现在我将正方形移动到一起,可见:

我现在只有6条边,而不是8条边!在中间触摸的两个镜头,无论放在哪里,也不可能看到。(正方形的纹理不同,因此我们不能称其为4边。)

(同样的事情也适用于三维立方体,但12个面(每个立方体6个)会随着2个接触被消除而变成10个。)

我的问题是:有哪些算法可以帮助我识别这些隐藏的面孔?(我很高兴自己做谷歌,但我甚至不知道这叫什么),特别是,我正在寻找一些处理中间空洞的东西——如果你在里面的话,这些斑点是可以看见的,但是因为它们被几何学所包围,你就看不到它们。 例如:

+----+----+----+----+
|                   |
|                   |
+    +----+         +
|    |    |         |
|    | A  |         |
+    +----+         +
|                   |
|                   |
+----+----+----+----+
在这种情况下,有人可能会认为有18条“可见”边,但因为我们知道相机在几何体之外,正方形“a”中的4条边是不可见的

为了使事情进一步复杂化,我希望找到一种算法,可以在添加或删除块时快速更新(同样是la MineCraft)


谢谢

你问题的第一部分非常简单。对于每个立方体,如果它与另一个立方体直接相邻,则删除它与该立方体共享的面

这不是性能问题(不包括修改和上载更改的顶点数据的成本),因为只有在放置或删除块时,才会重新计算。放置和移除块的效果相当局部;它只会影响6个相邻的立方体和它本身,所以它不应该是一个问题。除处理基于多维数据集的环境所需的明显数据结构外,您也不需要任何专门的数据结构

建造地形的初始成本可能是一些东西,但这是你可以承受的一次性成本。考虑到你的装载时间。如果您在一个框架的空间中进行大量的放置和移除,这可能是一个问题

更困难的问题是拆除密封的内部。我的建议是:这不值得。通过尝试移除密封内部,放置或移除块将成为非本地操作。通过花时间优化批处理计数(尽可能使用纹理地图集/阵列)和顶点数据,您可能会获得更高的性能

要移除密封的内部,您需要能够检测内部。因此,需要维护相邻面的双向图形。对于每个面,它将有四个相邻面。由于位于两个相邻立方体之间而被剔除的面(迄今为止称为“死面”)不应成为图形的一部分

放置立方体时,必须更新面图的邻接信息。死掉的脸需要去掉。放置后活动面的邻接需要合并由于放置的新块而添加的新面。如果你坐下来规划出可能性,那么实现这一点的算法应该相当简单。例如,如果您有这个正方形:

  A
+++++
+   +
+   + B
+   +
+++++
面A和B是相邻的。如果放置新块,将更改相邻关系:

     +++++
     +   +
   C +   +
     +   +
  A  +++++
+++++  D
+   +
+   + B
+   +
+++++
现在A与C相邻,B与D相邻

删除立方体后,必须再次更新面图的邻接信息。基本上,您必须反转上一个操作

这个邻接图的要点是:如果图中所有的非死面都是连接的,那么图中正好有一个循环是可见的;所有其他图形周期将不可见。图形的一个循环,是一组相互直接或间接连接的面

最大的问题是:你如何找到可见的周期?以下算法假定块由实体放置/移除。这意味着放置的任何块的至少一个面都是可见的。这还意味着通过删除块而变为活动的任何死面都是可见的

放置块时,可以创建一个或多个新的面循环。要检测这一点,首先查找通过放置块创建的所有非死面(与某个对象不直接相邻的面)。其中至少有一个是可见的;找到那张脸

然后,对于新块上的每一个非死面,使用A*(A星)图搜索来查找该面。A*是一种基于优先级队列的图形搜索算法。在这种情况下,算法的“距离”是当前面所在的正方形与可见面所在的正方形之间的距离

如果A*找不到面,那么您知道您搜索过的每个面(您可能应该在测试它们时将它们存储在缓冲区中)都是不可见循环的一部分,因此可以被剔除。应将这些面标记为不可见,以供以后参考

移除块要容易得多。删除块时,块的至少一个面必须可见(请参见上面的假设)。因此,如果要删除的块有一些不可见的面,则包括这些不可见面的循环中的每个面都必须可见。因此,在删除块之前,请检查块中是否有任何不可见的面。如果有,使用深度优先搜索查找所有fac
     +++++
     +   +
   C +   +
     +   +
  A  +++++
+++++  D
+   +
+   + B
+   +
+++++