Ammo.js — это порт библиотеки Bullet Physics на JavaScript с использованием Emscripten, предоставляющий мощный движок физики для браузера. Он позволяет создавать реалистичные симуляции твердых тел, столкновений и динамики объектов с высокой производительностью, подходящей для игр и интерактивных веб-приложений.
Основной принцип работы Ammo.js — это разделение сцены на объекты физики, которые обрабатываются в отдельной системе симуляции. Каждый объект имеет тело (rigid body), физические свойства и форму (collision shape).
Создание физического мира начинается с конфигурации и выбора подходящего дискретного динамического мира:
// Настройка конфигурации коллизий
const collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
const dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
const broadphase = new Ammo.btDbvtBroadphase();
const solver = new Ammo.btSequentialImpulseConstraintSolver();
// Создание физического мира
const dynamicsWorld = new Ammo.btDiscreteDynamicsWorld(
dispatcher,
broadphase,
solver,
collisionConfiguration
);
// Установка гравитации
dynamicsWorld.setGravity(new Ammo.btVector3(0, -9.81, 0));
Ключевые моменты:
Каждое тело физики состоит из формы (collision shape) и массы, а также имеет позицию и ориентацию. Наиболее часто используются следующие формы:
Пример создания куба:
const boxShape = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));
const mass = 1;
const localInertia = new Ammo.btVector3(0, 0, 0);
boxShape.calculateLocalInertia(mass, localInertia);
const startTransform = new Ammo.btTransform();
startTransform.setIdentity();
startTransform.setOrigin(new Ammo.btVector3(0, 10, 0));
const motionState = new Ammo.btDefaultMotionState(startTransform);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, boxShape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);
dynamicsWorld.addRigidBody(body);
Важные детали:
Для обновления состояния физического мира используется stepSimulation, принимающий время кадра и количество итераций:
function updatePhysics(deltaTime) {
dynamicsWorld.stepSimulation(deltaTime, 10);
// Обновление позиции объекта
const transform = new Ammo.btTransform();
body.getMotionState().getWorldTransform(transform);
const origin = transform.getOrigin();
console.log(`Позиция куба: x=${origin.x()}, y=${origin.y()}, z=${origin.z()}`);
}
Подшаги (substeps):
stepSimulation(deltaTime, maxSubSteps)
задает максимальное число подшагов для более точной
симуляции при изменении времени кадра.Для управления объектами используются методы:
Пример:
const force = new Ammo.btVector3(0, 50, 0);
body.applyCentralImpulse(force);
Ammo.js поддерживает различные типы соединений (constraints):
Создание шарнирной связи между двумя телами:
const pivotInA = new Ammo.btVector3(0, 1, 0);
const pivotInB = new Ammo.btVector3(0, -1, 0);
const constraint = new Ammo.btPoint2PointConstraint(bodyA, bodyB, pivotInA, pivotInB);
dynamicsWorld.addConstraint(constraint, true);
Ammo.js использует ручное управление памятью. Для предотвращения утечек необходимо удалять объекты после использования:
Ammo.destroy(body);
Ammo.destroy(boxShape);
Ammo.destroy(motionState);
btConvexHullShape позволяет создавать сложные формы:
const points = [ [1,1,1], [-1,1,1], [-1,-1,1], [1,-1,1] ];
const hullShape = new Ammo.btConvexHullShape();
points.forEach(p => hullShape.addPoint(new Ammo.btVector3(p[0], p[1], p[2])));
Использование выпуклых форм увеличивает реализм столкновений при сохранении стабильности симуляции.
maxSubSteps снижает точность, но ускоряет симуляцию.Для визуализации физики часто используют Three.js:
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
function syncPhysics() {
const transform = new Ammo.btTransform();
body.getMotionState().getWorldTransform(transform);
const origin = transform.getOrigin();
mesh.position.set(origin.x(), origin.y(), origin.z());
}
Поддержание синхронизации между физическим телом и графическим объектом является критическим для корректного отображения сцены.
Ammo.js предоставляет полную платформу для симуляции физики в браузере, сочетая мощь Bullet Physics с возможностями JavaScript, позволяя реализовать сложные системы столкновений, динамики тел и взаимодействий в реальном времени.