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