Extract Vertex Data from Ammo.js Convex Hull

This article explains how to retrieve raw vertex coordinates from an internal btConvexHullShape in ammo.js (the Emscripten port of the Bullet physics engine). You will learn how to access the underlying shape representation, iterate through its points using WebAssembly-compatible methods, and safely manage the allocated memory in JavaScript.

To extract vertex data from an ammo.js convex hull shape, you must utilize the methods inherited from btPolyhedralConvexShape. Although btConvexHullShape stores the points internally in a compressed or optimized format, the WebAssembly interface exposes helper functions to retrieve them individually without needing to access raw heap memory directly.

The Extraction Process

The extraction relies on two key methods exposed by the btConvexHullShape object: 1. getNumVertices(): Returns the total number of vertices in the hull. 2. getVertex(index, vertexOut): Populates a passed btVector3 object with the coordinates of the vertex at the specified index.

Step-by-Step Code Implementation

Below is a clean JavaScript implementation demonstrating how to extract the vertices into a flat array of floats:

function getConvexHullVertices(convexHullShape) {
    const vertices = [];
    
    // 1. Get the total count of vertices in the hull
    const numVertices = convexHullShape.getNumVertices();
    
    // 2. Create a temporary btVector3 to store the output of each iteration
    const tempVertex = new Ammo.btVector3();
    
    try {
        // 3. Loop through and extract each vertex's coordinates
        for (let i = 0; i < numVertices; i++) {
            convexHullShape.getVertex(i, tempVertex);
            
            vertices.push(
                tempVertex.x(),
                tempVertex.y(),
                tempVertex.z()
            );
        }
    } finally {
        // 4. Always destroy temporary Ammo objects to prevent WebAssembly memory leaks
        Ammo.destroy(tempVertex);
    }
    
    return vertices;
}

Memory Management Considerations

Because ammo.js runs inside WebAssembly, any object created with the new keyword (like new Ammo.btVector3()) allocates memory on the Emscripten heap.

To prevent memory leaks: * Instantiated helper vectors must be freed explicitly using Ammo.destroy(vector). * Do not instantiate a new btVector3 inside the loop. Instead, allocate a single temporary btVector3 outside the loop, reuse it for each iteration, and destroy it once the loop completes.

Utilizing the Extracted Data

The resulting flat array [x1, y1, z1, x2, y2, z2, ...] can be easily wrapped into a standard JavaScript Float32Array. This format is ideal for: * Reconstructing visual geometry in rendering engines like Three.js using BufferAttribute. * Debugging physics collision boundaries by drawing wireframes. * Serializing collision shapes for storage or network transmission.