В высокопроизводительных приложениях на Ammo.js, особенно в симуляциях физики с множеством объектов, критически важно минимизировать создание и удаление объектов в памяти. Частая динамическая аллокация объектов типа btVector3 и btTransform приводит к нагрузке на сборщик мусора и падению производительности. Для решения этой проблемы применяется пул объектов (object pool), позволяющий переиспользовать уже созданные экземпляры.
Создание этих объектов внутри цикла обновления физики может быть крайне затратным. Пул объектов позволяет хранить заранее созданные экземпляры и получать их по мере необходимости, возвращая обратно после использования.
Пул объектов можно реализовать как простой массив. Для btVector3 и btTransform выделяются отдельные пулы:
class AmmoPool {
constructor() {
this.vector3Pool = [];
this.transformPool = [];
}
getVector3(x = 0, y = 0, z = 0) {
let vec = this.vector3Pool.pop();
if (!vec) {
vec = new Ammo.btVector3(x, y, z);
} else {
vec.setValue(x, y, z);
}
return vec;
}
releaseVector3(vec) {
this.vector3Pool.push(vec);
}
getTransform() {
let tr = this.transformPool.pop();
if (!tr) {
tr = new Ammo.btTransform();
}
tr.setIdentity();
return tr;
}
releaseTransform(tr) {
this.transformPool.push(tr);
}
}
Ключевые моменты:
getVector3 возвращает вектор с заданными
координатами, создавая новый только если пул пуст.getTransform возвращает трансформацию с начальной
идентичной ориентацией.releaseVector3 или releaseTransform.btVector3 часто создаются при расчетах силы, импульса, скорости или в коллизиях. Без пула каждый кадр может генерировать десятки новых объектов:
function applyForce(body, force, pool) {
const btForce = pool.getVector3(force.x, force.y, force.z);
body.applyCentralForce(btForce);
pool.releaseVector3(btForce);
}
Выигрыши от пула:
btTransform используется при позиционировании объектов в мире, чтении результатов коллизий или при телах с кинематикой:
function updateBodyTransform(body, position, quaternion, pool) {
const tr = pool.getTransform();
const origin = pool.getVector3(position.x, position.y, position.z);
tr.setOrigin(origin);
tr.setRotation(new Ammo.btQuaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w));
body.setWorldTransform(tr);
pool.releaseVector3(origin);
pool.releaseTransform(tr);
}
Особенности:
setIdentity(), чтобы сбросить предыдущие данные.btQuaternion внутри цикла, а также рассмотреть пул для них
при необходимости.btTransform сокращает создание
временных объектов для каждого тела на каждом кадре.btTransform, содержащего
btVector3, следует убедиться, что внутренние векторы тоже
берутся из пула.onUpdate, tick или обработчики
столкновений.Переиспользование btVector3 и btTransform через пул объектов позволяет:
Применение таких подходов становится критически важным при разработке сложных 3D симуляций и игр на базе Ammo.js, где производительность напрямую зависит от количества временных объектов, создаваемых каждый кадр.