Симуляция тряпичной куклы

Тряпичная кукла (ragdoll) — это составная физическая модель персонажа, состоящая из набора твёрдых тел, соединённых ограничениями (joints). В библиотеке Oimo.js такая модель строится на основе:

  • RigidBody — отдельных физических тел;
  • Shape — геометрии коллизий;
  • Joint — ограничений между телами;
  • World — физического мира, управляющего шагом симуляции.

Ключевая идея — разложение персонажа на сегменты (голова, туловище, плечи, предплечья, бедра, голени), каждый из которых является отдельным динамическим телом. Суставы моделируются шарнирными соединениями с угловыми ограничениями.


Создание физического мира

Перед построением куклы инициализируется физический мир:

const world = new OIMO.World({
    timestep: 1 / 60,
    iterations: 8,
    broadphase: 2,
    worldscale: 1,
    random: true,
    info: false,
    gravity: [0, -9.8, 0]
});

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

  • timestep — шаг симуляции;
  • iterations — количество итераций решателя ограничений;
  • gravity — вектор гравитации.

Для стабильной тряпичной куклы важно увеличить iterations (например, 8–12), чтобы суставы не “разваливались” под нагрузкой.


Представление сегментов тела

Каждый сегмент реализуется как динамическое тело:

function createBody(size, position) {
    return world.add({
        type: "box",
        size: size,
        pos: position,
        move: true,
        density: 1,
        friction: 0.4,
        restitution: 0.1
    });
}

Пример структуры куклы

const torso = createBody([0.5, 1.0, 0.3], [0, 5, 0]);
const head = createBody([0.4, 0.4, 0.4], [0, 6.2, 0]);

const leftUpperArm = createBody([0.3, 0.6, 0.3], [-0.7, 5.5, 0]);
const leftLowerArm = createBody([0.25, 0.6, 0.25], [-0.7, 4.7, 0]);

const rightUpperArm = createBody([0.3, 0.6, 0.3], [0.7, 5.5, 0]);
const rightLowerArm = createBody([0.25, 0.6, 0.25], [0.7, 4.7, 0]);

Баланс масс

Для реалистичной физики:

  • Туловище должно иметь большую массу.
  • Голова — меньшую.
  • Конечности — среднюю.

Это регулируется параметром density или напрямую через mass.


Соединения суставов

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

  • BallJoint — шарнир с вращением во всех направлениях;
  • HingeJoint — шарнир с одной осью вращения;
  • DistanceJoint — фиксированное расстояние между точками.

Пример шарового сустава (плечо)

world.add({
    type: "jointBall",
    body1: torso,
    body2: leftUpperArm,
    pos1: [-0.4, 0.4, 0],
    pos2: [0, 0.3, 0],
    collision: false
});

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

Для реалистичности движения добавляются лимиты:

world.add({
    type: "jointHinge",
    body1: leftUpperArm,
    body2: leftLowerArm,
    axe1: [1, 0, 0],
    axe2: [1, 0, 0],
    pos1: [0, -0.3, 0],
    pos2: [0, 0.3, 0],
    min: -90,
    max: 0,
    collision: false
});

min и max задают диапазон вращения (в градусах).


Иерархия соединений

Полная тряпичная кукла включает:

  • Голова ↔︎ Туловище (BallJoint)
  • Плечо ↔︎ Верхняя рука (BallJoint)
  • Локоть ↔︎ Предплечье (HingeJoint)
  • Таз ↔︎ Бедро (BallJoint)
  • Колено ↔︎ Голень (HingeJoint)

Каждый сустав должен иметь:

  • Точную точку крепления;
  • Отключённую коллизию между связанными телами (collision: false);
  • Ограничение вращения.

Стабилизация симуляции

Тряпичная кукла подвержена нестабильности. Основные методы стабилизации:

1. Увеличение количества итераций

iterations: 12

2. Ограничение максимальной скорости

body.linearVelocity.limit(10);
body.angularVelocity.limit(10);

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

body.linearDamping = 0.1;
body.angularDamping = 0.1;

Демпфирование снижает дрожание суставов.


Интеграция с Three.js

Чаще всего визуализация выполняется через Three.js.

После каждого шага симуляции:

world.step();

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

Физика полностью управляет положением и ориентацией мешей.


Падение и реакция на столкновения

При создании пола:

world.add({
    type: "box",
    size: [20, 1, 20],
    pos: [0, -0.5, 0],
    move: false
});

Кукла падает под действием гравитации и взаимодействует с поверхностью.

Для более реалистичного поведения:

  • Увеличивается трение (friction);
  • Уменьшается упругость (restitution);
  • Настраивается масса туловища.

Принудительное управление куклой

Тряпичная кукла может получать внешние импульсы:

torso.applyImpulse([0, 5, 0], [0, 0, 0]);

Или силы:

torso.applyForce([10, 0, 0], [0, 0, 0]);

Это используется для:

  • Реакции на выстрелы;
  • Взрывов;
  • Перехода из анимационного состояния в физическое.

Переход от анимации к ragdoll

Гибридная схема:

  1. Персонаж управляется скелетной анимацией.
  2. При событии (например, смерти) отключается управление.
  3. Кости сопоставляются с физическими телами.
  4. Включается симуляция.

Каждая кость имеет соответствующий RigidBody. После активации физики кости начинают копировать трансформации тел.


Настройка анатомических ограничений

Для правдоподобности:

  • Колени — только сгибание вперёд.
  • Локти — ограниченный диапазон.
  • Шея — небольшой угол поворота.
  • Бёдра — широкий диапазон.

Пример ограничения бедра:

min: -45,
max: 45

Неверные диапазоны приводят к неестественным позам.


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

Тряпичная кукла содержит 10–15 тел и 10–14 суставов. При большом количестве персонажей:

  • Уменьшается iterations;
  • Используется спящий режим (sleep);
  • Деактивируются куклы вне зоны видимости.
body.allowSleep = true;

Спящие тела не участвуют в расчётах до получения импульса.


Частые проблемы

Разрыв суставов

Причина: низкое число итераций или слишком большая масса.

Дрожание

Решается увеличением демпфирования и уменьшением timestep.

Взрыв модели при старте

Причина: пересечение коллизионных форм.


Расширенные техники

Capsule вместо Box

Для конечностей лучше использовать капсулы:

type: "capsule"

Это снижает зацепления при падении.

Центр масс

Можно вручную корректировать распределение массы, чтобы кукла падала реалистично.

Дополнительные ограничения

Использование DistanceJoint для стабилизации плечевого пояса.


Полная схема построения

  1. Создание мира.
  2. Создание сегментов тела.
  3. Настройка масс и демпфирования.
  4. Добавление суставов с лимитами.
  5. Отключение коллизий между связанными частями.
  6. Интеграция с визуальной моделью.
  7. Оптимизация и стабилизация.

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