Для работы с Oimo.js требуется подключение библиотеки в проект.
Обычно это выполняется через <script> для браузерных
приложений или через npm для проектов на Node.js. После подключения
создается физический мир (world), который является контейнером для всех
объектов и взаимодействий.
import * as OIMO from 'oimo'; // через npm
const world = new OIMO.World({
timestep: 1/60,
gravity: [0, -9.8, 0],
broadphase: 2, // оптимизация расчёта коллизий
});
Ключевой момент: параметр broadphase
влияет на производительность при большом числе объектов. Значение
2 соответствует оптимизированной решётке (Sweep and
Prune).
Oimo.js поддерживает три основных типа тел: dynamic (подвижные), static (неподвижные) и kinematic (управляемые вручную). Для диагностики важно уметь получать доступ к объектам и их свойствам.
const box = world.add({
type: 'box',
size: [1, 1, 1],
pos: [0, 5, 0],
move: true,
});
const ground = world.add({
type: 'box',
size: [10, 1, 10],
pos: [0, 0, 0],
move: false,
});
Важный аспект: свойство move: true
определяет, что объект участвует в симуляции динамики, а
move: false — что объект неподвижен.
Для мониторинга состояния симуляции используется консоль. Oimo.js предоставляет методы для получения:
getPosition())getQuaternion())getLinearVelocity(),
getAngularVelocity())getForce())function logDiagnostics(body) {
const pos = body.getPosition();
const quat = body.getQuaternion();
const linVel = body.getLinearVelocity();
const angVel = body.getAngularVelocity();
console.log(`Позиция: x=${pos.x.toFixed(2)}, y=${pos.y.toFixed(2)}, z=${pos.z.toFixed(2)}`);
console.log(`Ориентация: x=${quat.x.toFixed(2)}, y=${quat.y.toFixed(2)}, z=${quat.z.toFixed(2)}, w=${quat.w.toFixed(2)}`);
console.log(`Линейная скорость: x=${linVel.x.toFixed(2)}, y=${linVel.y.toFixed(2)}, z=${linVel.z.toFixed(2)}`);
console.log(`Угловая скорость: x=${angVel.x.toFixed(2)}, y=${angVel.y.toFixed(2)}, z=${angVel.z.toFixed(2)}`);
}
Подсказка: метод toFixed(2) делает
вывод более читаемым, показывая только два знака после запятой.
Симуляция в Oimo.js требует регулярного обновления мира. В цикле анимации удобно выводить диагностические данные для анализа поведения тел.
function animate() {
world.step();
logDiagnostics(box);
requestAnimationFrame(animate);
}
animate();
Ключевой момент: world.step() проводит
расчет всех физических взаимодействий за один шаг симуляции. Важно
вызывать его перед чтением свойств объектов, иначе данные будут
устаревшими.
Oimo.js позволяет получать информацию о контактах между телами, что полезно для отладки столкновений и физического поведения.
const contacts = world.contacts;
contacts.forEach(contact => {
const bodyA = contact.body1;
const bodyB = contact.body2;
console.log(`Контакт между телами: ${bodyA.name || 'body1'} и ${bodyB.name || 'body2'}`);
});
Особенность: каждый контакт содержит нормаль столкновения, точку контакта и силу реакции. Для подробной диагностики можно выводить эти данные отдельно:
console.log(`Нормаль: x=${contact.normal.x}, y=${contact.normal.y}, z=${contact.normal.z}`);
console.log(`Сила: ${contact.impulse}`);
Для удобства диагностики часто комбинируют вывод в консоль с
графическим отображением тел. Даже простой рендеринг через
Three.js или Canvas позволяет сопоставлять численные данные
с визуальной симуляцией.
Совет: привязывать имена к телам при их создании помогает быстро идентифицировать объекты в консоли:
box.name = 'Box_1';
ground.name = 'Ground';
Это особенно важно при большом числе объектов.
Oimo.js поддерживает настройку отладочной информации через
debug и stats. Можно автоматически выводить
массив тел с их позициями и скоростями:
world.bodies.forEach(body => {
console.log(`Тело: ${body.name || 'Unnamed'}, Позиция: ${body.getPosition().toArray()}, Скорость: ${body.getLinearVelocity().toArray()}`);
});
Совет: использование массива .toArray()
ускоряет вывод и делает код компактным при необходимости логировать
десятки объектов одновременно.
Для отладки больших сцен полезно фильтровать тела по условию. Например, выводить информацию только о движущихся объектах:
world.bodies.forEach(body => {
if (body.isDynamic()) {
logDiagnostics(body);
}
});
Пояснение: isDynamic() возвращает true
только для тел с типом dynamic, исключая статические и
кинематические объекты.
Можно создать объект-обертку для логирования всех тел с определённой периодичностью:
class Diagnostics {
constructor(world, interval = 500) {
this.world = world;
setInterval(() => this.logAllBodies(), interval);
}
logAllBodies() {
this.world.bodies.forEach(body => logDiagnostics(body));
}
}
const diag = new Diagnostics(world);
Такой подход позволяет непрерывно отслеживать состояние симуляции без вмешательства в основной цикл анимации.
Выстроенная структура логирования, фильтрации и регулярного обновления данных позволяет получать детализированную информацию о поведении физических объектов в Oimo.js, выявлять ошибки, корректировать параметры симуляции и повышать точность физического моделирования.