Расчёт локальной инерции через calculateLocalInertia

В физическом моделировании объектов важным аспектом является инерция, которая определяет сопротивление тела изменению своей скорости при приложении силы. В библиотеке Ammo.js, являющейся JavaScript-портом популярного движка Bullet Physics, для расчёта локальной инерции используется метод calculateLocalInertia, который вычисляет тензор инерции для тел с различными формами.


Основные понятия

Локальная инерция — это матрица, отражающая распределение массы объекта относительно его локальной системы координат. Она отличается от глобальной инерции тем, что всегда вычисляется в системе координат самого объекта, что упрощает расчёт динамики при вращении и взаимодействии с внешними силами.

Тензор инерции (btVector3 в Ammo.js) задаёт моменты инерции по трем основным осям:

  • X — вращение вокруг оси X.
  • Y — вращение вокруг оси Y.
  • Z — вращение вокруг оси Z.

Для симметричных объектов (куб, сфера) тензор имеет одинаковые значения для осей, тогда как для асимметричных тел значения различаются.


Синтаксис метода

shape.calculateLocalInertia(mass, inertia);

Параметры:

  • shape — объект формы (btBoxShape, btSphereShape, btCylinderShape, btConvexHullShape и т.д.).
  • mass — масса тела. Для статических объектов (mass = 0) расчёт инерции не производится, так как статические тела не вращаются.
  • inertia — объект типа Ammo.btVector3, в который будет записан результат.

Метод не возвращает значение, а заполняет переданный объект inertia.


Пример использования для куба

// Создание формы куба
const halfExtents = new Ammo.btVector3(1, 1, 1);
const boxShape = new Ammo.btBoxShape(halfExtents);

// Масса тела
const mass = 2;

// Вектор для хранения локальной инерции
const localInertia = new Ammo.btVector3(0, 0, 0);

// Расчёт локальной инерции
boxShape.calculateLocalInertia(mass, localInertia);

console.log("Локальная инерция по осям:", localInertia.x(), localInertia.y(), localInertia.z());

Для куба с равными сторонами моменты инерции по всем осям будут одинаковыми, что соответствует формуле классической механики:

[ I_x = I_y = I_z = m (a^2 + b^2)]

где a и b — размеры куба по соответствующим осям.


Особенности расчёта для разных форм

  1. Сфера (btSphereShape) Для сферы локальная инерция рассчитывается одинаково по всем осям, по формуле:

    [ I = m r^2]

  2. Цилиндр (btCylinderShape) Инерция зависит от направления цилиндра. Для вертикального цилиндра моменты вокруг осей X и Z равны, а Y отличается.

  3. Выпуклый многоугольник (btConvexHullShape) Расчёт выполняется численно. Ammo.js интегрирует распределение массы по всем вершинам, учитывая асимметрию формы.


Связь с динамикой объекта

После вычисления локальной инерции её необходимо передать при создании rigid body:

const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 5, 0));

const motionState = new Ammo.btDefaultMotionState(transform);

const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, boxShape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);

Использование правильной локальной инерции обеспечивает реалистичное поведение объекта при вращении и столкновениях. Без корректного расчёта тело может вести себя нестабильно или вращаться неадекватно.


Советы по эффективному использованию

  • Масса = 0 автоматически делает тело статическим, и calculateLocalInertia можно пропускать.
  • Для сложных форм (комбинации нескольких мешей) локальная инерция рассчитывается отдельно для каждой составляющей и суммируется.
  • Перед повторным использованием формы желательно сбросить предыдущие значения btVector3, чтобы избежать накопления ошибок.

Практический пример: динамика смеси форм

// Куб + сфера
const box = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));
const sphere = new Ammo.btSphereShape(0.5);

const massBox = 1;
const massSphere = 0.5;

const inertiaBox = new Ammo.btVector3(0, 0, 0);
const inertiaSphere = new Ammo.btVector3(0, 0, 0);

box.calculateLocalInertia(massBox, inertiaBox);
sphere.calculateLocalInertia(massSphere, inertiaSphere);

// Для комбинированного тела моменты суммируются по осям
const combinedInertia = new Ammo.btVector3(
    inertiaBox.x() + inertiaSphere.x(),
    inertiaBox.y() + inertiaSphere.y(),
    inertiaBox.z() + inertiaSphere.z()
);

Этот подход позволяет строить сложные конструкции с реалистичной динамикой вращения.


Локальная инерция через calculateLocalInertia является ключевым инструментом для создания реалистичных физически корректных объектов в Ammo.js. Понимание того, как форма и масса влияют на тензор инерции, критично для точного моделирования динамических систем.