你好。
在过去的一个月里,我一直在不断搜集各种信息,但没有找到适合解决我的问题的想法。以下是问题的表述:
给定一个以缓冲几何体(32位顶点坐标和顶点索引的数组+附加数组,如顶点法线、UV或切线)的形式呈现的网格,在围绕几何体的均匀网格点上计算带符号距离函数(signed distance function,SDF)。
更具体地说,我想在3D引擎(如Maxon的Cinema4D或Blender)中创建类似于MetaBall对象的东西。我已经为所有几何图元实现了距离函数,但对于任意网格SDF,我需要实现一种暴力方法 - 为每个网格点测试每个三角形的距离 - 这当然会对复杂的网格产生很大的开销。
现在,我想起了大多数这些问题都需要构建类似于Octree、KD-tree、BSP-tree或AABB-tree的树状结构。然后我找到了一些关于所谓的快速扫描算法(用于解决Eikonal方程)的文章,该算法要求首先将边界上的网格点(在我的情况下是网格或最靠近网格的点)填充为0,其余点填充大值(无穷大),然后迭代地解决非线性双曲边值问题(Gauss-Seidel)。我还在CGAL库中发现了一个开源实现网格SDF方法的方法。或者,我也考虑使用一些着色器库(如GLSL),并尝试使用GPU构建树形结构,但我从未在JS或TS项目中使用过着色器。
我遇到的难题不仅仅在于选择最佳选项,而且在于实际高效地使用至少其中一种方法。例如:
如果我想实现Fast-Marching Method,我必须遍历所有三角形,并为每个三角形遍历所有网格点Gijk。使用类似于Marching Cubes查找表的东西来处理网格单元格交叉点(但选项更多),我会对相交的单元格顶点插值接近0的值。我有一种感觉,这将花费很长时间,并且无法适用于实时更新。
我成功找到了Unity中Ray Marching SDF计算的一些示例。由于我从未尝试直接在GPU上进行计算,因此我不知道例如并行计算的限制实际上是什么,也不知道这样的计算是如何执行的。我能够并行计算至每个三角形的距离,然后快速排序每个网格点Gijk的所有距离吗?如果可以,我要如何将其包含到TypeScript项目中?
假设我在网格周围建立一个AABB-tree(应该是O(n * log(n))),然后给定一个网格点Gijk(假设根节点是包含Gijk和所有三角形的框),我将搜索最接近的叶子并计算所包含三角形的欧几里得距离(如果有多个,则选择其中一个)。 (请纠正我是否错误理解了)搜索应为O(log(n)),如果用户移动网格,则更新将需要O(n),其中n为三角形数量。因此,如果m是网格大小,则整个SDF计算将为O(m * n * log(n))?这看起来不像是对O(n * m)蛮力方法的改进,但也许我错了。
我考虑过结合多种方法,但这一切都似乎非常耗时。我还考虑过使用CGAL库或为我的项目重新设计它,但由于库内的所有依赖性,我发现很难理解C ++代码。您中是否有人做过类似的事情?您会推荐什么?
感谢您提供的所有见解。