Составные тела: несколько форм на одном Body

В Cannon.js объект Body представляет физическое тело в симуляции. Обычно Body связывается с одной формой (Shape), например, Box, Sphere или Cylinder. Однако для моделирования сложных объектов часто требуется объединение нескольких форм в один Body. Это реализуется с помощью составных тел, когда один Body содержит несколько форм с индивидуальными смещениями и ориентациями относительно центра масс.


Добавление нескольких форм к одному телу

Каждую форму можно прикрепить к Body через метод addShape(shape, offset, orientation).

Синтаксис:

body.addShape(shape, offsetVector, quaternion);
  • shape — объект формы (CANNON.Box, CANNON.Sphere и т.д.).
  • offsetVector — объект CANNON.Vec3, задающий смещение формы относительно центра масс тела.
  • quaternion — объект CANNON.Quaternion, определяющий ориентацию формы относительно тела.

Пример: составное тело с кубом и сферой

const body = new CANNON.Body({
    mass: 5,
    position: new CANNON.Vec3(0, 5, 0)
});

const boxShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1));
const sphereShape = new CANNON.Sphere(0.5);

body.addShape(boxShape); // куб в центре тела
body.addShape(sphereShape, new CANNON.Vec3(0, 1.5, 0)); // сфера выше куба

world.addBody(body);

В этом примере куб формирует основу тела, а сфера располагается над ним. Смещение Vec3(0, 1.5, 0) указывает, что центр сферы находится на 1.5 единицы выше центра масс тела.


Расчёт инерции и центра масс

Cannon.js автоматически рассчитывает массу и момент инерции тела с учётом всех форм, добавленных через addShape. Если формы имеют разные смещения, центр масс тела смещается, а инерция корректно учитывает распределение массы.

Особенности:

  • Форма с положительным смещением увеличивает момент инерции вокруг соответствующей оси.
  • Для симметричных объектов центр масс обычно совпадает с геометрическим центром. Для асимметричных форм важно правильно задавать смещения.

Пример расчёта с асимметричным телом:

const body = new CANNON.Body({ mass: 10 });

const base = new CANNON.Box(new CANNON.Vec3(2, 0.5, 1));
const arm = new CANNON.Box(new CANNON.Vec3(0.5, 2, 0.5));

body.addShape(base); // основание
body.addShape(arm, new CANNON.Vec3(2.5, 1.5, 0)); // "рука" справа и выше

console.log(body.inertia); // автоматически рассчитанный тензор инерции

Ориентация форм внутри тела

Каждая форма может иметь собственную ориентацию через CANNON.Quaternion. Это позволяет создавать наклонённые или вращающиеся элементы внутри одного Body.

Пример: наклонённая плита

const tiltedShape = new CANNON.Box(new CANNON.Vec3(1, 0.2, 2));
const tiltQuat = new CANNON.Quaternion();
tiltQuat.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), Math.PI / 6); // наклон 30 градусов

body.addShape(tiltedShape, new CANNON.Vec3(0, 0, 0), tiltQuat);

Ограничения и особенности

  1. Форма не может быть удалена из тела после добавления — для изменения нужно создавать новый Body.
  2. Взаимодействие с другими телами учитывает все формы. Система столкновений работает с каждой формой отдельно, что позволяет точнее моделировать сложные объекты.
  3. Масса распределяется пропорционально формам. Если необходимо, можно задавать массу тела вручную, чтобы контролировать поведение симуляции.
  4. Производительность. Чем больше форм на одном Body, тем выше нагрузка на расчёт столкновений, особенно если формы сложные или имеют наклон.

Примеры составных тел для практических задач

  • Танк или робот: основное тело — куб или прямоугольник, башня и оружие — отдельные формы с смещением и вращением.
  • Мебель: стол с ножками, каждая ножка — отдельная форма, столешница — основная.
  • Мосты или конструкции: балки и перекладины можно моделировать как формы, объединённые в один Body.

Взаимодействие с внешними силами и столкновениями

Составные тела полностью интегрируются с физическим миром:

  • Гравитация действует на центр масс тела.
  • Сила и момент могут применяться через applyForce и applyLocalForce, при этом смещения форм учитываются.
  • Столкновения обрабатываются корректно для каждой формы, что позволяет моделировать сложные контактные ситуации.

Пример применения силы к составному телу:

const force = new CANNON.Vec3(0, 500, 0);
const point = new CANNON.Vec3(1, 0, 0); // точка относительно центра масс
body.applyForce(force, point);

Рекомендации по использованию

  • Для сложных объектов предпочтительно разделять на несколько составных тел, если требуется разное физическое поведение частей.
  • Для динамических тел стоит внимательно подбирать массу и распределение форм, чтобы избежать нестабильности.
  • Использование квази-симметричных форм упрощает расчёт инерции и делает симуляцию более предсказуемой.

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