Non-Uniform Scaling for Ammo.js Collision Shapes

This article explains how to apply non-uniform local scaling to collision shapes in ammo.js, the JavaScript port of the Bullet physics engine. You will learn how to use the built-in scaling methods, update the physics world to reflect these changes, and understand how different shape types handle non-uniform scaling.

In ammo.js, you can apply a non-uniform local scale to a collision shape using the setLocalScaling method. This method is available on all classes that inherit from btCollisionShape. It accepts a btVector3 parameter representing the scaling factors along the X, Y, and Z axes.

Code Implementation

To scale a collision shape, instantiate a btVector3 with your desired X, Y, and Z scale factors, pass it to the shape’s setLocalScaling method, and then free the vector from memory to prevent leaks.

// 1. Create or reference your collision shape (e.g., a box shape)
const boxShape = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));

// 2. Define the non-uniform scale (e.g., stretch X, squash Y, keep Z)
const scale = new Ammo.btVector3(2.5, 0.5, 1.0);

// 3. Apply the scale to the shape
boxShape.setLocalScaling(scale);

// 4. Clean up the allocated vector memory
Ammo.destroy(scale);

Updating the Physics World

If you apply a scale to a collision shape that is already attached to an active rigid body in your physics world, the broadphase collision detection will not automatically register the new size. You must force the physics world to recalculate the Axis-Aligned Bounding Box (AABB) for that specific rigid body.

// Update the bounding box in the dynamics world
dynamicsWorld.updateSingleAabb(rigidBody);

If you do not call this update, the physical collisions will still occur at the shape’s original dimensions until the body undergoes a major state change.

Shape Compatibility and Limitations

While ammo.js supports non-uniform scaling, different collision shapes handle it differently: