Ammo.js — это порт библиотеки
Bullet Physics на JavaScript с использованием
Emscripten. Он предоставляет высокопроизводительные
инструменты для реализации динамической физики в браузере. Основные
сущности движка включают мир (dynamicsWorld),
тела (rigidBody), формы коллизий
(collisionShape) и движки столкновений
(collisionDispatcher). Для работы с контактами между объектами
ключевым становится механизм обратного вызова —
onContactAdded.
onContactAdded вызывается каждый раз, когда два тела
начинают контактировать. Его основной назначение — обработка информации
о столкновении в реальном времени. Это может включать:
Подписка на этот коллбэк происходит через Ammo.custom.
Прямого интерфейса в чистом Ammo.js нет, поэтому
используется переопределение низкоуровневых функций
btManifoldResult и
contactProcessedCallback.
Пример базового шаблона:
Ammo.custom = {
contactProcessedCallback: function(cp, body0, body1) {
onContactAdded(cp, body0, body1);
return false;
}
};
function onContactAdded(cp, body0, body1) {
const rb0 = Ammo.castObject(body0, Ammo.btRigidBody);
const rb1 = Ammo.castObject(body1, Ammo.btRigidBody);
const pos0 = rb0.getCenterOfMassPosition();
const pos1 = rb1.getCenterOfMassPosition();
console.log("Контакт между телами:", rb0, rb1);
console.log("Позиции тел:", pos0.x(), pos0.y(), pos0.z(), pos1.x(), pos1.y(), pos1.z());
}
btManifoldPoint,
содержащая точку контакта, нормаль и силу столкновения.btCollisionObject, участвующие в контакте.Из btManifoldPoint можно получить:
cp.getPositionWorldOnA(),
cp.getPositionWorldOnB(),cp.m_normalWorldOnB,cp.getAppliedImpulse().function onContactAdded(cp, body0, body1) {
const type0 = body0.getUserIndex();
const type1 = body1.getUserIndex();
if ((type0 === 1 && type1 === 2) || (type0 === 2 && type1 === 1)) {
applySpecialEffect(cp, body0, body1);
}
}
Можно изменять массу, коэффициент трения или добавлять импульс при столкновении:
function applyImpulse(body, impulseVector) {
const rb = Ammo.castObject(body, Ammo.btRigidBody);
const impulse = new Ammo.btVector3(impulseVector.x, impulseVector.y, impulseVector.z);
rb.applyImpulse(impulse, new Ammo.btVector3(0,0,0));
Ammo.destroy(impulse);
}
onContactAdded идеально подходит для подсчета количества
контактов на кадр, определения зон с высокой нагрузкой или логики
разрушений объектов.
let contactsPerFrame = 0;
function onContactAdded(cp, body0, body1) {
contactsPerFrame++;
}
onContactAdded срабатывает только на начальных
фазах контакта. Для непрерывного мониторинга контактов нужно
использовать btPersistentManifold.btVector3 и других объектов Ammo.js, чтобы
избежать утечек.false или true.
true иногда используется для модификации поведения
столкновения, но в большинстве случаев достаточно
false.setUserIndex) для фильтрации контактов, чтобы
уменьшить количество проверок.onContactAdded с
группами столкновений
(collisionFilterGroup), чтобы обработка
происходила только для нужных категорий объектов.contactProcessedCallback.Использование onContactAdded позволяет создавать
продвинутые механики взаимодействия объектов в браузере: от простых
столкновений до сложных систем разрушений и симуляций.