【发布时间】: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