Верёвки и цепи из связанных тел

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

Ключевая идея:

  • Верёвка — гибкая система тел с ограничением расстояния или шарнирными соединениями.
  • Цепь — набор звеньев, соединённых шарнирами с ограничением вращения.
  • Трос — комбинация ограничений расстояния и демпфирования.

Физически корректное поведение достигается за счёт итеративного решателя ограничений, встроенного в Oimo.js.


Типы соединений, применяемые для верёвок и цепей

Для построения связанных систем используются следующие ограничения:

1. DistanceJoint (ограничение расстояния)

Поддерживает фиксированную дистанцию между двумя телами. Применяется для:

  • имитации троса;
  • стабилизации сегментов;
  • ограничения растяжения.

Принцип работы — удержание заданного расстояния между якорными точками тел.

2. RevoluteJoint (шарнирное соединение)

Позволяет телам вращаться вокруг одной оси. Используется для:

  • цепей;
  • звеньев;
  • гибких подвесов.

Шарнир сохраняет общую точку соединения, но допускает вращение.

3. BallAndSocketJoint (сферический шарнир)

Позволяет свободное вращение во всех направлениях вокруг точки крепления. Применяется для:

  • мягких канатов;
  • гибких соединений в 3D;
  • подвесов с максимальной свободой движения.

Построение простой верёвки

Верёвка состоит из:

  1. Набора небольших тел (обычно цилиндры или коробки).
  2. Последовательных соединений между соседними сегментами.
  3. Фиксации одного конца к статическому телу.

Создание сегментов

Каждый сегмент — динамическое тело:

const body = world.add({
    type: 'box',
    size: [0.2, 0.2, 0.5],
    pos: [0, 5 - i * 0.5, 0],
    move: true,
    density: 1
});

Ключевые параметры:

  • move: true — тело динамическое.
  • density влияет на массу.
  • Малый размер сегмента повышает гибкость.

Соединение сегментов

Используется RevoluteJoint или BallAndSocketJoint:

world.add({
    type: 'jointBall',
    body1: segments[i],
    body2: segments[i+1],
    pos1: [0, -0.25, 0],
    pos2: [0, 0.25, 0]
});

Таким образом создаётся последовательная цепочка.


Построение цепи с жёсткими звеньями

Цепь отличается от верёвки большей жёсткостью и ограничением углов вращения.

Ограничение углов

Для RevoluteJoint можно задать пределы:

limit: [ -Math.PI / 4, Math.PI / 4 ]

Это предотвращает:

  • чрезмерное изгибание;
  • самопересечение;
  • нестабильность.

Масса и инерция

Для реалистичной цепи:

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

Фиксация концов

Статическое крепление

Первый сегмент соединяется со статическим телом:

const anchor = world.add({
    type: 'box',
    size: [0.1, 0.1, 0.1],
    pos: [0, 5, 0],
    move: false
});

Далее создаётся шарнир между anchor и первым сегментом.

Динамическое крепление

Верёвка может быть соединена с движущимся объектом — например, грузом:

world.add({
    type: 'jointBall',
    body1: lastSegment,
    body2: heavyBox,
    pos1: [0, -0.25, 0],
    pos2: [0, 0.5, 0]
});

Так формируется подвес.


Стабильность и численные проблемы

Связанные системы особенно чувствительны к параметрам симуляции.

1. Количество итераций решателя

В настройках мира:

world = new OIMO.World({
    iterations: 12
});

Увеличение числа итераций:

  • уменьшает растяжение верёвки;
  • повышает стабильность;
  • увеличивает нагрузку на CPU.

2. Малые сегменты

Чем больше сегментов:

  • тем выше гибкость;
  • тем больше вычислительная нагрузка.

Оптимальный баланс достигается экспериментально.

3. Демпфирование

Для предотвращения вибраций:

linearDamping: 0.1,
angularDamping: 0.1

Слишком малое демпфирование приводит к дрожанию цепи.


Растягивающаяся верёвка

DistanceJoint позволяет задать пружинные параметры:

spring: [frequency, damping]

Параметры:

  • frequency — жёсткость;
  • damping — затухание.

Так создаётся эффект эластичного троса.


Коллизии между сегментами

По умолчанию сегменты могут сталкиваться друг с другом. Это приводит к:

  • самоблокировке;
  • нестабильности;
  • резкому росту нагрузки.

Отключение внутренних коллизий выполняется через фильтры групп:

collisionMask: 2,
collisionGroup: 1

Сегменты одной группы можно исключить из взаимных столкновений.


Подвесной мост как пример сложной системы

Верёвки часто применяются для:

  • подвесных мостов;
  • канатных дорог;
  • лифтовых механизмов.

Конструкция моста:

  1. Две параллельные цепи.
  2. Поперечные соединения.
  3. Деревянные доски как отдельные динамические тела.

Каждая доска соединяется с цепями через шарниры, образуя гибкую платформу.


Производительность

Связанные тела — одна из самых тяжёлых задач для движка.

Факторы нагрузки:

  • количество сегментов;
  • число активных контактов;
  • число итераций решателя;
  • включённые коллизии.

Оптимизация достигается:

  • снижением количества сегментов;
  • отключением внутренних столкновений;
  • уменьшением плотности объектов;
  • использованием статических тел там, где возможно.

Визуализация

Oimo.js отвечает только за физику. Отрисовка выполняется через сторонний рендерер, например Three.js.

Каждому сегменту физического тела соответствует визуальный меш. В цикле обновления:

mesh.position.copy(body.getPosition());
mesh.quaternion.copy(body.getQuaternion());

Физическая модель и графическая сцена должны синхронизироваться на каждом шаге симуляции.


Альтернативный подход: канат без жёстких тел

Иногда вместо множества тел используется:

  • один DistanceJoint между двумя точками;
  • визуальная интерполяция кривой Безье;
  • отсутствие физической симуляции промежуточных сегментов.

Преимущества:

  • высокая производительность;
  • минимальные вычисления.

Недостаток — отсутствие реальной физики провисания и столкновений.


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

  • Для короткой верёвки достаточно 8–12 сегментов.
  • Для тяжёлых грузов увеличивается число итераций.
  • Для длинных цепей рекомендуется шаг симуляции не более 1/60 секунды.
  • Угловые ограничения предотвращают хаотическое вращение.
  • Небольшое демпфирование значительно повышает устойчивость системы.

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