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:
getNumVertices(): Returns the total number of vertices in the hull.getVertex(index, vertexOut): Populates a passedbtVector3object 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
btVector3inside the loop. Instead, allocate a single temporarybtVector3outside 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.