Який найкращий спосіб вирішити одночасні зіткнення у фізичному двигуні?


13

Я пишу 2d двигун фізики в JavaScript, щоб я міг дізнатися більше про фізику у відеоіграх. У мене це правильно працює при жорстких зіткненнях кузова, за винятком випадків, коли якесь тіло стикається з двома або більше іншими тілами одночасно.

В даний час для кожної пари тіл, що стикаються (A, B), я змінюю їх швидкість і кутові швидкості на основі імпульсу зіткнення і виштовхую їх одне від одного, щоб вони не проникали. Але тоді виявлення зіткнення та обчислення імпульсу для інших зіткнень, пов’язаних з A, буде неправильним.

Які підходи я можу дослідити, щоб мої двигун працював над 3+ об'єктами, що стикаються один з одним?


2
Пов’язано: gamedev.stackexchange.com/questions/15836/… та gamedev.stackexchange.com/questions/26181/…, і я впевнений, що є більше, я просто не можу знайти потрібний зараз.
MichaelHouse

Відповіді:


11

Я використовую такий підхід (подібний до алгоритму масового розщеплення Tonge http://www.richardtonge.com/ ):

  • виявити всі пари, що стикаються у вашій сцені / контексті. Нехай (A, B) є такою парою. Застосуйте ідею розбиття примари / маси: якщо A контактує з M тілами, а B контактує з N іншими тілами, тоді тимчасово встановіть масу A на, m_A/Mа B наm_B/N
  • обчислити внески на реакцію / реституцію для кожної пари (A, B) і зберегти ці внески у власних акумуляторах A і B
  • обчислюйте швидкості відновлення з імпульсів (як ви заявили) та зберігайте їх таким же чином (як залишки швидкості deltaV у власних акумуляторах для кожної пари (A, B))
  • обчислити зміщення штрафних санкцій (знову ж таки, накопичуйте переміщення, не застосовуйте їх миттєво!)
    • скинути маси всіх органів, які раніше були визначені сторонами в зіткненнях пар ( m_A = m_A * Mі m_B = m_B * N)

Цей підхід схожий на те, як ітераційний алгоритм Якобі працює з лінійними одночасними системами рівнянь. І це не гарантовано конвергується, але в моєму тренажері це виконує роботу досить гладко .. в 3D (так, додатковий вимір додає вдвічі складніше!).

Caveat : виправляйте положення та швидкості лише після того, як ваша фаза виявлення / керування зіткненням закінчиться! Таким чином ви одночасно оновлюєте своїх учасників, що стикаються. Також сили реституції слід враховувати наступного разу при інтеграції для позицій та швидкостей.

EDIT: Ну, я думаю, ви використовуєте вже зловживали методом інтеграції Verlet (цей став домашньою назвою серед ентузіастів gamedev). У цьому спектрі керування зіткненнями та інтеграції ви можете поглянути тут .

ОНОВЛЕННЯ. Деякі відомості про те, як наблизитись до зіткнення (і самовпевненого з цього приводу), можна знайти в цих документах:

Запропонований мною підхід - це далеко не оригінальний внесок, багато ігор використовують його з правдоподібними результатами, і його найкраще застосував Якобсен у своєму ігровому двигуні Hitman.

З дещо практичного досвіду, штрафні сили (подібні до лінійних або експоненціальних пружин, які отримують свій вхід з відстані проникнення), не вирішують належним чином проникнення, коли інші сили, що стикаються з тіл, що стикаються, встигають бути більшими за них. Ось чому я вирішив поєднати три (майже зайві) підходи: ньютонівські сили реакції (ти відштовхуєш стіну, стіна відштовхується назад), швидкість походження імпульсу (стикаються кулі снукера) та неприродне "переміщення тіл один від одного геометрично "рішення. Вони, схоже, забезпечують все: позбудуться більшостіпотворні артефакти взаємопроникнення, що стикаються тіла, як правило, взаємодіють один з одним у довгостроковій перспективі (через швидкість і сили реституції - принаймні сили, що мали тенденцію перетягувати тіла за сценарієм зіткнення, скасовуються, а тіла відштовхуються одне від одного) . Нарешті, для подальшого розуміння цих простих, але поширених понять, пропоную проаналізувати ці слайди .

Мій епітет "зловживаного методу", що описує кроки інтеграції Верле, орієнтований на переконання популярної культури, що це Святий Грааль методів інтеграції. Він просто незначно кращий, ніж його симплектичний Ойлер (його також називають якийсь напівзрозумілий Ейлер) двоюрідний брат. Існують способи більш складних методів інтеграції (і всі вони мають імпліцитну назву). Потужні ігрові двигуни використовують їх, але інді-розробники не встигають експериментувати з тими, оскільки Verlet, налаштований на конкретний сценарій, справді творить чудеса. Крім того, немає абсолютно ніякого методу інтеграції, який би міг вирішувати жорсткі обмеження, не залучаючи жодного обману (не можу знайти посилання, але документ, про який я посилаюся, повинен називатися "X.Provot -" Деформаційні обмеження в масі -спрінг-модель для опису жорсткої поведінки тканини "


Дякую (+1)! Що таке "швидкість реституції" та "переміщення штрафних санкцій"? Крім того, чому ви кажете, що інтеграція верлетів "зловживається"? Як ви вважаєте, це поганий метод використання?
Cam

Швидкість відновлення - це саме ті швидкості, які ви отримуєте від імпульсів. Єдина відмінність полягає в тому, що я обчислюю їх як залишки (тобто я зберігаю різницю між цією швидкістю, заснованою на імпульсі, і швидкістю струму, зберігаючи поточну швидкість недоторканою для подальших обчислень). Зміщення покарань - це вектори, довжина яких визначається тим, наскільки два об'єкта проникають, і саме вектор мінімальної довжини може перевести один об'єкт повністю за межі іншого. Я зазвичай додаю таке зміщення до кожного об'єкта, розділяючи довжину на 2).
теодрон

1
Блискуча відповідь! У мене є ще одне питання. Скажіть, я накопичую швидкість реституції, чи не вони складуть дуже нереалістичну кількість? Якщо я розглядаю кожне зіткнення з об'єктом A окремо і просто додаю ефекти на кожен об'єкт, чи не буде A імпульс поширюватися між об'єктами? Натомість до кожного буде застосований повний імпульс, який інтуїтивно мені здається неправильним
Cam

Це дуже гарне запитання .. З одного боку, це видається правдоподібним для імпульсів, що додатково сприяють швидкості, що виникає. Ось моє (можливо, несправне!) Міркування: уявіть, що три кулі в пул / снукер стикаються. Один з них повинен отримувати внески від двох інших за цією добавкою. Спочатку я думав зважити ці внески і обчислити середньозважену для кінцевої швидкості, але оскільки хотів швидких результатів, я пропустив цю ідею. Загалом, куля, що стикається, повинен отримати внесок у швидкість від двох інших. Можливо, може допомогти підручник з середньої школи.
теодрон

3
Можливо, я не розумію, що ви пояснили, тому що наступний приклад мене все ж стосується: Розгляньте горизонтально-довгий прямокутник, що падає прямо вниз, і припустимо, підлога зазубрувана (так складається з декількох трикутників набік). Якщо є n трикутників, використовуючи ваш накопичувальний метод, прямокутник буде відскакувати назад в п ять разів швидше, ніж слід! Як можна виправити таку ситуацію?
Cam

1

Я пропоную, замість того, щоб змінювати швидкість, ви міняєте сили, що діють на об’єкт. Не «висувайте» їх, скоріше, робіть це плавно і використовуючи вже наявний код. Роблячи це, тіла не зможуть негайно (і швидко, я думаю) змінювати свої швидкості.

Ознайомтеся з прикладом Box2DJS: http://box2d-js.sourceforge.net/index2.html .


-1

Я аналітично вирішив рівняння імпульсів для груп тіл, що стикаються. Єдиною проблемою, з якою я стикався, було відсутність змінних, щоб знайти відносну силу взаємодії між контактами в групі, яку я заповнив глибиною перетину тіл.

Рішення для групових контактів не набагато складніше, ніж для одного контакту. На жаль, я втратив папір із розрахунками, тому не можу поділитися ним тут.

Редагувати: Напевно, я придумав щось подібне /physics/296767/multiple-colliding-balls

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.