This release focuses on improvements to clusterization, simplification and partitioning algorithms, as well as stabilization - with the exception of permissive simplification mode, all other library functionality introduced in prior releases is now considered stable.
Highlights:
Clusterization algorithms (meshopt_buildMeshlets/meshopt_buildMeshletsFlex, meshopt_buildMeshletsSpatial) are now faster and, in the case of spatial clusterization, produce higher-quality clusters for vertex-bound meshlets. Additionally, meshlet builders no longer align local index data to 4 bytes, which simplifies memory management and removes alignment restrictions on triangle limits. When cluster partitioning is required, meshopt_partitionClusters now produces better partitioning for disconnected clusters which improves quality of DAGs for hierarchical clusterization.
Speaking of hierarchical clusterization, a new single-header library clusterlod.h is now developed and maintained alongside meshoptimizer. This library implements continuous level of detail by generating a hierarchy of clusters that are progressively grouped and simplified, similarly to Nanite. It leverages meshoptimizer algorithms for internal processing, and can either be used as-is or as a starting point for implementing a custom solution - the code is structured to be easy to understand and modify. Some relevant improvements are described in Billions of triangles in minutes blog post.
New simplification features added in the last release have seen further quality improvements as well; both meshopt_simplifyWithUpdate and the meshopt_SimplifyPermissive option now generate higher-quality outputs. Permissive mode option specifically is still considered experimental, and future releases may improve or change behavior further.
All other experimental library functions and options have been promoted to stable status. This means that future releases will be API compatible (code will continue compiling), ABI compatible (code can link to a shared library build of meshoptimizer which can then be updated independently) and behavior compatible (results may improve in future releases, but these improvements should not require adjustments to the calling code) as far as current 1.0 functionality is concerned.
The vertex encoding functions (meshopt_encodeVertexBuffer/meshopt_encodeVertexBufferLevel) now encode v1 data by default. This can be overridden for applications that need to produce data in v0 format, especially if producing data for EXT_meshopt_compression extension which only supports v0. This version only switches the encoding default; support for encoding and decoding v0/v1 will be provided in perpetuity.
gltfpack now supports the new KHR_meshopt_compression extension via -cz option (or -ce khr which allows specifying compression level independently; -cz is equivalent to -ce khr -cc), which provides better compression compared to the existing EXT_meshopt_compression extension. Note that loader support for this extension is not yet widely available, and by default gltfpack continues to use EXT_meshopt_compression when compression is requested.
Finally, JavaScript bindings have been updated to use ES modules instead of CommonJS modules, which may require adjustments to import paths. For the MeshoptDecoder module, a CommonJS variant meshopt_decoder.cjs is still provided for compatibility (but note a different file extension, required for correct handling by some bundlers).
The majority of the work on the core library in this release has been sponsored by Valve; thank you!
Upgrade notes
meshopt_encodeVertexBuffernow uses format version 1 by default, which requires meshoptimizer v0.23 or later to decode. Applications that encode data forEXT_meshopt_compressionglTF extensions need to switch to version 0 by usingmeshopt_encodeVertexVersionormeshopt_encodeVertexBufferLevelfunctions.- Meshlet builders (
meshopt_buildMeshletsand other variants) no longer align local index data for each meshlet by 4 bytes; applications that usewritePackedPrimitiveIndices4x8NVintrinsic (fromNV_mesh_shaderextension) may need to align each meshlet manually.
Library improvements
- Switch to vertex encoding version 1 by default;
meshopt_encodeVertexVersion/meshopt_encodeVertexBufferLevelcan be used to encode data using version 0 if needed - Remove 4b alignment padding and triangle alignment requirements for
meshopt_buildMeshlets*functions meshopt_buildMeshletsFlex,meshopt_buildMeshletsSpatial,meshopt_decodeFilterColor,meshopt_encodeFilterColorandmeshopt_generatePositionRemapfunctions are now stablemeshopt_simplifyWithUpdateandmeshopt_simplifySloppyfunctions, as well asmeshopt_SimplifyRegularizeflag, are now stablemeshopt_partitionClustersnow returns slightly tighter partitions (now containing up topartition_size + partition_size / 3clusters)meshopt_partitionClustersnow merges spatially adjacent partitions if vertex positions are provided, even if the input clusters do not share vertices- Remove support for negative
cone_weightfrommeshopt_buildMeshletsFlex(this was an experimental feature, superseded bymeshopt_buildMeshletsSpatial) - Significantly improve performance of
meshopt_buildMeshlets*functions for sparse mesh subsets - Improve quality of simplified meshes when using
meshopt_simplifyWithUpdate(reduced position deformation, attributes are now updated on more vertices, attribute continuity is preserved in permissive mode) - Improve quality of simplified meshes when using
meshopt_SimplifyPermissivefor attribute discontinuities without protection bits - Improve performance of
meshopt_simplify*functions when usingmeshopt_SimplifySparseflag on very sparse mesh subsets - Improve clusterization quality for
meshopt_buildMeshletsSpatialon meshes with vertex-bound meshlets - Improve performance of
meshopt_buildMeshletsSpatialby 10-25% on x64 and AArch64 - Improve performance of
meshopt_buildMeshletsby 20-30% on meshes with many attribute discontinuities - Improve performance of
meshopt_decodeFilter*function family by 15-45% on AArch64 - Improve performance of
meshopt_decodeFilterQuatby 10-20% on x64 - Fix a rare (and benign) division by zero in
meshopt_simplifySloppy - Guarantee bounded recursion depth for all recursive functions (
meshopt_buildMeshletsFlex,meshopt_buildMeshletsSpatial,meshopt_partitionClusters)
gltfpack improvements
- Implement support for draft
KHR_meshopt_compressionextension (via-ce khror-czcommand line options) - Preserve per-instance colors (
_COLOR_0) when using mesh instancing - Fix duplicate texture encoding with Basis/WebP (when
-tcand-twcommand line options are used together) - Improve precision of texture coordinate encoding when using
-vtfon meshes with UV mapping issues - Warn when texture coordinate quantization error is significant and
-vtfis not specified - Validate output file extension before processing to prevent unnecessary work
JavaScript improvements
- Replace CommonJS modules with ES modules; this may require adjustments to import paths. For decoder,
meshopt_decoder.cjsis still provided for compatibility (note a different extension). - Switch to vertex encoding version 1 in
MeshoptEncoder.encodeVertexBufferby default; for compatibility withEXT_meshopt_compressionextension,MeshoptEncoder.encodeGltfBuffercontinues to default to v0 - Add
MeshoptSimplifier.generatePositionRemapfunction - Add
MeshoptClusterizer.buildMeshletsFlexandMeshoptClusterizer.buildMeshletsSpatialfunctions - Add optional
versionargument toMeshoptEncoder.encodeGltfBufferto support encoding v1 data
Thanks to @minitoine, @OfficialKris and @ynnob for contributions to this release!