meshly v0.6.0
Meshly
A TypeScript library for decoding Python meshoptimizer zip files into THREE.js geometries.
Installation
npm install meshly
Usage
Basic Usage
import * as THREE from 'three';
import { MeshUtils } from 'meshly';
// Load a mesh from a zip file
async function loadMesh(zipData: ArrayBuffer) {
const geometry = await MeshUtils.loadZipAsBufferGeometry(zipData, {
normalize: true,
computeNormals: true
});
// Create a THREE.js mesh
const material = new THREE.MeshStandardMaterial({ color: 0x2194ce });
const mesh = new THREE.Mesh(geometry, material);
return mesh;
}
// Example: Load a mesh from a URL
async function loadMeshFromURL(url: string) {
const response = await fetch(url);
const zipData = await response.arrayBuffer();
return loadMesh(zipData);
}
Advanced Usage
You can also use the lower-level functions to extract and decode the mesh data:
import { MeshUtils } from 'meshly';
async function loadMeshManually(zipData: ArrayBuffer) {
// Extract the mesh data from the zip file
const decodedMesh = await MeshUtils.loadMeshFromZip(zipData);
// Convert the decoded mesh to a THREE.js geometry
const geometry = MeshUtils.convertToBufferGeometry(decodedMesh, {
normalize: true,
computeNormals: true
});
return geometry;
}
Encoding and Decoding Meshes
You can use the encode
and decode
functions to encode and decode meshes directly:
import { MeshUtils, Mesh, EncodedMesh } from 'meshly';
// Create a mesh with vertices, indices, and additional arrays
const mesh: Mesh = {
vertices: new Float32Array([
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5
]),
indices: new Uint32Array([0, 1, 2, 2, 3, 0]),
normals: new Float32Array([
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1
])
};
// Encode the mesh
const encodedMesh: EncodedMesh = MeshUtils.encode(mesh);
console.log(`Encoded vertices size: ${encodedMesh.vertices.byteLength} bytes`);
console.log(`Encoded indices size: ${encodedMesh.indices?.byteLength} bytes`);
console.log(`Additional arrays: ${Object.keys(encodedMesh.arrays || {})}`);
// Decode the mesh
const decodedMesh = MeshUtils.decode(null, encodedMesh);
console.log(`Decoded vertices: ${decodedMesh.vertices.length} elements`);
console.log(`Decoded indices: ${decodedMesh.indices?.length} elements`);
console.log(`Decoded normals: ${decodedMesh.normals?.length} elements`);
Array Utilities
The library also provides utilities for working with arrays:
import { ArrayUtils } from 'meshly';
// Encode a Float32Array
const array = new Float32Array([1.0, 2.0, 3.0, 4.0, 5.0]);
const encoded = ArrayUtils.encodeArray(array);
console.log(`Original size: ${array.byteLength} bytes`);
console.log(`Encoded size: ${encoded.data.byteLength} bytes`);
// Decode an array
const decoded = ArrayUtils.decodeArray(encoded.data, {
shape: encoded.shape,
dtype: encoded.dtype,
itemsize: encoded.itemsize
});
console.log(`Decoded array length: ${decoded.length}`);
API Reference
MeshUtils
MeshUtils.loadZipAsBufferGeometry(zipData: ArrayBuffer, options?: DecodeMeshOptions): Promise<THREE.BufferGeometry>
Loads a mesh from a zip file and converts it to a THREE.js BufferGeometry.
Parameters
zipData
: The zip file data as an ArrayBufferoptions
: Options for decoding the meshnormalize
: Whether to normalize the mesh to fit within a unit cube (default:false
)computeNormals
: Whether to compute normals if they don't exist (default:true
)
Returns
A Promise that resolves to a THREE.js BufferGeometry.
MeshUtils.loadMeshFromZip(zipData: ArrayBuffer): Promise<Mesh>
Extracts and decodes a mesh from a zip file.
Parameters
zipData
: The zip file data as an ArrayBuffer
Returns
A Promise that resolves to a Mesh object.
MeshUtils.convertToBufferGeometry(mesh: Mesh, options?: DecodeMeshOptions): THREE.BufferGeometry
Converts a decoded mesh to a THREE.js BufferGeometry.
Parameters
mesh
: The decoded mesh dataoptions
: Options for the conversionnormalize
: Whether to normalize the mesh to fit within a unit cube (default:false
)computeNormals
: Whether to compute normals if they don't exist (default:true
)
Returns
A THREE.js BufferGeometry.
MeshUtils.decodeVertexBuffer(vertexCount: number, vertexSize: number, data: Uint8Array): Float32Array
Decodes a vertex buffer using the meshoptimizer algorithm.
Parameters
vertexCount
: Number of verticesvertexSize
: Size of each vertex in bytesdata
: Encoded vertex buffer
Returns
Decoded vertex buffer as a Float32Array.
MeshUtils.encode(mesh: Mesh): EncodedMesh
Encodes a mesh for efficient transmission. This function encodes the mesh's vertices, indices, and any additional arrays.
Parameters
mesh
: The mesh to encode
Returns
An EncodedMesh object containing the encoded vertices, indices, and arrays.
MeshUtils.decode(MeshClass: any, encodedMesh: EncodedMesh): Mesh
Decodes an encoded mesh. This function decodes the mesh's vertices, indices, and any additional arrays.
Parameters
MeshClass
: The mesh class constructor (not used in TypeScript version, included for API compatibility with Python)encodedMesh
: The EncodedMesh object to decode
Returns
A decoded Mesh object.
MeshUtils.decodeIndexSequence(indexCount: number, indexSize: number, data: Uint8Array): Uint32Array
Decodes an index sequence using the meshoptimizer algorithm.
Parameters
indexCount
: Number of indicesindexSize
: Size of each index in bytesdata
: Encoded index sequence
Returns
Decoded index sequence as a Uint32Array.
ArrayUtils
ArrayUtils.encodeArray(data: Float32Array): EncodedArray
Encodes a Float32Array using the meshoptimizer algorithm.
Parameters
data
: Float32Array to encode
Returns
EncodedArray object containing the encoded data and metadata.
ArrayUtils.decodeArray(data: Uint8Array, metadata: ArrayMetadata): Float32Array
Decodes an encoded array using the meshoptimizer algorithm.
Parameters
data
: Encoded array datametadata
: Array metadata
Returns
Decoded array as a Float32Array.
Python Mesh Format
This library is designed to work with the Python meshoptimizer library's zip format. The zip file should contain:
mesh/vertices.bin
: Encoded vertex buffermesh/indices.bin
: Encoded index bufferarrays/
: Additional arrays (normals, colors, etc.)metadata.json
: General metadata about the mesh, including mesh size information
The metadata.json file contains:
class_name
: Name of the mesh classmodule_name
: Name of the module containing the mesh classfield_data
: Dictionary of model fields that aren't numpy arraysmesh_size
: Size metadata for the encoded mesh (vertex_count, vertex_size, index_count, index_size)
Setup
# Clone the repository
git clone https://github.com/OpenOrion/meshly.git
cd meshly
# Install dependencies
pnpm install
Build
The project uses TypeScript and builds to the dist
directory:
pnpm run build
Test
pnpm test
CI/CD
This project uses GitHub Actions for continuous integration and deployment:
- CI: On every push and pull request, the code is built and tested.
- Testing: A dedicated test workflow runs tests on multiple Node.js versions (16.x, 18.x, 20.x) to ensure compatibility across different environments.
- CD: When a new release is created on GitHub, the package is automatically published to npm.
The GitHub Actions workflows are located in the root .github/workflows
directory:
npm-publish.yml
: Handles building, testing, and publishing the packagenpm-test.yml
: Runs tests across multiple Node.js versions
To publish a new version:
- Update the version in
package.json
- Create a new release on GitHub
- GitHub Actions will automatically build and publish the package to npm
License
MIT