The Difference Between meshopt_generateVertexRemap and meshopt_generatePositionRemap in meshoptimizer
Both functions generate index remapping tables, but meshopt_generateVertexRemap compares the entire vertex payload for complete deduplication while meshopt_generatePositionRemap compares only the 12-byte position attribute, making them suitable for distinct optimization pipelines.
When optimizing geometry in the zeux/meshoptimizer library, developers must choose between two remap generators that appear similar but serve different purposes. Understanding the difference between meshopt_generateVertexRemap and meshopt_generatePositionRemap is critical for correctly deduplicating vertices during mesh preprocessing. These functions operate at different granularities—one treats vertices as identical only when every byte matches, while the other ignores all attributes except spatial coordinates.
Scope of Comparison: Full Vertex Data vs. Position Only
Full-Vertex Deduplication with meshopt_generateVertexRemap
The meshopt_generateVertexRemap function performs complete vertex deduplication by comparing every byte of the vertex structure. As defined in src/meshoptimizer.h (lines 53-63), it treats vertices as equal only if the entire vertex_size payload—including padding—is bit-identical. This ensures that all attributes such as normals, UVs, and colors remain synchronized when remapping indices.
Position-Only Deduplication with meshopt_generatePositionRemap
In contrast, meshopt_generatePositionRemap performs position-only deduplication by examining only the first 12 bytes of each vertex (the float3 position). According to the source code in src/meshoptimizer.h (lines 155-156), this function ignores normals, tangents, and other attributes, making it ideal for generating index buffers where only spatial connectivity matters.
Input Signatures and Return Values
The functions differ significantly in their signatures and return semantics. meshopt_generateVertexRemap accepts a raw vertex buffer pointer and returns the count of unique vertices:
size_t meshopt_generateVertexRemap(
unsigned int* destination,
const unsigned int* indices,
size_t index_count,
const void* vertices,
size_t vertex_count,
size_t vertex_size);
This return value allows you to allocate a compact vertex buffer sized exactly for the unique entries.
Conversely, meshopt_generatePositionRemap takes a dedicated position array and returns void:
void meshopt_generatePositionRemap(
unsigned int* destination,
const float* vertex_positions,
size_t vertex_count,
size_t vertex_positions_stride);
Because it returns no count, you must determine the number of unique positions separately if needed, or simply use the remap table directly for re-indexing operations where only positional continuity is required.
Practical Implementation and Code Examples
Compacting a Mesh with meshopt_generateVertexRemap
Use this function when preparing a mesh for meshopt_remapVertexBuffer to eliminate duplicate vertices across all attributes. In src/meshoptimizer.cpp, the implementation hashes the full vertex blob to find duplicates.
// Example: Deduplicating an interleaved vertex buffer
size_t vertexCount = 1024;
size_t vertexSize = 20; // 8-byte position + 12-byte normal
unsigned int* remap = (unsigned int*)malloc(vertexCount * sizeof(unsigned int));
size_t uniqueCount = meshopt_generateVertexRemap(
remap,
NULL, // no indices (unindexed mesh)
0,
vertices,
vertexCount,
vertexSize);
// uniqueCount can now size the compact buffer
Building Position-Only Index Buffers with meshopt_generatePositionRemap
This function excels in shadow-map generation or hierarchical LOD construction, as seen in demo/clusterlod.h. When vertex attributes differ but positions coincide—such as split normals on hard edges—this function merges them into a single logical vertex for positional passes.
// Example: Generating a remap for position-only rendering
size_t vertexCount = 1024;
size_t stride = 20; // distance between position starts
unsigned int* posRemap = (unsigned int*)malloc(vertexCount * sizeof(unsigned int));
meshopt_generatePositionRemap(
posRemap,
positions, // pointer to first float3
vertexCount,
stride);
// posRemap now maps original indices to position-unique indices
Summary
meshopt_generateVertexRemapcompares the entirevertex_sizebytes to find truly identical vertices, returns the unique vertex count, and is defined insrc/meshoptimizer.hlines 53-63.meshopt_generatePositionRemapcompares only the 12-byte position attribute, returnsvoid, and is optimized for position-only passes like shadow mapping.- Choose the full-vertex variant when all attributes must remain coherent; choose the position-only variant when only spatial connectivity matters.
- Both functions write to a destination remap array that can be consumed by
meshopt_remapIndexBufferor similar utilities.
Frequently Asked Questions
Can I use meshopt_generatePositionRemap to reduce vertex buffer size?
No. Because meshopt_generatePositionRemap returns void and does not account for other attributes, it cannot safely resize a full vertex buffer containing normals or UVs. Use meshopt_generateVertexRemap for buffer compaction, as it returns the exact count of unique vertices needed for allocation.
Why does meshopt_generateVertexRemap require the vertex buffer to be contiguous?
The function signature in src/meshoptimizer.h takes const void* vertices and size_t vertex_size, implying a tightly packed array. The implementation hashes vertex_size bytes at each offset, so non-contiguous data or complex striding requires manual packing before calling the function.
When should I prefer position-only remapping over full-vertex remapping?
Prefer meshopt_generatePositionRemap when building connectivity for shadow volumes, depth pre-passes, or hierarchical simplification where attribute splits (like hard-edge normals) should be ignored. The demo/clusterlod.h file demonstrates this for level-of-detail generation.
Do these functions modify the input index buffer?
No. Both functions treat the input arrays as read-only. They write only to the destination remap array, leaving your original geometry data intact.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →