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

> Discover mesh simplification options in meshoptimizer including meshopt_SimplifyLockBorder. Control border preservation, error metrics, and triangle regularity for efficient mesh reduction.

- Repository: [Arseny Kapoulkine/meshoptimizer](https://github.com/zeux/meshoptimizer)
- Tags: deep-dive
- Published: 2026-07-11

---

**meshoptimizer provides bit-mask flags such as `meshopt_SimplifyLockBorder`, `meshopt_SimplifySparse`, and `meshopt_SimplifyRegularize` in [`src/meshoptimizer.h`](https://github.com/zeux/meshoptimizer/blob/main/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/main/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`](https://github.com/zeux/meshoptimizer/blob/main/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](https://github.com/zeux/meshoptimizer/blob/master/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](https://github.com/zeux/meshoptimizer/blob/master/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](https://github.com/zeux/meshoptimizer/blob/master/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](https://github.com/zeux/meshoptimizer/blob/master/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](https://github.com/zeux/meshoptimizer/blob/master/src/meshoptimizer.h#L473) and [src/meshoptimizer.h#L475](https://github.com/zeux/meshoptimizer/blob/master/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](https://github.com/zeux/meshoptimizer/blob/master/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`](https://github.com/zeux/meshoptimizer/blob/main/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](https://github.com/zeux/meshoptimizer/blob/master/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](https://github.com/zeux/meshoptimizer/blob/master/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](https://github.com/zeux/meshoptimizer/blob/master/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`](https://github.com/zeux/meshoptimizer/blob/main/src/meshoptimizer.h) is:

```c
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:

```c
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:

```c
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:

```c
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`](https://github.com/zeux/meshoptimizer/blob/main/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`](https://github.com/zeux/meshoptimizer/blob/main/src/simplifier.cpp), with practical usage examples in [`demo/clusterlod.h`](https://github.com/zeux/meshoptimizer/blob/main/demo/clusterlod.h) and the interactive [`demo/simplify.html`](https://github.com/zeux/meshoptimizer/blob/main/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`.