Filter Convex Sweep Tests by Layer in Ammo.js
This article explains how to restrict a convex sweep test in Ammo.js
to specific collision layers. You will learn how to configure bitwise
collision groups and masks, apply them to a
ClosestConvexResultCallback, and execute the filtered sweep
test to ignore unwanted physics bodies.
Step 1: Define Collision Groups
Bullet Physics (and by extension Ammo.js) uses bitwise flags to handle collision filtering. Define your collision layers as powers of two:
const COLLISION_GROUP_DEFAULT = 1; // 0001
const COLLISION_GROUP_PLAYER = 2; // 0010
const COLLISION_GROUP_ENEMY = 4; // 0100
const COLLISION_GROUP_WALL = 8; // 1000When adding rigid bodies to your dynamics world, assign them a group and a mask defining what they can collide with:
// Add a wall that only collides with the player and default objects
dynamicsWorld.addRigidBody(
wallBody,
COLLISION_GROUP_WALL,
COLLISION_GROUP_PLAYER | COLLISION_GROUP_DEFAULT
);Step 2: Configure the Convex Sweep Callback
To filter the sweep test, instantiate a
ClosestConvexResultCallback. This object exposes properties
to set the collision group of the test itself and the mask of layers it
is allowed to hit.
// Define start and end vectors for the sweep
const fromVec = new Ammo.btVector3(0, 5, 0);
const toVec = new Ammo.btVector3(10, 5, 0);
// Create the callback
const callback = new Ammo.ClosestConvexResultCallback(fromVec, toVec);
// Set the sweep test's identity and target layers
// Example: The sweep acts as a "Player" and should only hit "Wall" objects
callback.set_m_collisionFilterGroup(COLLISION_GROUP_PLAYER);
callback.set_m_collisionFilterMask(COLLISION_GROUP_WALL);Step 3: Execute the Sweep Test
Pass your collision shape, start and end transforms, and the
configured callback to the convexSweepTest method of your
dynamics world.
const startTransform = new Ammo.btTransform();
startTransform.setIdentity();
startTransform.setOrigin(fromVec);
const endTransform = new Ammo.btTransform();
endTransform.setIdentity();
endTransform.setOrigin(toVec);
// Perform the sweep test
dynamicsWorld.convexSweepTest(
convexShape, // e.g., Ammo.btBoxShape or Ammo.btCapsuleShape
startTransform,
endTransform,
callback,
0 // Allowed CCD penetration (usually 0)
);
// Process the results
if (callback.hasHit()) {
const hitBody = Ammo.castObject(callback.get_m_hitCollisionObject(), Ammo.btCollisionObject);
const hitPoint = callback.get_m_hitPointWorld();
const hitNormal = callback.get_m_hitNormalWorld();
console.log("Sweep hit a filtered target at:", hitPoint.x(), hitPoint.y(), hitPoint.z());
} else {
console.log("No filtered targets detected in sweep path.");
}Step 4: Clean Up Memory
To avoid memory leaks in the WebAssembly runtime, always destroy the created Ammo objects when they are no longer needed:
Ammo.destroy(fromVec);
Ammo.destroy(toVec);
Ammo.destroy(startTransform);
Ammo.destroy(endTransform);
Ammo.destroy(callback);