我正在尝试实现一个子例程,以查找从点可见的3D凸网格的所有三角形,而无需遍历所有三角形 但只有使用三角形与其邻居的连通性,网格物体始终具有第一个可见的三角形。 img exm.
我只能想到递归方法,例如
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)
但是递归方法很慢,并且此例程应该比在所有三角形上迭代都要快。
有什么想法或方法可以解决这个问题而无需递归吗?
谢谢。
答案 0 :(得分:1)
这似乎是一个非常错误的想法。
因为
无论如何,您都必须访问所有三角形(至少所有可见的三角形,请参见下文);
的连通性是不够的;无论如何,都需要进行几何测试以考虑视点的位置。
无论您做什么,复杂度必须在 visible 个面孔的数量上呈线性,而在 total 个面孔的数量上也呈线性,您将交易一个复杂的图形遍历时在面上的直接循环加上相同数量的几何功。我的赌注是速度降低了五倍左右。
如果表面是凸形的,则前表面和后表面由连续的轮廓线分隔。从可见的面孔开始,您可以使用图中的 seed fill 过程“填充”连续的面孔,直到到达分隔线。这样,您就无需遍历背面(或仅与分隔线接触的背面)。
这实际上就是您所描述的方法。种子填充本质上是一个递归过程。您可以使用本地堆栈模拟递归,但不会提供任何提速(仅避免堆栈溢出)。
有一个没有办法避免递归,这有一个很好的理由:当您在面对面填充区域并保持连接状态时,您可以很好地结束未填充区域的连接。没有遍历顺序可以避免这种情况,这意味着在某些阶段必须独立填充多个区域,并且您需要对其进行跟踪。这需要一些存储和回溯过程。
还请注意,在凸体上,前表面的数量与后表面的数量差不多,而跳过其中一半的好处在很大程度上由图形遍历和填充的成本所补偿。
如果表面是凹面,则可能需要多个起始面(我怀疑您可以有效地找到它们),因为可能有多个轮廓。
最后一句话:在凸面的情况下,您可以从初始面开始,沿与视点相反的方向行进,直到到达某些边界面,然后通过跟踪轮廓线来找到轮廓,从而找到分离的轮廓。分开边缘。要访问的面孔数量将与行进到第一个轮廓面孔期间看到的面孔数量大致成正比,再加上轮廓长度。
对于F个面的网格,工作量将为O(√F)。但这仍然无法告诉您哪些是可见的面孔。