我目前正在玩弄网格化体素块,这是一个N^3的体素值列表。由于在我的用例中,大多数体素将属于同一类型,因此许多邻居将共享相同的值。因此,使用 RLE(运行长度编码)是有意义的,因为它以随机查找(即块中的运行数量)为O(log(n))
代价大幅降低了实际存储需求。n
同时,我将每个体素位置编码为 z 阶曲线,具体使用 morton 编码。这一切都适用于我的用例,并提供了所需的预期空间减少。
问题在于对各个块进行网格划分。生成网格最多需要 500 毫秒(N=48),这对于流畅的游戏玩法来说太长了。我当前的算法大量借鉴了这里和这里描述的算法。
伪代码算法:
- For each axis in [X, Y, Z]
- for each k in 0..N in axis
- Create a mask of size [N * N]
- for each u in 0..N of orthogonal axis:
- for each v in 0..N of second orthogonal axis:
- Check if (k, u, v) has a face between itself and (k+1, u, v)
- If yes, set mask[u*v*N] = true
- using the mask, make a greedy mesh and output that
网格生成本身非常快(<<< 1ms)并且不会从优化中获得太多收益,但是构建遮罩本身的成本非常高。正如在下面的跟踪输出中可以看到的,每个mesh_mask_building
平均需要约 4 毫秒,每个网格发生 3*N 次!
我的第一个想法是优化这个,是使用块的固有运行并简单地遍历它们并为每个块构建一个掩码,但这没有成功,因为 morton 编码在整个原语中缠绕了很多,因此不会更擅长构建网格。当考虑一个只有一层设置为可见体素的块时,它也将是非常次优的。当前方法生成一个简单的长方体,因为它不关心运行,但在我建议的方法中,每次运行将是单独的并生成更多面。
所以我的问题是,如何使用 morton-run-length 编码来生成网格?