【问题标题】:Detect and Remove Hidden Surfaces of a Mesh检测并移除网格的隐藏表面
【发布时间】:2014-09-20 04:38:18
【问题描述】:

在过去的几周里,我一直在研究一种算法,该算法可以找到复杂网格的隐藏表面并将其移除。这些隐藏的表面被完全遮挡,永远不会被看到。由于我正在使用的网格的性质,有很多这些隐藏的三角形。在某些情况下,隐藏的表面比可见的表面多。由于手动删除它们对于较大的网格来说是禁止的,我希望用软件来自动化它。

我目前的算法包括:

  1. 在三角形曲面上生成多个点。
  2. 对于每个点,生成一个与三角形法线对齐的半球采样器。
  3. 将光线投射到半球。
  4. 如果未被遮挡的光线少于一定数量,我将三角形标记为删除。

但是,这种算法引起了很多麻烦。这是非常不一致的。虽然算法没有发现一些“被遮挡”的面孔被算法遮挡,但我更担心由于当前实现的问题而被移除的非常明显的面孔。因此,我想知道两件事,主要是:

  1. 有没有比光线追踪更好的方法来查找和移除这些隐藏的表面?
  2. 我应该调查非随机射线生成吗?我目前正在余弦加权半球中生成随机方向,这可能会导致问题。我没有对此进行研究的唯一原因是因为我还没有找到一种算法来在半球中生成均匀分布的光线。

注意:这是一种对象空间算法。也就是说,从任何角度都能看到——不是固定的摄像头。

【问题讨论】:

  • 关于你的最后一个问题,请参阅mathworld.wolfram.com/SpherePointPicking.html 以在半球中生成均匀间隔的光线
  • 这称为“背面剔除”,可能有助于搜索。至于检测一个可剔除的面,为什么不将每个顶点的光线投射到您的相机上,然后如果来自三角形的所有三条光线都与另一个面相交,则该三角形被完全遮挡并且可以从网格中移除。需要注意的是,OpenGL等图形库可以在渲染阶段为你做到这一点
  • @DrewMcGowen 感谢您的链接。我已经看过了。主要问题是,由于算法的计算强度很高,我希望将光线保持在最低限度(一些网格已经需要 1000 亿条光线,每个半球有 512 条光线)。与任何随机事物一样,总是存在点“簇”。我一直在寻找能够产生完美均匀分布光线的东西。最终,我可能会在头文件或其他文件中分解并硬编码均匀间隔光线的方向。
  • @Bojangles 仅仅因为从三角形的每个顶点到相机的光线被遮挡并不意味着整个三角形都被遮挡
  • 我知道您正在寻找对象空间算法,但是我不明白如何隐藏某些东西?当一个表面被隐藏时,还必须有一个观察点,从该观察点隐藏该表面。如果将相机放置在离表面足够近的位置,则任何表面都应该可见。或者您的表面是否封闭并且您想要完全移除其他表面内的表面?也许你可以澄清你对隐藏的定义?

标签: c++ algorithm optimization mesh raytracing


【解决方案1】:

我实际上从未实现过光线追踪,但无论如何我有一些建议。由于您的目标是检测每个隐藏的三角形,因此您可以扭转问题,而是找到每个可见的三角形。

我正在考虑以下两种情况:

  1. 从外部向中心/垂直于表面的光线追踪,将任何击中的三角形标记为可见。
  2. 剔除所有其他人。

  1. 选择您的模型的视图。
  2. 对模型进行栅格化(例如,为每个三角形使用不同的颜色)。
  3. 将任何可见的三角形标记为可见。
  4. 改变方向并重复。
  5. 剔除所有不可见的三角形。

最后一个的优点是,如果您可以可靠地读取/写入像素,则使用图形 API 实现应该相对便宜。

两者的缺点是所需的分辨率。不应剔除的小开口内的三角形可能仍然存在,因此光线的数量可能会令人望而却步(在第一个算法中),或者您将需要非常大的屏幕外帧缓冲区(在第二个算法中)。

【讨论】:

  • 我最初使用光线追踪的尝试是在模型周围使用一个大球体并向内投射光线。但是,存在无法保留的非常大的内部空间的问题。我主要是想删除将要创建的较小的“房间”。因此,实际上有人推荐了一种算法,该算法可以测试到其他表面的距离,并尝试确定该表面是否以这种方式被遮挡。但是,我还没有真正尝试过,因为我不知道它是否适用于所有情况。
  • 另外,我想补充一点,我在技术上使用当前算法查找所有可见三角形。也就是说,我正在测试所有三角形中是否有未被遮挡的光线或没有击中任何东西的光线。一开始这些三角形都“被认为”被遮挡了。
  • 嗯,我明白了...如果您能够识别这些内部空间的“入口”,这可能仍然是一种可行的方法,但我看到您仍然会遇到长开的圆柱体等问题. 你有更多关于你期望得到的形状的信息吗?或者它们是完全任意的?
  • 不幸的是,它们几乎完全是任意的三角形网格。至于寻找“入口”,我的一个朋友实际上建议我研究某种流体模拟算法,在其中我“淹没”网格,然后查看哪些三角形与水接触。理论上,被遮挡的三角形永远不会接触到“流体”。然而,这会给在某些情况下被遮挡的三角形带来误报。
  • 嗯。一个让我印象深刻的想法是,您可能试图一步完成太多事情。以您在上面制作的示例为例。您将如何区分禁止进入房间中的雕塑背面与您可以四处走动的完全相同的房间。区分网格的可访问部分和仅可见部分可能是一个想法。在可到达的部分,洪水可能是合适的,对于可见部分,您将需要有关可能视图的信息。
【解决方案2】:

一些可能会有所帮助的想法。

  1. 使用连接测试来确定连接到您的主模型(如果有的话)。
  2. 使用Depth Peeling 的变体(我用它来将壳转换为体素;一旦您知道模型内部要保留的内容(体素),您就可以与要删除的垃圾相交.)
  3. 创建连接图并根据连接组的复杂性修剪该图。

【讨论】:

  • 我不确定第 1 点在这种情况下有何帮助。你能再解释一下吗?是不是有可能隐藏的面是主船体的一部分,而可见的面不是?
  • 它假定您要删除的大部分内容都是三角形的小组。如果是这样,您可以确定哪些点是连接的 tris 的一部分(共享点)。每个连接的组都可以分配一个唯一的 ID。然后你想保留的组可以以某种方式被隔离(其余的被删除)。
  • 连接图是我一开始考虑的,但它没有提供我想要的结果。深度剥离的想法可能很有趣。感谢您的想法。
  • 哇,深度剥离看起来很有趣。唯一的问题是使用屏幕空间技术可能会有问题。我一定会考虑的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-25
  • 2021-10-03
  • 1970-01-01
  • 2023-03-10
  • 2014-12-05
相关资源
最近更新 更多