Oimo.js — это лёгкая библиотека для симуляции физики твёрдых тел в JavaScript. Она предназначена для работы с динамическими объектами, расчёта столкновений, гравитации и инерции. Центральной частью любого физического симулятора является определение состояния объектов: движутся они или находятся в покое. Этот аспект критичен для оптимизации, корректной обработки коллизий и реалистичной физики.
Покоящееся тело (sleeping body) — объект, который временно не участвует в активных вычислениях симулятора, так как его скорость и ускорение находятся ниже заданного порога. Использование режима покоя позволяет значительно снизить нагрузку на процессор, особенно при большом количестве объектов.
В Oimo.js каждое тело (RigidBody) имеет следующие
ключевые свойства для определения покоя:
Для определения покоя используются пороговые значения:
const linearThreshold = 0.01; // минимальная линейная скорость
const angularThreshold = 0.01; // минимальная угловая скорость
const sleepTimeThreshold = 60; // количество шагов симуляции для сна
Логика проверки состояния тела строится следующим образом:
linearVelocity и
angularVelocity меньше соответствующих порогов.sleepTime.sleepTime превышает
sleepTimeThreshold, тело переводится в состояние сна
(sleeping = true).sleepTime и выводит тело из сна.Процесс вычисления состояния тела делится на несколько этапов:
Сначала обновляются линейная и угловая скорости на основе приложенных сил и моментов:
body.linearVelocity.add(body.force.scale(body.inverseMass));
body.angularVelocity.add(body.torque.applyMatrix3(body.inverseInertia));
Вычисляются нормы скорости:
const linearSpeed = body.linearVelocity.length();
const angularSpeed = body.angularVelocity.length();
Если обе скорости меньше порогов, тело считается потенциально покоящимся.
if (linearSpeed < linearThreshold && angularSpeed < angularThreshold) {
body.sleepTime++;
if (body.sleepTime >= sleepTimeThreshold) {
body.sleeping = true;
}
} else {
body.sleepTime = 0;
body.sleeping = false;
}
Любое внешнее воздействие, которое изменяет скорости тела выше порогов, автоматически выводит его из сна:
body.linearVelocity.add(externalImpulse);
body.angularVelocity.add(externalTorque);
body.sleeping = false;
body.sleepTime = 0;
linearThreshold и
angularThreshold, что позволяет точнее контролировать
поведение мелких или тяжёлых объектов.function stepSimulation(world) {
const bodies = world.bodies;
for (let i = 0; i < bodies.length; i++) {
const body = bodies[i];
if (!body.sleeping) {
body.integrate(); // обновление позиции и скорости
body.checkSleep(); // проверка условий покоя
}
}
}
Метод checkSleep() внутри RigidBody
инкапсулирует весь алгоритм проверки порогов и перевода в состояние
сна.
Использование режима сна повышает производительность, но требует аккуратного выбора порогов. Слишком высокие значения могут привести к «залипанию» объектов и визуальным артефактам, особенно для мелких и лёгких тел. Слишком низкие — увеличивают нагрузку, так как почти все объекты остаются активными.
Для динамического контроля можно принудительно разбудить тело:
body.sleeping = false;
body.sleepTime = 0;
Это используется, когда объекты сталкиваются с внешними воздействиями, анимацией или игровыми событиями.
linearVelocity, angularVelocity,
sleeping, sleepTime,
linearThreshold, angularThreshold.integrate(), applyForce(),
applyTorque(), checkSleep().Этот подход позволяет поддерживать баланс между физической реалистичностью и производительностью симуляции в Oimo.js. Он лежит в основе управления активными объектами и эффективной обработки динамических сцен.