zeux / meshoptimizer

Mesh optimization library that makes meshes smaller and faster to render
MIT License
5.49k stars 473 forks source link

How to avoid seams in terrain chunk meshes? #311

Closed Zylann closed 2 years ago

Zylann commented 3 years ago

I'm experimenting with Transvoxel terrain, where chunks are each independent meshes that line up seamlessly. But like a previous attempt at using a simplification library, meshes tend to no longer connect seamlessly, no matter which error threshold I set:

image

This is with meshopt_simplify, with target indices count set to 0 and error set to 0.01.

Is there a way to tell MeshOptimizer to avoid collapsing vertices on borders? (or collapse them deterministically the same way but that sounds tricky to do)

zeux commented 3 years ago

This is currently not supported out of the box, but planned as a future option. It can be easily accomplished e.g. by running this loop after classifyVertices call:

for (size_t i = 0; i < vertex_count; ++i)
    if (vertex_kind[i] == Kind_Border)
        vertex_kind[i] = Kind_Locked;
Zylann commented 3 years ago

I also figured this seems to work with no runtime cost:

const unsigned char kCanCollapse[Kind_Count][Kind_Count] = {
    // <Zylann> TEST
    // Original
    // {1, 1, 1, 1, 1},
    // {0, 1, 0, 0, 0},
    // Borders never collapse
    {1, 0, 1, 1, 1},
    {0, 0, 0, 0, 0},
    // </Zylann>
    {0, 0, 1, 0, 0},
    {0, 0, 0, 1, 1},
    {0, 0, 0, 0, 0},
};

This covers all my uses at the moment but I can see it's not clean as-is ;)

Zylann commented 2 years ago

Came back to this issue with a problem rising in Godot Engine 4: Now my module and the engine both ship with MeshOptimizer. My version has this different implementation for border collapsing, which cannot be used by Godot. And I cannot use (or modify) Godot's version because it does not do this. The problem is, Godot modules link statically, and this fails because Godot's version of MeshOptimizer conflicts with the altered one my module needs to use.

One workaround I could think of was to wrap the whole library into a custom namespace or rename the existing one, however it seems like it's not as trivial as it sounds, because the library also has functions outside of the meshopt namespace and a C API, which would also require to change the prefixes everywhere. Would this be the only way to go though?

zeux commented 2 years ago

All individual source files are self contained by design. So I would take just simplifier.cpp, rename the simplify functions and inside the file rename meshopt namespace; shouldn’t be too many changes. Hopefully once this is implemented and Godot’s version gets updated this won’t be necessary.

fire commented 2 years ago

@zeux @Zylann Do you want to create another simplifier with your algorithm and pull request it to meshoptimizer? I can then use it as a option in the importer.