Soft Body Cluster Collision in Ammo.js

This article explains soft body cluster collision in the ammo.js physics engine, detailing what it is, why it is used for performance optimization, and the exact steps required to enable it in your JavaScript-based 3D applications.

Understanding Soft Body Cluster Collision

In physics simulation, a soft body is a deformable object—such as gelatin, cloth, or rubber—whose shape changes upon impact. Simulating these objects realistically requires representing them as a network of vertices (nodes) and links. By default, calculating collisions for every individual vertex against other physical objects is computationally expensive and can severely degrade performance.

Cluster collision solves this performance bottleneck. Instead of checking every node, the physics engine groups the soft body’s vertices into localized “clusters.” The engine then calculates collisions between these clusters and other rigid or soft bodies. This approximation dramatically reduces the number of collision checks, allowing for real-time simulation of complex deformable objects while still maintaining a highly realistic appearance.

How to Enable Cluster Collision in Ammo.js

To use cluster collision in ammo.js (the Emscripten port of the Bullet Physics engine), you must configure both the soft body’s structure and its collision configuration flags.

Step 1: Initialize the Soft Body World

Ensure you are using btSoftRigidDynamicsWorld as your physics world, as standard rigid-only dynamics worlds do not support soft bodies.

const collisionConfiguration = new Ammo.btSoftBodyRigidBodyCollisionConfiguration();
const dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
const broadphase = new Ammo.btDbvtBroadphase();
const solver = new Ammo.btSequentialImpulseConstraintSolver();
const softBodySolver = new Ammo.btDefaultSoftBodySolver();

const physicsWorld = new Ammo.btSoftRigidDynamicsWorld(
    dispatcher, 
    broadphase, 
    solver, 
    collisionConfiguration, 
    softBodySolver
);

Step 2: Create the Soft Body and Generate Clusters

When creating your soft body (for example, from a mesh helper), you must explicitly tell Ammo.js to generate the collision clusters. This is done using the generateClusters method, passing the number of clusters you want to create.

// Assuming 'softBody' has been created via Ammo.btSoftBodyHelpers
const numClusters = 64; // Adjust based on complexity and performance needs
softBody.generateClusters(numClusters);

Step 3: Configure Collision Flags

Once the clusters are generated, you must update the soft body’s configuration (m_cfg) to instruct the engine to use cluster-based collision detection instead of vertex-based detection.

You can enable cluster-to-rigid-body collisions, cluster-to-soft-body collisions, or both by using bitwise operations on the collision flags:

const sbConfig = softBody.get_m_cfg();

// Clear default collisions and enable cluster-based collisions
sbConfig.set_collisions(0x0000); 

// Enable Cluster vs. Rigid Body collisions (CL_RS)
sbConfig.set_collisions(sbConfig.get_collisions() | 0x0001); 

// Enable Cluster vs. Soft Body collisions (CL_SS)
sbConfig.set_collisions(sbConfig.get_collisions() | 0x0002);

Step 4: Set Solver Iterations

Because cluster collisions rely on joint-like constraints between clusters, you may need to increase the cluster solver iterations to prevent objects from clipping or passing through one another.

// Increase cluster solver iterations for stability (default is usually 1)
sbConfig.set_citerations(4); 

Once these configurations are applied, add the soft body to your physics world using physicsWorld.addSoftBody(softBody). The engine will now handle all physical interactions using the optimized cluster collision method.