Export Ammo.js Collision Shapes to JSON
This article explains how to export Ammo.js collision shapes to a standard JSON format. While Ammo.js does not feature a native, single-method JSON exporter, developers can successfully serialize collision shapes by querying shape properties programmatically and structuring them into custom JSON objects. Below, we explore the limitations of Ammo.js’s built-in serialization and provide a step-by-step guide on how to manually extract and format this data.
The Limitation of Native Ammo.js Serialization
Ammo.js is a WebAssembly/JavaScript port of the C++ Bullet Physics
library. Bullet possesses a native serialization system
(btDefaultSerializer) that exports physics worlds into a
proprietary binary format (usually saved with a .bullet
extension). However, this binary output is not human-readable, nor is it
natively compatible with standard web workflows that rely heavily on
JSON.
To get a clean, standard JSON representation of a collision shape (such as a box, sphere, cylinder, or triangle mesh), you must write a helper function that inspects the Ammo.js shape, extracts its geometric dimensions, and formats it.
How to Manually Export Shapes to JSON
To export Ammo.js shapes, you must identify the shape type using its
broadphase entity type ID, retrieve its specific properties (like
radius, half-extents, or vertex arrays), and map them to a JavaScript
object which can then be converted to JSON using
JSON.stringify().
Step 1: Identify the Shape Type
Ammo.js shapes inherit from btCollisionShape. You can
determine the type of shape by calling the getShapeType()
method. This returns an integer representing the shape’s type (e.g.,
BOX_SHAPE_PROXYTYPE or
SPHERE_SHAPE_PROXYTYPE).
Step 2: Extract Specific Dimensions
Once the shape type is identified, cast or treat the shape object according to its specific subclass to retrieve its dimensions:
- Box Shape (
btBoxShape): Retrieve the half-extents. - Sphere Shape (
btSphereShape): Retrieve the radius. - Cylinder Shape (
btCylinderShape): Retrieve the half-extents and orientation axis. - Capsule Shape (
btCapsuleShape): Retrieve the radius and the height of the cylindrical part.
Step 3: Map to a JSON Structure
Create a helper function to compile these properties into a structured JavaScript object. Here is a practical example of how this serialization logic looks in JavaScript:
function serializeCollisionShape(shape) {
const shapeType = shape.getShapeType();
const exportData = {
type: null,
params: {}
};
// Ammo.js shape type constants (represent numerical IDs in Bullet)
const BOX_SHAPE_PROXYTYPE = 0;
const SPHERE_SHAPE_PROXYTYPE = 8;
const CAPSULE_SHAPE_PROXYTYPE = 10;
if (shapeType === BOX_SHAPE_PROXYTYPE) {
exportData.type = "Box";
const halfExtents = shape.getHalfExtentsWithMargin();
exportData.params.halfExtents = {
x: halfExtents.x(),
y: halfExtents.y(),
z: halfExtents.z()
};
} else if (shapeType === SPHERE_SHAPE_PROXYTYPE) {
exportData.type = "Sphere";
exportData.params.radius = shape.getRadius();
} else if (shapeType === CAPSULE_SHAPE_PROXYTYPE) {
exportData.type = "Capsule";
exportData.params.radius = shape.getRadius();
exportData.params.height = shape.getHalfHeight() * 2;
} else {
exportData.type = "Unsupported/Complex";
exportData.params.shapeTypeId = shapeType;
}
return JSON.stringify(exportData, null, 2);
}Handling Complex Mesh Shapes
For complex geometries like btBvhTriangleMeshShape or
btConvexHullShape, exporting becomes more
resource-intensive.
To export these shapes to JSON, you must access the underlying vertex
and index buffers. For a convex hull, you can iterate through the points
using the shape’s internal points array and store them as a flat array
of coordinate triplets [x, y, z] in your JSON payload. Keep
in mind that serializing large meshes into JSON can result in very large
file sizes, so it is recommended to keep mesh resolutions as low as
possible for physics collisions.