Mesh Simplification Options in meshoptimizer: Complete Guide to Flags Like meshopt_SimplifyLockBorder

meshoptimizer provides bit-mask flags such as meshopt_SimplifyLockBorder, meshopt_SimplifySparse, and meshopt_SimplifyRegularize in src/meshoptimizer.h to control border preservation, error metrics, and triangle regularity during mesh reduction.

The meshoptimizer library exposes fine-grained mesh simplification options through bitwise flags that modify the behavior of the decimation algorithm. These flags, defined in the public header [src/meshoptimizer.h](https://github.com/zeux/meshoptimizer/blob/master/src/meshoptimizer.h), allow you to preserve topological boundaries, adjust error calculations, and control vertex locking when generating level-of-detail (LOD) meshes. Understanding these options is essential for producing optimized geometry that maintains visual fidelity in critical areas.

Core Simplification Flags

The primary simplification options are defined as unsigned integer constants starting at line 469 in src/meshoptimizer.h. Pass these to meshopt_simplify or meshopt_simplifyWithAttributes by combining them with the bitwise OR operator (|).

Preserve Border Geometry with meshopt_SimplifyLockBorder

meshopt_SimplifyLockBorder prevents vertices on the topological border—edges belonging to only one triangle—from being moved or removed during simplification. This is essential when simplifying chunks of a larger mesh that must connect seamlessly at the boundaries. According to the source code, this flag is declared at src/meshoptimizer.h#L469.

Optimize for Sparse Indices with meshopt_SimplifySparse

meshopt_SimplifySparse adjusts the error metric to be relative to the extents of the sparse subset rather than the full mesh bounds. Use this flag when processing meshes with sparse index buffers to improve simplification accuracy and performance. See the definition at src/meshoptimizer.h#L470.

Control Error Thresholds with meshopt_SimplifyErrorAbsolute

By default, meshoptimizer interprets the target_error value relative to mesh extents. meshopt_SimplifyErrorAbsolute switches the error limit to absolute units, giving you precise control over deformation magnitude regardless of mesh size. This flag is located at src/meshoptimizer.h#L471.

Remove Disconnected Geometry with meshopt_SimplifyPrune

meshopt_SimplifyPrune enables the incremental removal of disconnected components during simplification, even when such removal violates local topological constraints. This helps clean up stray geometry that might otherwise persist through decimation. Find this at src/meshoptimizer.h#L472.

Improve Triangle Quality with Regularization

meshopt_SimplifyRegularize encourages the generation of uniform triangle shapes and sizes, trading slight geometric or attribute quality for rasterization efficiency. For a lighter touch, meshopt_SimplifyRegularizeLight applies similar regularization with reduced impact on overall mesh quality. These are defined at src/meshoptimizer.h#L473 and src/meshoptimizer.h#L475 respectively.

Handle Attribute Discontinuities with meshopt_SimplifyPermissive

meshopt_SimplifyPermissive is an experimental flag that permits edge collapses across attribute discontinuities, provided the vertices are not marked with meshopt_SimplifyVertex_Protect. This enables more aggressive simplification when you can tolerate attribute seams, such as UV boundaries or hard normals. The flag appears at src/meshoptimizer.h#L474.

Vertex-Level Control Flags

When supplying a vertex_lock array to meshopt_simplifyWithAttributes, you can mark individual vertices with specialized flags defined in src/meshoptimizer.h at lines 490-492.

Lock Specific Vertices with meshopt_SimplifyVertex_Lock

meshopt_SimplifyVertex_Lock guarantees that specific vertices remain completely stationary throughout the simplification process, preventing any collapses involving those positions. This is defined at src/meshoptimizer.h#L490.

Protect Attribute Seams with meshopt_SimplifyVertex_Protect

meshopt_SimplifyVertex_Protect marks vertices where attribute discontinuities must be preserved, preventing collapses across these boundaries when combined with meshopt_SimplifyPermissive. See src/meshoptimizer.h#L491.

Prioritize Vertex Preservation

meshopt_SimplifyVertex_Priority increases the preservation priority of specific vertices during simplification, making the algorithm less likely to remove them even when they are technically collapsible. This is declared at src/meshoptimizer.h#L492.

Implementing Simplification Options in Code

The simplification API accepts an options bitmask parameter. Combine flags using the bitwise OR operator (|).

The function signature from src/meshoptimizer.h is:

size_t meshopt_simplify(
    unsigned int* destination,
    const unsigned int* indices,
    size_t index_count,
    const float* vertex_positions,
    size_t vertex_count,
    size_t vertex_positions_stride,
    size_t target_index_count,
    float target_error,
    unsigned int options,
    float* result_error);

To preserve borders and regularize triangles:

unsigned int opts = meshopt_SimplifyLockBorder | meshopt_SimplifyRegularize;
float result_error;

size_t new_index_count = meshopt_simplify(
    dst_indices, src_indices, index_count,
    positions, vertex_count, sizeof(float) * 3,
    target_index_count, 0.01f, opts, &result_error);

When using meshopt_simplifyWithAttributes with vertex locks to protect UV seams:

unsigned char* vertex_lock = (unsigned char*)malloc(vertex_count);
memset(vertex_lock, 0, vertex_count);

// Mark seam vertices for protection
for (size_t i = 0; i < seam_vertex_count; ++i) {
    vertex_lock[seam_indices[i]] = meshopt_SimplifyVertex_Protect;
}

unsigned int opts = meshopt_SimplifyPermissive;
float result_error;

size_t new_count = meshopt_simplifyWithAttributes(
    dst_indices, src_indices, index_count,
    positions, vertex_count, sizeof(float) * 3,
    attributes, attribute_stride, attribute_weights, attribute_count,
    vertex_lock, target_count, 0.02f, opts, &result_error);

For aggressive simplification on sparse meshes with absolute error control:

unsigned int opts = meshopt_SimplifySparse | meshopt_SimplifyErrorAbsolute;

size_t new_count = meshopt_simplify(
    dst_indices, src_indices, index_count,
    positions, vertex_count, sizeof(float) * 3,
    target_count, 0.005f, opts, NULL);

Summary

  • meshoptimizer exposes mesh simplification options as bit-mask flags in src/meshoptimizer.h, including meshopt_SimplifyLockBorder for border preservation and meshopt_SimplifyRegularize for triangle quality optimization.
  • The options parameter in meshopt_simplify accepts combined flags using bitwise OR to control error metrics, topology pruning, and attribute handling.
  • Vertex-level flags like meshopt_SimplifyVertex_Lock and meshopt_SimplifyVertex_Protect provide fine-grained control when used with meshopt_simplifyWithAttributes.
  • Implementation details are found in src/simplifier.cpp, with practical usage examples in demo/clusterlod.h and the interactive demo/simplify.html.

Frequently Asked Questions

What is the difference between meshopt_SimplifyRegularize and meshopt_SimplifyRegularizeLight?

meshopt_SimplifyRegularize aggressively enforces uniform triangle shapes, potentially sacrificing some geometric fidelity for better rasterization performance. meshopt_SimplifyRegularizeLight applies similar regularization but with a reduced impact on quality, offering a middle ground between geometric accuracy and mesh regularity.

Can I combine meshopt_SimplifyLockBorder with other simplification options?

Yes, you can combine meshopt_SimplifyLockBorder with any other flags using the bitwise OR operator. For example, meshopt_SimplifyLockBorder | meshopt_SimplifySparse | meshopt_SimplifyRegularize preserves borders while optimizing for sparse indices and improving triangle regularity.

When should I use meshopt_SimplifyErrorAbsolute instead of relative error?

Use meshopt_SimplifyErrorAbsolute when you need to specify error thresholds in absolute world units rather than as a percentage of mesh extents. This is particularly important when processing multiple meshes of vastly different scales where a relative error value would produce inconsistent visual quality.

How do vertex lock flags interact with the meshopt_SimplifyLockBorder option?

meshopt_SimplifyLockBorder operates automatically on topological border vertices detected by the algorithm, while meshopt_SimplifyVertex_Lock and related flags in the vertex_lock array allow you to manually constrain specific vertices regardless of their topological position. These systems work independently; border locks apply globally based on mesh topology, whereas vertex locks target specific indices you mark in the array passed to meshopt_simplifyWithAttributes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →