Three.js AABB Collision Detection with Box3
This article explains how to implement Axis-Aligned Bounding Box
(AABB) collision detection in Three.js using the built-in
Box3 class. You will learn how to create bounding boxes for
3D meshes, update them dynamically as objects move, and check for
intersections to detect collisions in your 3D scenes.
Understanding Box3 and AABB
An Axis-Aligned Bounding Box (AABB) is a rectangular prism wrapped
around a 3D object, aligned perfectly with the X, Y, and Z axes of the
world space. In Three.js, the Box3 class represents this
bounding box. Because these boxes do not rotate with the object,
calculating their intersection is computationally cheap, making AABB
ideal for real-time collision detection in games and interactive 3D
applications.
Step 1: Create Bounding Boxes for Your Meshes
To perform collision detection, you first need to create a
Box3 instance for each 3D object you want to track. You can
generate a bounding box that perfectly fits a mesh using the
setFromObject method.
import * as THREE from 'three';
// Create meshes
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const mesh1 = new THREE.Mesh(geometry, material);
const mesh2 = new THREE.Mesh(geometry, material);
// Create Box3 instances
const box1 = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
const box2 = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
// Calculate initial bounding boxes
box1.setFromObject(mesh1);
box2.setFromObject(mesh2);Step 2: Update Bounding Boxes in the Animation Loop
If your meshes move, scale, or rotate, their world coordinates change. Therefore, you must recalculate the bounding boxes inside your animation loop before checking for collisions.
function animate() {
requestAnimationFrame(animate);
// Move mesh1 along the X-axis
mesh1.position.x += 0.01;
// Recalculate bounding boxes to match new positions
box1.setFromObject(mesh1);
box2.setFromObject(mesh2);
// Check for collisions
checkCollisions();
renderer.render(scene, camera);
}Step 3: Check for Collisions
To determine if two bounding boxes are colliding, use the
intersectsBox method of the Box3 class. This
method returns true if the two boxes overlap in 3D
space.
function checkCollisions() {
if (box1.intersectsBox(box2)) {
console.log("Collision detected!");
// Handle collision logic here (e.g., stop movement or change color)
mesh1.material.color.setHex(0xff0000);
} else {
mesh1.material.color.setHex(0x00ff00);
}
}Performance Optimization for Complex Geometries
Calling setFromObject every frame can be computationally
expensive for complex geometries because it traverses all vertices of
the mesh. If your objects only translate (move) and do not rotate or
scale, you can optimize performance by copying the pre-computed geometry
bounding box and applying the mesh’s world matrix:
// Define the bounding box once at start
mesh1.geometry.computeBoundingBox();
const localBox = mesh1.geometry.boundingBox;
// Inside the animation loop, apply the world matrix
const dynamicBox = localBox.clone().applyMatrix4(mesh1.matrixWorld);This approach bypasses the need to traverse geometry vertices in every frame, significantly improving performance for high-poly models.