Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

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

Metadata

Release files for meshoptimizer 0.2.30a0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for meshoptimizer 0.2.30a0
File Size Uploaded Provenance
meshoptimizer-0.2.30a0.tar.gz 98.8 kB Without provenance Details

Release files / meshoptimizer-0.2.30a0.tar.gz

Download URL meshoptimizer-0.2.30a0.tar.gz
Size 98.8 kB
Tags Source
SHA-256 checksum
How to use checksums
36b18b61a95ba992de804b1e91e86be2ba185925e4e2c1481495f8c68a17f5db
BLAKE2b-256 checksum
How to use checksums
35b923259780df3097b6b70e7091970a689b677bd320b02a63fdf60493902167
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Security for meshoptimizer 0.2.30a0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page