Ammo.js Collision Margin and Stacked Bodies

This article explains how the collision margin in ammo.js (the JavaScript port of the Bullet physics engine) impacts the stability, alignment, and resting contact of stacked rigid bodies. You will learn how the collision margin creates a virtual boundary around shapes, how it prevents interpenetration, and how to configure it to avoid visual gaps or physical jitter in your 3D physics simulations.

What is Collision Margin in Ammo.js?

In ammo.js, the collision margin is a small, protective buffer zone added around collision shapes. Instead of calculating collisions exactly at the polygon surface, the physics engine uses this margin to detect and resolve contacts before the core geometries actually intersect. By default, Bullet/ammo.js sets this margin to 0.04 units.

For some shapes, like spheres and capsules, the margin is “internal” (subtracted from the total size), meaning the physical dimensions match the graphical representation. For other shapes, like boxes and convex hulls, the margin is “external” (added to the exterior), expanding the physical collision boundary slightly beyond the original geometry dimensions.

Effect on Resting Contact and Visual Gaps

When rigid bodies are stacked, they rely on resting contact to remain stable. The collision margin directly dictates where this resting contact occurs:

Impact on Stack Stability and Jitter

Stacking multiple bodies increases the cumulative mass and force acting on the bottom-most contacts. The collision margin plays a vital role in maintaining stack stability:

How to Optimize Margins for Stacking

To achieve stable stacks without unsightly visual gaps, you can apply the following techniques:

  1. Shrink the Graphical Mesh: If you must use a standard collision margin for stability, shrink your visual 3D mesh slightly so that it matches the inner boundary of the collision shape, masking the visual gap.
  2. Adjust the Margin Judiciously: For small-scale objects, the default 0.04 margin might be too large. You can lower the margin using shape.setMargin(0.01), but avoid setting it to absolute zero.
  3. Use Implicit Margin Shapes: Whenever possible, use spheres, capsules, or cylinders for stacked components. Because their margins are embedded internally, they transition into resting contact seamlessly without creating external visual gaps.