Класика механики твердого тіла – ragdoll фізика представляє персонажа у вигляді дерева жорстких елементів, з’єднаних кутовими суглобами з обмеженнями моменту – точна, але обчислювально складна та схильна до тремтіння при накладених обмеженнях. Ця симуляція замість цього використовує інтеграцію Верле з обмеженнями відстаней, той самий підхід на основі частинок, який популяризував Thomas Jakobsen у своїй GDC-доповіді 2001 року "Advanced Character Physics". Тіло – це просто набір масних точок (голову, плечі, лікті, стегна, коліна, ...), з’єднаних обмеженнями відстаней — жорсткі або частково жорсткі зв'язки, які просто намагаються утримати кожен паралельний зв’язок між двома точками на фіксованій відносній довжині.
Classic rigid-body ragdoll physics represents a character as a tree of rigid segments connected by angular joints with torque limits — accurate, but numerically stiff and prone to jitter under stacked constraints. This simulation instead uses Verlet integration with distance constraints, the same particle-based approach popularised for cloth and rope by Thomas Jakobsen's 2001 GDC paper "Advanced Character Physics." The body is just a set of point masses (head, shoulders, elbows, hips, knees, ...) connected by distance constraints — rigid or semi-rigid links that simply try to hold each connected pair of points at a fixed rest length.
Інтеграція Верлет без зберігання швидкості
Кожна точка рухається під інтеграцією Верлет: замість відстеження положення та швидкості окремо, вона зберігає поточне положення та попереднє положення, та виводить швидкість за їхньою різницею.
Положення (Верлет) — без явного визначення швидкості xNext = x + (x - xPrev) * гальмування + прискорення * dt * dt xPrev = x x = xNext Вивід швидкості здійснюється за допомогою (x - xPrev); обмеження просто переміщує x і "швидкість" автоматично оновлюється на наступному кроці.
Це пояснює, чому інтеграція положення Верлет є стандартним вибором для систем з жорсткими обмеженнями, таких як одяг, мотузки та ляпас-килим, а не методи з явним визначенням швидкості Ейлера або Рунге-Кутта, які використовуються для орбіт в інших частинах цього сайту: розв’язувач обмежень, який повинен задовольняти умову довжини кінцівки або кута суглоба, може просто перемістити точку до правильного положення, а виведена швидкість — (x − xPrev) різниця — автоматично та послідовно оновлюється без необхідності окремого змінної швидкості, щоб синхронізувати її.
// position (Störmer) Verlet — no explicit velocity needed xNext = x + (x - xPrev) * damping + acceleration * dt * dt xPrev = x x = xNext // velocity is implied by (x - xPrev); a constraint just moves x directly // and the "velocity" automatically updates itself next step
Задовільне дотримання обмежень: розслаблення, а не рівняння
Зазвичай ragdoll має десяток або більше обмежень на відстані (верхня рука, передплічя, тулова секція, стегно, гомілка тощо), усі з’єднані спільними суглобами, і точне одночасне їх вирішення є дороговартійною лінійною системою. Підхід Якобсена замість цього використовує ітеративне розслаблення: повторюйте цикл для кожного обмеження та штовхайте кожну пару з’єднаних точок безпосередньо до задоволення власної початкової довжини, ігноруючи всі інші обмеження в цей момент, а потім повторюйте весь прохід кілька разів.
for (let iter = 0; iter < NUM_ITERATIONS; iter++) { for (const c of constraints) { const delta = c.p2.pos.sub(c.p1.pos); const dist = delta.length(); const diff = (dist - c.restLength) / dist; const correction = delta.scale(0.5 * diff); if (!c.p1.pinned) c.p1.pos.addInPlace(correction); if (!c.p2.pinned) c.p2.pos.subInPlace(correction); } } // кожен прохід приблизно задовольняє кожне обмеження; // повторні прогони збігаються до узгодженої пози; Це розв’язувач ітеративного типу Гаусса-Зедель, а не пряме лінійне розв’язання: воно не обчислює математично точне рішення за один прохід, воно наближається до нього асимптотично. Більша кількість ітерацій на кадр робить скелет твердішим і менш еластичним — занадто мало ітерацій призводить до видимої розтяжки довгих ланцюгів кінцівок під навантаженням, що й є причиною, чому перерахунок обмежень є одним з найважливіших регулюючих гвинтів у цьому типу симуляції, безпосередньо обмінюючи візуальну жорсткість на вартість обчислень ЦП.
for (let iter = 0; iter < NUM_ITERATIONS; iter++) {
for (const c of constraints) {
const delta = c.p2.pos.sub(c.p1.pos);
const dist = delta.length();
const diff = (dist - c.restLength) / dist;
const correction = delta.scale(0.5 * diff);
if (!c.p1.pinned) c.p1.pos.addInPlace(correction);
if (!c.p2.pinned) c.p2.pos.subInPlace(correction);
}
}
// each pass only approximately satisfies every constraint;
// repeated passes converge toward a mutually consistent pose
Від дистанційних обмежень до межі суглобів
Просте дистанційне обмеження дозволило б ліктю згинатися назад на 360° без жодного опору, що виглядає неправильно, коли ragdoll падає в нездорову позу. Реалістичні ragdolls додають кутові обмеження поверх дистанційних обмежень — додаткові зв’язки або явні перевірки кутів, які підтримують, наприклад, кут між верхньою та передньою частиною руки в межах анатомічно правдоподібного діапазону — тоді як вони все ще покладаються на той самий ітеративний цикл розслаблення для їх приблизного застосування разом із дистанційними обмеженнями, а не точно вирішують жорстку суглобову ієрархію.
Чому цей підхід домінує в іграх
Позиційно-орієнтовані, з використанням інтегрівки Верлета, системи обмежень (загальна родина тепер часто називається Position Based Dynamics, формалізована Мульцером та іншими у 2007 році) є популярними в реальному часі іграх та інтерактивних демо, через три основні причини: вони безумовно стабільні незалежно від того, наскільки сильно ви тягнете точку, оскільки ви безпосередньо встановлюєте позиції замість інтегрування сил, які можуть призвести до нестабільності; вони простим чином комбінуються з іншими позиційно-орієнтованими типами обмежень (одяг, мотузка, м’які тіла) в одному розв’язувачі; і їх вартість масштабується лінійно та передбачувано з кількістю обмежень та ітерацій, що робить бюджетування продуктивності у реальному часі гри легким – різкий контраст із розв’язувачами жорсткого тіла, які можуть стати чисельно стійкими та нестабільними саме тоді, коли сцена стає цікавою (наприклад, купа ляльок-розтяжок, стопка коробок).
Frequently asked questions
Чому ця симуляція ragdoll не відстежує швидкість безпосередньо?
Вона використовує інтегрування Störmer-Verlet, яке зберігає поточне та попереднє положення замість явно заданої швидкості. Швидкість випливає з різниці між ними, що означає, що розв’язувач обмежень може просто перемістити точку в нове положення, і правильна швидкість на наступному кроці автоматично визначається.
Чому перетягування ragdoll іноді робить його кінцівки розтягнутими?
Розв’язувач обмежень використовує ітеративне релаксацію замість точного одночасного розв’язку — кожен прохід лише частково задовольняє кожну відстатню обмеження. Якщо кількість ітерацій на кадр недостатня, довгі ланцюги з'єднаних точок (наприклад, рука) видимі розтягуються за межі їхнього спокійного положення під час сильного перетягу до того, як розв’язувач зможе наздогнати.
Це одна й та сама техніка, яка використовується в комерційних ігрових движках?
Це та ж сім'я, зазвичай звана Position Based Dynamics (PBD): частинки з обмеженнями відстані та кута, розв’язані шляхом ітеративної релаксації під інтегруванням Verlet. Це популярно особливо тому, що воно безумовно стабільне та легко комбінується з тканиною та мотузками в одному розв’язувачі, на відміну від розв’язувачів жорстких тіл.
Спробуйте наживо
Усе, що вище, працює прямо у вашому браузері — відкрийте Ragdoll Physics і змінюйте параметри під час роботи. Нічого не встановлюється, нічого не завантажується на сервер, уся модель живе в одній вкладці.
▶ Відкрити симуляцію Ragdoll Physics