【问题标题】:finding triangles of a mesh that are visible from a point [duplicate]找到从一点可见的网格三角形[重复]
【发布时间】:2018-11-28 22:40:00
【问题描述】:

我正在尝试实现一个子例程,用于查找从一个点可见的 3D 凸网格的所有三角形,而无需遍历所有三角形 但仅使用三角形与其邻居的连通性,网格始终具有可见的第一个三角形。

我只能想到递归方法,例如

struct trn
    vec3 vertices[3]
    vec3 normal
    trn* neighbors[3]
    bool checked = false

func(vec3 p, trn* t, trn* output[], uint size)
    t->checked = true
    for n in t->neighbors
        if n->checked
            continue
        if dot(n->normal, p - n->vertices[0]) > 0.0
            output[size] = n
            size++
            func(p, n, output, size)

但是递归方法很慢,而且这个例程应该比遍历所有三角形更快。

有没有什么想法或方法可以不用递归解决这个问题?

谢谢。

【问题讨论】:

  • 除了性能之外,是否还有其他原因需要使用连通性来遍历网格?因为如果性能是主要原因,我建议只探索一种线性复杂度算法,它会检查所有三角形而不是有效的数据表示。在今天的平均硬件上,仅检查每个三角形法线就能够每秒剔除数亿个或更多三角形是非常合理的(甚至不是惊人的)(特别是如果三角形法线和顶点位置存储在并行数组中)在 CPU 中(我已经做过很多次了)。
  • 通过连接方式遍历网格的棘手部分即使会导致一小部分算法迭代,也就是您基本上是以非常零星和随机访问的模式访问内存,等等最重要的是,连接数据通常会使需要加载的内存量增加一倍,并引入大量间接。即使算法复杂性降低,这在内存访问方面也是相当高的成本——我仍然倾向于避免连接遍历作为一种优化,除非我们谈论的是减少 [...]
  • [...] 线性时间的二次复杂度算法或类似的东西(算法复杂度的指数降低)。如果您仍然想以连接方式遍历它,无论出于何种原因,我建议的一件事是一次检查多个点/相机的背面剔除,而不是一次检查一个点/相机。这将增加每个三角形完成的工作量,以补偿连接遍历的额外成本。
  • @TeamUpvote:无论以何种方式枚举面,背面剔除在面数上都是线性的。背面可见面孔的比例非常接近 0.5。所以绝对不可能在渐近复杂度上获得任何收益,并且图遍历将是一种悲观化。
  • @scicyb:我的回答解决了这个问题。有一个 O(√F) 解。您似乎问了一个 XY 问题。

标签: algorithm geometry computational-geometry mesh convex-hull


【解决方案1】:

这看起来是个非常错误的想法。

因为

  • 无论如何,您都必须访问所有三角形(至少所有可见的三角形,见下文);

  • 单靠连接是不够的;无论如何都需要进行几何测试以考虑观察点的位置。

无论你做什么,复杂性必须与 可见 面的数量成线性关系,这与 面的数量也呈线性关系,你将换取一个用于复杂图形遍历的面上的直接循环加上相同数量的几何工作。我的赌注是减速五倍左右。


如果您的表面是凸面,则正面和背面由连续的轮廓线隔开。从可见面开始,您可以使用图表中的种子填充过程“填充”连续的面,直到到达该分隔线。这样,您无需遍历背面(或仅穿过与分隔线接触的背面)。

这实际上是您描述的方法。种子填充本质上是一个递归过程。您可以使用本地堆栈模拟递归,但这不会提供加速(只是避免堆栈溢出)。

没有办法避免递归,这是有充分理由的:当您从面对面填充域以保持连接性时,您很可能最终导致未填充区域断开连接。没有遍历顺序可以避免这种情况,这意味着在某些阶段必须独立填充几个区域,并且您需要对它们进行跟踪。这需要一些存储和回溯过程。

另请注意,在凸体上,正面的数量与背面的数量大致相同,跳过一半的好处在很大程度上被图遍历和填充的成本所补偿。

如果表面是凹的,你可能需要几个起始面(我怀疑你能不能有效地找到它们),因为可能有多个轮廓。


最后说明:在凸面的情况下,您可以通过从初始面开始,沿着与观察点相反的方向行进直到到达某个边界面并通过跟踪轮廓来找到分离轮廓分离边缘。访问的人脸数量将大致与行军到第一个轮廓人脸的过程中看到的人脸数量成正比,再加上轮廓长度。

对于 F 个面的网格,工作量的数量级为 O(√F)。但这仍然不能告诉你哪些是可见的面孔。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 1970-01-01
    • 2017-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多