Взаимосвязь между World, Body, Shape и Joint

В основе библиотеки Oimo.js лежит чёткая модель разделения ответственности между четырьмя ключевыми сущностями:

  • World — физический мир и симуляция
  • Body — физическое тело
  • Shape — геометрическая форма тела
  • Joint — ограничение или связь между телами

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


World — центр управления симуляцией

World является контейнером всей физической сцены. Он отвечает за:

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

Основные обязанности World

  1. Хранение объектов

    • Массив тел
    • Массив соединений
    • Контактные пары
  2. Физический шаг

    • Вычисление сил
    • Интеграция скоростей
    • Обнаружение столкновений
    • Разрешение контактов
    • Решение ограничений Joint
  3. Глобальные параметры

    • Вектор гравитации
    • Итерации решателя
    • Параметры широкофазной проверки

Связи World

World
 ├── Body
 │    └── Shape
 └── Joint (соединяет Body ↔ Body)

World управляет всеми Body и Joint, но не владеет Shape напрямую — формы принадлежат телам.


Body — физический носитель массы и движения

Body представляет физический объект с положением, ориентацией, массой и скоростью. Однако геометрии внутри него нет — она задаётся через Shape.

Что содержит Body

  • Позиция (Vector3)
  • Кватернион вращения
  • Линейная скорость
  • Угловая скорость
  • Масса
  • Матрица инерции
  • Список Shape
  • Флаги состояния (static, dynamic, kinematic)

Типы тел

  1. Dynamic

    • Подчиняется гравитации
    • Участвует в столкновениях
    • Может двигаться
  2. Static

    • Бесконечная масса
    • Не двигается
    • Используется для пола, стен
  3. Kinematic

    • Движется вручную
    • Не подчиняется силам
    • Влияет на другие тела

Связь Body с World

При добавлении тела в мир:

world.add(body);
  • Body регистрируется в World
  • Создаётся прокси для broad-phase
  • Тело включается в цикл симуляции

Удаление происходит аналогично.


Shape — геометрическая составляющая тела

Shape описывает форму, по которой рассчитываются:

  • столкновения
  • объём
  • инерция
  • центр масс

Важная особенность

Body может содержать несколько Shape. Это позволяет:

  • создавать составные объекты,
  • смещать центр масс,
  • строить сложные формы из простых примитивов.

Поддерживаемые формы

  • Box
  • Sphere
  • Cylinder
  • Capsule
  • Convex

Связь Shape → Body

Shape не существует самостоятельно. Она:

  • создаётся,
  • добавляется к Body,
  • учитывается при расчёте массы.
body.addShape(shape);

После добавления:

  1. Пересчитывается масса тела.
  2. Пересчитывается тензор инерции.
  3. Обновляется AABB.

Локальное преобразование Shape

Каждая Shape имеет:

  • локальную позицию внутри Body,
  • локальную ориентацию.

Таким образом:

Мировая трансформация Shape =
    Трансформация Body +
    Локальная трансформация Shape

Это позволяет создавать, например, Т-образные или L-образные конструкции.


Joint — ограничение между телами

Joint связывает два Body и ограничивает их относительное движение.

Основные функции Joint

  • фиксация расстояния,
  • ограничение вращения,
  • создание шарниров,
  • моделирование пружин,
  • имитация механических систем.

Структура Joint

Joint всегда содержит:

  • body1
  • body2
  • параметры ограничения
  • якорные точки

Типы соединений

  • DistanceJoint
  • HingeJoint
  • SliderJoint
  • BallAndSocketJoint
  • PrismaticJoint

Каждый тип накладывает определённые математические ограничения на движение тел.


Взаимодействие во время шага симуляции

Внутри метода world.step() происходит последовательность действий:

1. Применение гравитации к Body

Dynamic-тела получают ускорение.

2. Broad-phase

Используются AABB Shape для поиска потенциальных столкновений.

3. Narrow-phase

Выполняется точный расчёт контактов между Shape разных тел.

4. Генерация контактных ограничений

Создаются временные структуры контакта.

5. Решение ограничений

Решатель обрабатывает:

  • контактные ограничения,
  • ограничения Joint.

6. Интеграция скоростей и позиций

Обновляются:

  • позиция Body,
  • ориентация Body.

Shape автоматически следуют за Body.


Иерархия владения

Уровень 1 — World

Хранит:

  • Body
  • Joint

Уровень 2 — Body

Хранит:

  • Shape

Уровень 3 — Shape

Не владеет другими сущностями.

Joint

Не принадлежит Body, а регистрируется в World и содержит ссылки на два Body.


Контактная модель: как Shape влияет на Body

Когда две Shape сталкиваются:

  1. Вычисляется точка контакта.
  2. Рассчитывается нормаль.
  3. Определяется глубина проникновения.
  4. Формируется контактное ограничение.

Далее:

  • Контакт влияет на скорость Body.
  • Body изменяет положение.
  • Shape получают новую мировую позицию через Body.

Таким образом Shape является геометрическим интерфейсом, а Body — физическим контейнером состояния.


Масса и инерция: роль Shape в расчётах

При добавлении нескольких Shape к одному Body:

Итоговая масса = сумма масс Shape
Центр масс = взвешенное среднее
Тензор инерции = сумма инерций с учётом смещения

Это означает:

  • геометрия влияет на физику,
  • изменение Shape меняет поведение Body,
  • Joint опираются на центр масс тел.

Связь Joint с Body и World

Joint регистрируется в World:

world.add(joint);

Во время шага симуляции:

  • Joint получает текущие трансформации Body.
  • Вычисляется ошибка ограничения.
  • Решатель корректирует скорости Body.

Важно, что Joint не управляет Shape напрямую — он воздействует исключительно на Body.


Пространственные зависимости

Сущность Имеет позицию Имеет массу Участвует в столкновениях Участвует в решателе
World Нет Нет Управляет процессом Да
Body Да Да Да Да
Shape Локально Через Body Да Через Body
Joint Через Body Нет Нет Да

Типичный жизненный цикл объекта

  1. Создаётся World.
  2. Создаётся Body.
  3. К Body добавляется Shape.
  4. Body добавляется в World.
  5. При необходимости создаётся Joint.
  6. Joint добавляется в World.
  7. Выполняется world.step() в цикле.

Удаление происходит в обратном порядке:

  • удаление Joint,
  • удаление Body,
  • очистка World.

Практическая архитектурная модель сцены

В сложных проектах используется следующая логика:

  • Графическая модель (Three.js, Babylon.js и др.)
  • Отдельная физическая модель на основе Oimo.js
  • Связь через синхронизацию позиции и кватерниона
ThreeMesh.position ← Body.position
ThreeMesh.quaternion ← Body.quaternion

Shape остаются полностью невидимыми для рендера.


Ошибки проектирования при работе с этими сущностями

1. Создание Body без Shape

Такое тело не участвует в столкновениях.

2. Частое пересоздание World

Нарушает производительность.

3. Изменение геометрии Shape без пересчёта массы

Приводит к некорректной физике.

4. Прямое изменение позиции Shape

Не влияет на мир — управлять нужно через Body.


Ключевые принципы взаимосвязи

  1. World управляет всем.
  2. Body содержит физическое состояние.
  3. Shape определяет форму и столкновения.
  4. Joint ограничивает движение между Body.
  5. Shape никогда не существуют вне Body.
  6. Joint никогда не существуют вне World.
  7. Все вычисления происходят в World.

Ментальная модель системы

  • World — сцена и движок.
  • Body — физический актёр.
  • Shape — его геометрия.
  • Joint — механическая связь между актёрами.

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