Итерация по всем активным контактам мира

В физическом движке Oimo.js взаимодействия между объектами моделируются через контакты — точки соприкосновения между коллайдерами тел. Управление контактами позволяет детально контролировать поведение объектов в симуляции, отслеживать столкновения и реализовывать сложные физические эффекты.

Контакты и их структура

Контакт в Oimo.js представляет собой объект с набором ключевых свойств:

  • body1 и body2 — тела, участвующие в контакте.
  • manifold — информация о точках контакта, нормалях и глубине проникновения.
  • enabled — флаг активности контакта, определяющий, учитывается ли он при расчёте силы реакции.

Контакты создаются автоматически при столкновении тел, имеющих коллайдеры с физическими свойствами. Oimo.js поддерживает динамические и статические тела, что важно учитывать при обработке контактов: статические тела могут быть участниками контакта, но их реакция на столкновение ограничена.

Доступ к контактам мира

Мир в Oimo.js (world) хранит все текущие контакты в виде внутреннего списка. Для итерации по всем активным контактам используется метод world.contacts или напрямую обходятся внутренние структуры движка.

Пример базового обхода:

const contacts = world.contacts; // массив или связанный список контактов
for (let i = 0; i < contacts.length; i++) {
    const contact = contacts[i];
    if (contact.enabled) {
        console.log("Контакт между:", contact.body1.name, "и", contact.body2.name);
    }
}

Ключевой момент — проверка флага enabled. Это позволяет исключить неактивные контакты и уменьшить нагрузку на симуляцию, особенно при большом количестве тел.

Манипуляция контактами

Контакты можно включать или отключать, изменять параметры трения или упругости на лету:

contact.enabled = false; // временно игнорировать контакт
contact.friction = 0.5;  // изменение коэффициента трения
contact.restitution = 0.8; // коэффициент упругости

Эти возможности позволяют реализовывать:

  • зональные эффекты столкновений (например, отключение контакта с определённой поверхностью),
  • динамическую регулировку поведения материалов,
  • специализированные механики вроде «скольжения» или «липких» объектов.

Обход и модификация в реальном времени

Для сложных симуляций важно обрабатывать контакты во время шага симуляции. Это делается в основном цикле, после вызова world.step():

world.step();
world.contacts.forEach(contact => {
    if (contact.enabled) {
        const penetrationDepth = contact.manifold.depths[0];
        if (penetrationDepth > 0.1) {
            contact.friction *= 0.9; // уменьшение трения при сильном проникновении
        }
    }
});

Oimo.js хранит несколько точек контакта для одного столкновения (manifold), что позволяет учитывать сложные формы коллайдеров и точные физические реакции.

Практические рекомендации

  1. Фильтрация контактов по телам Для оптимизации можно проверять, участвует ли в контакте конкретное тело, чтобы обрабатывать только нужные взаимодействия.

  2. Использование колбэков столкновений Oimo.js позволяет отслеживать события начала и конца контакта через onContact-подобные функции. Это облегчает обработку логики без постоянной итерации по всему массиву.

  3. Минимизация прямого изменения контактов В большинстве случаев достаточно менять свойства тел или коллайдеров. Прямое вмешательство в контакты рекомендуется только для продвинутых эффектов, чтобы не нарушить внутреннюю целостность физического мира.

Совместное использование с другими компонентами

Контакты часто взаимодействуют с:

  • RigidBody — определяют физические реакции и ограничения движения,
  • Collider — форма, материал и свойства поверхности влияют на manifold,
  • Constraints — ограничения, например, шарнир или пружина, могут менять активность контактов через силу или движение тел.

Правильная организация обхода всех активных контактов обеспечивает точное управление симуляцией, позволяет реализовать кастомную механику столкновений и улучшает производительность сложных сцен.