Cannon.js — это физический движок для JavaScript, предназначенный для симуляции твердого тела, столкновений и динамики объектов в 3D-пространстве. Одним из ключевых инструментов при отладке физических сцен является визуализация AABB (Axis-Aligned Bounding Box) и самих форм. AABB представляет собой прямоугольный параллелепипед, выровненный по осям координат, который полностью охватывает объект. Он используется для ускорения вычислений столкновений и для диагностики неправильного поведения физических тел.
В Cannon.js каждый объект физического мира представлен экземпляром класса Body, а его форма — экземпляром класса Shape. Для визуализации можно использовать как готовые библиотеки, например, three.js, так и кастомное создание геометрий.
Каждое тело в Cannon.js имеет метод updateAABB(), который вычисляет актуальные границы тела. После этого можно получить свойства aabb.lowerBound и aabb.upperBound, которые задают минимальные и максимальные координаты параллелепипеда.
body.updateAABB();
const lower = body.aabb.lowerBound;
const upper = body.aabb.upperBound;
Эти координаты можно использовать для построения каркаса AABB с помощью линий:
const geometry = new THREE.BoxGeometry(
upper.x - lower.x,
upper.y - lower.y,
upper.z - lower.z
);
const edges = new THREE.EdgesGeometry(geometry);
const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
const wireframe = new THREE.LineSegments(edges, material);
wireframe.position.set(
(upper.x + lower.x) / 2,
(upper.y + lower.y) / 2,
(upper.z + lower.z) / 2
);
scene.add(wireframe);
Ключевой момент: для динамических тел нужно обновлять позицию AABB каждый кадр после симуляции физики, иначе визуализация будет отставать от реального положения тела.
Cannon.js предоставляет различные типы форм: Box, Sphere, Cylinder, ConvexPolyhedron, Trimesh. Для ручной визуализации формы можно использовать аналогичную геометрию в three.js, синхронизируя позицию и ориентацию тела.
const boxShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1));
const boxBody = new CANNON.Body({ mass: 1 });
boxBody.addShape(boxShape);
const boxGeometry = new THREE.BoxGeometry(2, 2, 2);
const boxMaterial = new THREE.MeshNormalMaterial();
const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
scene.add(boxMesh);
// В анимационном цикле
function upd ate() {
world.step(1/60);
boxMesh.position.copy(boxBody.position);
boxMesh.quaternion.copy(boxBody.quaternion);
requestAnimationFrame(upd ate);
}
update();
const sphereShape = new CANNON.Sphere(1);
const sphereBody = new CANNON.Body({ mass: 1 });
sphereBody.addShape(sphereShape);
const sphereGeometry = new THREE.SphereGeometry(1, 16, 16);
const sphereMaterial = new THREE.MeshNormalMaterial();
const sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphereMesh);
// В анимационном цикле
sphereMesh.position.copy(sphereBody.position);
sphereMesh.quaternion.copy(sphereBody.quaternion);
Для сложных форм типа ConvexPolyhedron или Trimesh требуется конструировать геометрию вручную, перебирая вершины и индексы:
const vertices = convexShape.vertices.map(v => new THREE.Vector3(v.x, v.y, v.z));
const geometry = new THREE.BufferGeometry().setFromPoints(vertices);
// Для Trimesh необходимо использовать индексные массивы треугольников
geometry.setIndex(triangleIndices);
Визуализация AABB полезна для выявления проблем с коллизиями, таких как:
Для каждого тела можно создавать отдельный каркас AABB и обновлять его каждый кадр:
body.updateAABB();
wireframe.position.se t(
(body.aabb.lowerBound.x + body.aabb.upperBound.x)/2,
(body.aabb.lowerBound.y + body.aabb.upperBound.y)/2,
(body.aabb.lowerBound.z + body.aabb.upperBound.z)/2
);
wireframe.scale.se t(
body.aabb.upperBound.x - body.aabb.lowerBound.x,
body.aabb.upperBound.y - body.aabb.lowerBound.y,
body.aabb.upperBound.z - body.aabb.lowerBound.z
);
Такой подход позволяет наблюдать реальное положение и ориентацию тел, а также отследить возможные ошибки синхронизации с визуальными объектами.
Эта методика визуализации позволяет не только отлаживать физические симуляции, но и создавать наглядные инструменты для интерактивного обучения и демонстрации работы физического движка Cannon.js.