В библиотеке Ammo.js физические объекты
представляются как тела (btRigidBody), которые
взаимодействуют с миром через физический движок. Процесс добавления тела
начинается с определения его формы, массы и начальных свойств.
Форма тела создается с помощью коллайдеров
(btCollisionShape). Среди наиболее распространенных
форм:
Куб (btBoxShape) — определяется
вектором половины размеров по осям X, Y, Z.
let halfExtents = new Ammo.btVector3(1, 1, 1);
let boxShape = new Ammo.btBoxShape(halfExtents);Сфера (btSphereShape) — задается
радиусом.
Цилиндр, конус, капсула (btCylinderShape,
btConeShape, btCapsuleShape) — для
более сложных объектов.
Композитные формы (btCompoundShape)
— позволяют объединять несколько простых форм в одно тело.
Масса и инерция. Для динамических объектов необходимо задать массу больше нуля и вычислить локальный тензор инерции:
let mass = 5;
let localInertia = new Ammo.btVector3(0, 0, 0);
boxShape.calculateLocalInertia(mass, localInertia);
Положение и ориентация тела задаются через
btTransform:
let transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 10, 0)); // начальная позиция
transform.setRotation(new Ammo.btQuaternion(0, 0, 0, 1)); // ориентация
Создание тела и добавление в мир:
let motionState = new Ammo.btDefaultMotionState(transform);
let rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, boxShape, localInertia);
let body = new Ammo.btRigidBody(rbInfo);
physicsWorld.addRigidBody(body);
Ключевой момент: все динамические объекты должны иметь вычисленный локальный тензор инерции, иначе они будут вести себя как статические.
После создания тела можно задать дополнительные физические свойства:
body.setFriction(0.5);
body.setRestitution(0.7);
body.setLinearFactor(new Ammo.btVector3(1, 1, 1));
body.setAngularFactor(new Ammo.btVector3(0, 1, 0)); // вращение только по оси Y
body.setActivationState(Ammo.DISABLE_DEACTIVATION);
Удаление тела из мира в Ammo.js требует нескольких шагов, чтобы избежать утечек памяти, так как библиотека использует систему ручного управления памятью.
Пошаговый процесс:
physicsWorld.removeRigidBody(body);
MotionState):let motionState = body.getMotionState();
if (motionState) {
Ammo.destroy(motionState);
}
let shape = body.getCollisionShape();
Ammo.destroy(shape);
Ammo.destroy(body);
После этих действий объект полностью освобождается из памяти, и повторного обращения к нему быть не должно.
Для игр и симуляций часто необходимо создавать и уничтожать объекты на лету:
Пример динамического удаления по условию позиции:
if (body.getWorldTransform().getOrigin().y() < -10) {
physicsWorld.removeRigidBody(body);
Ammo.destroy(body.getMotionState());
Ammo.destroy(body.getCollisionShape());
Ammo.destroy(body);
}
mass = 0) для объектов, которые не должны двигаться. Это
снижает нагрузку на физический движок.physicsWorld.addRigidBody(body, group, mask);
group — группа, к которой относится телоmask — с какими группами оно может сталкиватьсяbtCompoundShape позволяет создавать сложные тела,
комбинируя несколько коллайдеров:
let compound = new Ammo.btCompoundShape();
let childTransform = new Ammo.btTransform();
childTransform.setIdentity();
childTransform.setOrigin(new Ammo.btVector3(0, 1, 0));
compound.addChildShape(childTransform, boxShape);
Это особенно полезно для машин, зданий и других объектов со сложной геометрией, где требуется точное определение столкновений.
Ammo.destroy. Пропуск этого шага
приводит к утечкам памяти.Эти правила позволяют эффективно управлять физическими объектами, обеспечивая корректную симуляцию и стабильную работу приложения.