Менеджер физических объектов

Cannon.js — это высокопроизводительная библиотека для физического моделирования в браузере на JavaScript. Она позволяет создавать реалистичное взаимодействие объектов в 3D-пространстве, включая столкновения, гравитацию и динамику твердых тел. Центральным элементом управления является World и связанные с ним Body, Shape и Constraint.


World: пространство физической симуляции

World представляет собой контейнер для всех физических объектов. Он управляет гравитацией, интеграцией движения, коллизиями и временем симуляции. Основные свойства:

  • gravity — вектор гравитации (CANNON.Vec3). Например, стандартная сила тяжести:
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
  • broadphase — алгоритм предварительного определения возможных столкновений. Доступны варианты:

    • NaiveBroadphase — проверяет все пары объектов (подходит для малого количества тел).
    • SAPBroadphase — более оптимизирован для множества объектов.
  • solver — решатель физических ограничений, определяет точность симуляции.

world.solver.iterations = 10; // Увеличение итераций повышает точность, но снижает производительность

Метод world.step(dt) продвигает симуляцию на интервал dt секунд. Обычно вызывается в игровом цикле.


Body: физическое тело

Body — базовый класс для динамических объектов. Свойства:

  • mass — масса тела. 0 делает объект статическим.
  • position — текущая позиция (CANNON.Vec3).
  • velocity — текущая скорость.
  • angularVelocity — угловая скорость.
  • shape — геометрическая форма тела, определяющая коллизии.

Создание динамического тела:

const sphereShape = new CANNON.Sphere(1); // Радиус 1
const sphereBody = new CANNON.Body({
    mass: 5,
    position: new CANNON.Vec3(0, 10, 0),
    shape: sphereShape
});
world.addBody(sphereBody);

Взаимодействие тел

Body поддерживает методы для приложения силы и импульсов:

  • applyForce(forceVec, worldPoint) — сила в определенной точке.
  • applyImpulse(impulseVec, worldPoint) — мгновенный импульс.
  • applyLocalForce и applyLocalImpulse — те же действия, но в локальной системе координат объекта.

Shape: формы тел

Формы определяют границы коллизий. Основные классы:

  • CANNON.Box — параллелепипед, принимает halfExtents (CANNON.Vec3).
  • CANNON.Sphere — сфера, принимает radius.
  • CANNON.Cylinder — цилиндр, задается радиусами, высотой и числом сегментов.
  • CANNON.Plane — бесконечная плоскость.
  • CANNON.ConvexPolyhedron — произвольный выпуклый полиэдр, более сложный, но точный для нестандартных форм.

Пример создания коробки:

const boxShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1));
const boxBody = new CANNON.Body({ mass: 2 });
boxBody.addShape(boxShape);
boxBody.position.set(0, 5, 0);
world.addBody(boxBody);

Constraint: связи между телами

Cannon.js поддерживает ограничения для моделирования механических соединений:

  • CANNON.DistanceConstraint — фиксирует расстояние между двумя телами.
  • CANNON.HingeConstraint — шарнирное соединение с одной степенью свободы.
  • CANNON.LockConstraint — полностью фиксирует положение и ориентацию тел относительно друг друга.

Пример дистанционного ограничения:

const constraint = new CANNON.DistanceConstraint(bodyA, bodyB, 5);
world.addConstraint(constraint);

Коллизии и события

Cannon.js позволяет отслеживать столкновения через событие collide на объекте Body. Срабатывает при столкновении с другим телом:

sphereBody.addEventListener('collide', function(event) {
    const contactBody = event.body;
    console.log('Столкновение с', contactBody);
});

Оптимизация симуляции

  • Использование mass = 0 для статических объектов уменьшает вычислительные затраты.
  • Предварительное определение столкновений с помощью broadphase.
  • Контроль итераций решателя (solver.iterations) и времени шага (world.step) помогает балансировать точность и производительность.
  • Объединение нескольких мелких тел в CompoundShape снижает нагрузку на коллизии.

Интеграция с визуализацией

Cannon.js не содержит встроенного рендеринга. Обычно синхронизация происходит с библиотеками вроде Three.js:

mesh.position.copy(body.position);
mesh.quaternion.copy(body.quaternion);

Это обеспечивает визуальное соответствие физики и графики, позволяя создавать реалистичные сцены.


Управление временем и шагами

Фиксированный шаг симуляции гарантирует стабильность, даже если частота кадров изменяется:

const fixedTimeStep = 1.0 / 60.0; // 60 Гц
const maxSubSteps = 3;

function update(dt) {
    world.step(fixedTimeStep, dt, maxSubSteps);
}
  • dt — фактический прошедший интервал времени.
  • maxSubSteps — максимальное количество шагов для компенсации разницы между симуляцией и рендером.

Важные рекомендации

  • Всегда использовать векторы Cannon.js (CANNON.Vec3) для позиций, сил и скоростей. Неправильные типы могут привести к ошибкам.
  • Для сложных сцен сочетать статические и динамические тела, чтобы снизить нагрузку на движок.
  • Следить за балансом точности и производительности через шаг интеграции и параметры решателя.

Эти принципы позволяют создавать сложные физические симуляции с реалистичной динамикой и управлением объектами, полностью раскрывая возможности Cannon.js в браузере.