Python wrapper for meshoptimizer library
Project description
Meshoptimizer Python
Python bindings for the meshoptimizer library, which provides algorithms for optimizing 3D meshes for GPU rendering.
Installation
pip install meshoptimizer
Or install from source:
git clone https://github.com/zeux/meshoptimizer.git
cd meshoptimizer/python
pip install -e .
Features
- Vertex cache optimization
- Overdraw optimization
- Vertex fetch optimization
- Mesh simplification
- Vertex/index buffer compression and decompression
- Zip file storage for encoded meshes
- Numpy array compression and storage
- And more...
Usage
Low-level API
The meshoptimizer Python bindings provide a low-level API that directly maps to the C++ functions. All functions accept numpy arrays and have optional parameters that are automatically derived when not provided.
import numpy as np
from meshoptimizer import (
optimize_vertex_cache,
optimize_overdraw,
optimize_vertex_fetch,
simplify,
encode_vertex_buffer,
decode_vertex_buffer,
encode_index_buffer,
decode_index_buffer
)
# Create a simple mesh (a cube)
vertices = np.array([
# positions
[-0.5, -0.5, -0.5],
[0.5, -0.5, -0.5],
[0.5, 0.5, -0.5],
[-0.5, 0.5, -0.5],
[-0.5, -0.5, 0.5],
[0.5, -0.5, 0.5],
[0.5, 0.5, 0.5],
[-0.5, 0.5, 0.5]
], dtype=np.float32)
indices = np.array([
0, 1, 2, 2, 3, 0, # front
1, 5, 6, 6, 2, 1, # right
5, 4, 7, 7, 6, 5, # back
4, 0, 3, 3, 7, 4, # left
3, 2, 6, 6, 7, 3, # top
4, 5, 1, 1, 0, 4 # bottom
], dtype=np.uint32)
# Optimize vertex cache
optimized_indices = np.zeros_like(indices)
optimize_vertex_cache(optimized_indices, indices) # vertex_count is automatically derived
# Optimize overdraw
optimized_indices2 = np.zeros_like(indices)
optimize_overdraw(
optimized_indices2,
optimized_indices,
vertices
) # index_count, vertex_count, and vertex_positions_stride are automatically derived
# Optimize vertex fetch
optimized_vertices = np.zeros_like(vertices)
unique_vertex_count = optimize_vertex_fetch(
optimized_vertices,
optimized_indices2,
vertices
) # index_count, vertex_count, and vertex_size are automatically derived
print(f"Optimized mesh has {unique_vertex_count} unique vertices")
# Simplify the mesh
simplified_indices = np.zeros(len(indices), dtype=np.uint32)
target_index_count = len(indices) // 2 # Keep 50% of triangles
simplified_index_count = simplify(
simplified_indices,
optimized_indices2,
vertices,
target_index_count=target_index_count
) # index_count, vertex_count, and vertex_positions_stride are automatically derived
print(f"Simplified mesh has {simplified_index_count} indices")
# Encode the mesh for efficient transmission
encoded_vertices = encode_vertex_buffer(optimized_vertices[:unique_vertex_count])
encoded_indices = encode_index_buffer(simplified_indices[:simplified_index_count])
print(f"Encoded vertex buffer size: {len(encoded_vertices)} bytes")
print(f"Encoded index buffer size: {len(encoded_indices)} bytes")
# Decode the mesh
decoded_vertices = decode_vertex_buffer(
unique_vertex_count,
vertices.itemsize * vertices.shape[1],
encoded_vertices
)
decoded_indices = decode_index_buffer(
simplified_index_count,
4, # 4 bytes per index (uint32)
encoded_indices
)
# Verify the decoded data
print(f"Decoded vertices shape: {decoded_vertices.shape}")
print(f"Decoded indices shape: {decoded_indices.shape}")
Notes on Index Encoding/Decoding
When using the index buffer encoding and decoding functions, note that the decoded indices may not exactly match the original indices, even though the mesh geometry remains the same. This is due to how the meshoptimizer library internally encodes and decodes the indices. The triangles may be in a different order, but the resulting mesh is still valid and represents the same geometry.
API Reference
Vertex Remapping
generate_vertex_remap(destination, indices=None, index_count=None, vertices=None, vertex_count=None, vertex_size=None): Generate vertex remap table.remap_vertex_buffer(destination, vertices, vertex_count=None, vertex_size=None, remap=None): Remap vertex buffer.remap_index_buffer(destination, indices, index_count=None, remap=None): Remap index buffer.
Optimization
optimize_vertex_cache(destination, indices, index_count=None, vertex_count=None): Optimize vertex cache.optimize_vertex_cache_strip(destination, indices, index_count=None, vertex_count=None): Optimize vertex cache for strip-like caches.optimize_vertex_cache_fifo(destination, indices, index_count=None, vertex_count=None, cache_size=16): Optimize vertex cache for FIFO caches.optimize_overdraw(destination, indices, vertex_positions, index_count=None, vertex_count=None, vertex_positions_stride=None, threshold=1.05): Optimize overdraw.optimize_vertex_fetch(destination_vertices, indices, source_vertices, index_count=None, vertex_count=None, vertex_size=None): Optimize vertex fetch.optimize_vertex_fetch_remap(destination, indices, index_count=None, vertex_count=None): Generate vertex remap to optimize vertex fetch.
Simplification
simplify(destination, indices, vertex_positions, index_count=None, vertex_count=None, vertex_positions_stride=None, target_index_count=None, target_error=0.01, options=0, result_error=None): Simplify mesh.simplify_with_attributes(destination, indices, vertex_positions, vertex_attributes, attribute_weights, index_count=None, vertex_count=None, vertex_positions_stride=None, vertex_attributes_stride=None, attribute_count=None, vertex_lock=None, target_index_count=None, target_error=0.01, options=0, result_error=None): Simplify mesh with attribute metric.simplify_sloppy(destination, indices, vertex_positions, index_count=None, vertex_count=None, vertex_positions_stride=None, target_index_count=None, target_error=0.01, result_error=None): Simplify mesh (sloppy).simplify_points(destination, vertex_positions, vertex_colors=None, vertex_count=None, vertex_positions_stride=None, vertex_colors_stride=None, color_weight=1.0, target_vertex_count=None): Simplify point cloud.simplify_scale(vertex_positions, vertex_count=None, vertex_positions_stride=None): Get the scale factor for simplification error.
Encoding/Decoding
encode_vertex_buffer(vertices, vertex_count=None, vertex_size=None): Encode vertex buffer.encode_index_buffer(indices, index_count=None, vertex_count=None): Encode index buffer.encode_vertex_version(version): Set vertex encoder format version.encode_index_version(version): Set index encoder format version.decode_vertex_buffer(vertex_count, vertex_size, buffer): Decode vertex buffer.decode_index_buffer(index_count, index_size, buffer): Decode index buffer.decode_vertex_version(buffer): Get encoded vertex format version.decode_index_version(buffer): Get encoded index format version.decode_filter_oct(buffer, count, stride): Apply octahedral filter to decoded data.decode_filter_quat(buffer, count, stride): Apply quaternion filter to decoded data.decode_filter_exp(buffer, count, stride): Apply exponential filter to decoded data.
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file meshoptimizer-0.2.30a0.tar.gz.
File metadata
- Download URL: meshoptimizer-0.2.30a0.tar.gz
- Upload date:
- Size: 98.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36b18b61a95ba992de804b1e91e86be2ba185925e4e2c1481495f8c68a17f5db
|
|
| MD5 |
a321ab09adc47558fddb9f557e0714a7
|
|
| BLAKE2b-256 |
35b923259780df3097b6b70e7091970a689b677bd320b02a63fdf60493902167
|