npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

meshly

v1.0.6

Published

TypeScript library to decode Python meshoptimizer zip files into THREE.js geometries

Readme

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 ArrayBuffer
  • options: Options for decoding the mesh
    • normalize: 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 data
  • options: Options for the conversion
    • normalize: 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 vertices
  • vertexSize: Size of each vertex in bytes
  • data: 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.

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 data
  • metadata: 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 buffer
  • mesh/indices.bin: Encoded index buffer
  • arrays/: 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 class
  • module_name: Name of the module containing the mesh class
  • field_data: Dictionary of model fields that aren't numpy arrays
  • mesh_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 package
  • npm-test.yml: Runs tests across multiple Node.js versions

To publish a new version:

  1. Update the version in package.json
  2. Create a new release on GitHub
  3. GitHub Actions will automatically build and publish the package to npm

License

MIT