Create an Infinite Floor in ammo.js with btStaticPlaneShape
This article explains how to create an infinite static floor in a 3D
physics simulation using Ammo.js (the Emscripten port of the Bullet
physics engine) and btStaticPlaneShape. You will learn how
to define the plane’s normal vector, configure its offset, instantiate
the rigid body with zero mass, and add it to your physics world.
To create an infinite floor, Ammo.js provides the
btStaticPlaneShape class. Unlike box or grid shapes, a
static plane shape is mathematically infinite and highly optimized for
collision detection. It is defined by a normal vector (which points in
the direction the plane is facing) and a plane constant (the
distance/offset from the origin along that normal vector).
Step-by-Step Implementation
1. Define the Plane Shape
First, create the plane normal vector and instantiate the shape. For
a flat horizontal floor, the normal vector should point straight up
along the Y-axis (0, 1, 0).
// Define the normal vector pointing straight up
const planeNormal = new Ammo.btVector3(0, 1, 0);
// Define the plane offset (0 means it passes through the origin)
const planeConstant = 0;
// Create the infinite plane shape
const groundShape = new Ammo.btStaticPlaneShape(planeNormal, planeConstant);2. Configure the Transform
Even though the plane is mathematically infinite, Bullet still requires a transform to position the rigid body in the world. For a standard floor passing through the origin, use an identity transform.
const groundTransform = new Ammo.btTransform();
groundTransform.setIdentity();
// Set the origin position if needed (usually 0, 0, 0)
groundTransform.setOrigin(new Ammo.btVector3(0, 0, 0)); 3. Create the Rigid Body
Static objects in Ammo.js must have a mass of 0. Setting
the mass to zero tells the physics engine that this object cannot be
moved by collisions or gravity.
const mass = 0;
const localInertia = new Ammo.btVector3(0, 0, 0);
// Motion state helps synchronize the physics body with your graphics engine
const motionState = new Ammo.btDefaultMotionState(groundTransform);
// Construction information for the rigid body
const rbInfo = new Ammo.btRigidBodyConstructionInfo(
mass,
motionState,
groundShape,
localInertia
);
// Instantiate the rigid body
const groundBody = new Ammo.btRigidBody(rbInfo);4. Add the Body to the Physics World
Finally, add the newly created rigid body to your active Ammo.js dynamics world.
physicsWorld.addRigidBody(groundBody);Key Considerations
Memory Management: Ammo.js is a C++ wrapper. To prevent memory leaks, clean up your vectors and temporary objects using
Ammo.destroy()if you recreate or destroy the floor during runtime:Ammo.destroy(planeNormal); Ammo.destroy(localInertia);No Double Transformations: Because the
planeConstantalready offsets the plane along the normal vector, it is best practice to keep the rigid body’s transform origin at(0, 0, 0)to avoid unexpected offsets.