Neikos
Neikos

Reputation: 1980

How to optimally use a run length morton-encoded chunk of voxels to generate a mesh?

I am currently toying around with meshing voxel chunks, that is a N^3 list of voxel values. Since in my use-case most of the voxels are going to be of the same type a lot of the neighbors will share the same value. Thus, using RLE (run length encoding) makes sense to use, as it drastically cuts down the actual storage requirement at the cost of a O(log(n)) (n being the amount of runs in a chunk) random lookup. At the same time, I encode each voxel position as a z-order curve, specifically using morton encoding. This all works in my use-case and gives the expected space reductions required.

The issue is with meshing the individual chunks. Generating meshes takes up to 500ms (for N=48) which is simply too long for fluid gameplay. My current algorithm heavily borrows from the one described here and here.

Pseudocode algorithm:

- 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

The mesh generation itself is very fast (<<< 1ms) and wouldn't gain much from being optimized, but building the mask itself is very costly. As one can see in the tracing output below, each mesh_mask_building takes on average ~4ms which happens 3*N times per mesh!

My first thought to optimize this, was to use the inherent runs of the chunk and simply traverse those and build a mask of each, but this did not work out, as morton encoding is winding a lot throughout the primitive and as such would not be much better at constructing a mesh. It would also be highly suboptimal when one considers a chunk where only one layer is set to visible voxels. The current method generates a simple cuboid as it does not care about runs, but in my suggested method, each run would be seperate and generate more faces.

Tracing timings

So my question is, how can I use a morton-run-length encoding to generate a mesh?

Upvotes: 1

Views: 456

Answers (0)

Related Questions