Внутри движка Ammo.js обработка столкновений
основана на механизмах библиотеки Bullet Physics. Одним
из ключевых элементов этой системы является структура
btPersistentManifold — объект, хранящий информацию о
контактах между двумя коллидирующими телами.
btPersistentManifold представляет собой набор точек
контакта, которые сохраняются между кадрами симуляции. Это
позволяет:
Каждая пара объектов, находящихся в контакте, может иметь один или несколько манфолдов, в зависимости от типа коллизии и настроек диспетчера.
Система столкновений строится вокруг следующих компонентов:
btCollisionWorldbtDispatcherbtPersistentManifoldbtManifoldPointПоследовательность работы:
btPersistentManifold.btPersistentManifold создаётся диспетчером
(btDispatcher) и хранится внутри него до тех пор, пока
объекты продолжают находиться в контакте.
После выполнения шага симуляции (stepSimulation) можно
получить доступ к списку всех текущих контактов через диспетчер:
let dispatcher = physicsWorld.getDispatcher();
let numManifolds = dispatcher.getNumManifolds();
Метод getNumManifolds() возвращает количество активных
манфолдов.
Получение конкретного манфолда:
let manifold = dispatcher.getManifoldByIndexInternal(i);
Каждый такой объект — это btPersistentManifold,
содержащий информацию о двух телах и их контактных точках.
btPersistentManifold хранит ссылки на два объекта:
let body0 = manifold.getBody0();
let body1 = manifold.getBody1();
Эти значения — указатели на btCollisionObject. Для
работы с физическими телами требуется приведение к
btRigidBody:
let rigidBody0 = Ammo.castObject(body0, Ammo.btRigidBody);
let rigidBody1 = Ammo.castObject(body1, Ammo.btRigidBody);
Это позволяет получить доступ к массе, скорости, пользовательским данным и другим параметрам.
Количество контактных точек в манфолде:
let numContacts = manifold.getNumContacts();
Контактные точки представлены объектами
btManifoldPoint.
Получение конкретной точки:
let contactPoint = manifold.getContactPoint(j);
btManifoldPointКаждая контактная точка содержит:
Основные методы:
let ptA = contactPoint.getPositionWorldOnA();
let ptB = contactPoint.getPositionWorldOnB();
let normal = contactPoint.get_m_normalWorldOnB();
let distance = contactPoint.getDistance();
getDistance() возвращает:
Обычно проверяется условие:
if (distance < 0) {
// контакт активен
}
let dispatcher = physicsWorld.getDispatcher();
let numManifolds = dispatcher.getNumManifolds();
for (let i = 0; i < numManifolds; i++) {
let manifold = dispatcher.getManifoldByIndexInternal(i);
let body0 = Ammo.castObject(
manifold.getBody0(),
Ammo.btRigidBody
);
let body1 = Ammo.castObject(
manifold.getBody1(),
Ammo.btRigidBody
);
let numContacts = manifold.getNumContacts();
for (let j = 0; j < numContacts; j++) {
let contactPoint = manifold.getContactPoint(j);
let distance = contactPoint.getDistance();
if (distance < 0) {
let positionA = contactPoint.getPositionWorldOnA();
let positionB = contactPoint.getPositionWorldOnB();
let normal = contactPoint.get_m_normalWorldOnB();
console.log("Контакт обнаружен");
}
}
}
btPersistentManifold:
Контактные точки могут:
Это повышает производительность и устойчивость симуляции.
Если требуется отслеживать столкновения конкретного объекта, эффективнее:
Каждому btRigidBody можно назначить
userData в JavaScript-обёртке. Это позволяет:
При создании тела можно использовать группы и маски столкновений, чтобы сократить число манфолдов.
Ammo.js использует WebAssembly-обёртку над C++-кодом. Векторы
(btVector3) и другие объекты занимают память вне сборщика
мусора JavaScript.
После использования временных объектов рекомендуется освобождать их:
Ammo.destroy(vector);
Однако объекты, полученные через getContactPoint() или
getPositionWorldOnA(), уничтожать не требуется — они
управляются внутренним движком.
Контакты позволяют реализовать:
Пример проверки «на земле»:
if (normal.y() > 0.5) {
isGrounded = true;
}
Значение нормали позволяет определить направление контакта.
В Ammo.js отсутствует встроенная система событий столкновения, как в некоторых игровых движках. Поэтому:
btPersistentManifold,Для этого создаётся структура:
let previousContacts = new Set();
И сравниваются пары тел между кадрами.
Количество и стабильность контактных точек зависит от:
stepSimulation,Неправильный timestep может приводить к:
btPersistentManifoldbtPersistentManifold является центральным элементом
взаимодействия между этапами обнаружения столкновений и расчётом
физической реакции, обеспечивая стабильность и производительность всей
системы физической симуляции в Ammo.js.