Cannon.js — это физический движок для JavaScript, реализующий твердотельную динамику, включая столкновения, силы, инерцию и пружинные связи. Одной из ключевых задач любого физического движка является обнаружение столкновений, которое в Cannon.js разделено на два этапа: широкофазовое (broadphase) и узкофазовое (narrowphase) обнаружение. Такой подход позволяет повысить производительность и точность симуляции.
Широкофазовое обнаружение отвечает за отсев объектов, которые явно не могут столкнуться. Оно не вычисляет точные точки контакта, а лишь определяет пары тел, которые находятся достаточно близко для дальнейшего анализа.
Cannon.js поддерживает несколько алгоритмов широкофазового обнаружения:
NaiveBroadphase
SAPBroadphase (Sweep and Prune)
const world = new CANNON.World();
world.broadphase = new CANNON.SAPBroadphase(world);
world.broadphase.axisIndex = 0; // сортировка по X-оси
После определения потенциальных пар объектов широкофазовым этапом, Cannon.js выполняет узкофазовую проверку, которая вычисляет:
Cannon.js реализует несколько типов коллайдеров:
Сферы (Sphere)
Коробки (Box)
Капсулы, цилиндры, конусы и полигоны
Контакт представляет собой объект с параметрами:
bi, bj — столкнувшиеся тела.ni — нормаль столкновения, направленная от
bi к bj.ri, rj — точки на телах относительно
центра масс.penetration — глубина проникновения.world.addEventListener('postStep', () => {
world.contacts.forEach(contact => {
console.log(contact.bi.id, contact.bj.id, contact.penetration);
});
});
Для ускорения столкновений Cannon.js использует AABB (Axis-Aligned Bounding Box):
В современных версиях возможна интеграция BVH (Bounding Volume Hierarchy), что особенно полезно для сцен с большим количеством сложных мешей.
Cannon.js позволяет подписываться на события столкновений:
collide — при начале контакта двух тел.collideBegin и collideEnd — для детальной
обработки фаз столкновения.bodyA.addEventListener('collide', function(e) {
console.log('Столкновение с', e.body.id, 'на точке', e.contact.rj);
});
Это позволяет создавать реакции на столкновения: звук, эффект, изменение состояния объекта.
Для визуализации столкновений часто используют комбинацию Cannon.js и Three.js:
mesh.position.copy(body.position);
mesh.quaternion.copy(body.quaternion);
Такой подход позволяет использовать точные физические столкновения, сохраняя высокую производительность рендеринга.