Вывод диагностической информации в консоль

Для работы с 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, выявлять ошибки, корректировать параметры симуляции и повышать точность физического моделирования.