Вирішення зіткнення з силами


14

У своєму двигуні 2D фізики я можу виявити зіткнення AABB проти AABB і вирішити їх, знайшовши найкоротший вектор проникнення і додавши його до положення AABB.

Це "виштовхує" перший AABB за межами другого AABB, але зовсім не займається змінами швидкості / прискорення.

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

Я спробував встановити швидкість до нуля після роздільної здатності, але це, очевидно, не спрацювало добре, і створив нереальні симуляції.

Я читав в Інтернеті, що розв'язання зіткнень шляхом ручної роботи в положенні або швидкості не є правильним. Я спробував реалізувати сили (маса зараз є «жорстким кодом»):

void Body::applyForce(sf::Vector2f mForce) { acceleration += mForce; }

void Body::integrate(float mFrameTime)
{
    velocity += acceleration * mFrameTime;
    position += velocity * mFrameTime;

    acceleration = {0, 0};
}

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

Чи є спосіб застосувати "тимчасову" силу? Сила, яка займається виштовхуванням першого AABB з другого AABB, потім зупиняється, коли AABB більше не стикається?

Весь вихідний код доступний тут: https://github.com/SuperV1234/SSVSCollision


1
Мене це цікавить. Ви ще придумали рішення?
TravisG

@TravisG: ще немає, на жаль. Я завтра додам щедрості, якщо не отримаю жодної відповіді.
Вітторіо Ромео

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

Особисто я б запропонував взяти книгу про двигуни фізики, принаймні прочитати перші кілька розділів з фізики Ньютона. Ваші припущення невірні, а спроба відповісти на це запитання означатиме необхідність навчити вас основ фізики, намагаючись пояснити алгоритми високого рівня для вирішення зіткнень.
дрета

@dreta його припущення прекрасні. Він зазначив, що його маса для всіх об'єктів наразі просто "1", що робить його розділи коду дійсними. До речі, навіть незважаючи на те, що Box2D може працювати безпосередньо зі швидкістю, він якось повинен мати справу з тією ж проблемою. Якщо замість прикладання сили Box2D застосовує імпульс, він якось повинен мати справу з тим, що імпульс не просто відходить, як тільки об'єкти відокремлюються. Хоча, можливо, він насправді цим не займається і просто дає об'єктам зберегти свою енергію (все-таки це було б у реальному світі)
TravisG

Відповіді:


13

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


Для швидкого моделювання більш точного дозволу зіткнення двох об'єктів A і B:

  1. Знайдіть позиції безпосередньо перед зіткненням. Ви вже наближаєте це, "знайшовши найкоротший вектор проникнення і додавши його до положення AABB".
  2. Знайдіть швидкості відразу після зіткнення за допомогою ньютонівської фізики :
    • У випадку, коли маса жорстко кодована як 1, просто поміняйте швидкості (це не стосується статичних об'єктів, які повинні мати нескінченну масу):
      • Av = Bu
      • Bv = Au
    • Якщо об'єкти A і B мають різні маси:
      • Av = (Au * (Am - Bm) + (2 * Bm * Bu)) / (Am + Bm)
      • Bv = (Bu * (Bm - Am) + (2 * Am * Au)) / (Am + Bm)
    • де:
      • v: швидкість після зіткнення
      • u: швидкість перед зіткненням
      • m: маса (використовуйте найбільшу кількість можливих для маси нерухомого статичного об'єкта)
  3. Встановіть прискорення на 0: Прискорення від зіткнення було враховано вище розрахунками швидкості на кроці №2.

Погляньте, будь ласка, на мою зразок програми астероїдів, яка демонструє ці поняття.


Далі, обліковий запис для складених об'єктів:

Як ви зазначали, використання швидкості для імітації об'єктів, що складаються / відпочивають, не працює добре: швидкість - це швидкість руху об'єкта, тому, якщо він опирається на статичний об'єкт, швидкість повинна бути близькою до 0. Не має сенсу збільшувати швидкість об’єкта, щоб він з'явився в спокої:

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

Що насправді має відбутися, це сила прискорення, яка рухається у зворотному напрямку, оскільки гравітація повинна скасувати гравітацію. (Це називається нормальною контактною силою). Ярлик - це просто не застосовувати гравітацію до тіл, які не знаходяться у повітрі:

  • Один із способів зробити це шляхом збереження "заземленого" стану:
    • Не застосовуйте гравітацію до предметів у заземленому стані.
    • Якщо об'єкт стикається з об'єктом знизу і його швидкість дуже мала, він переходить у заземлений стан.
    • Об'єкт виходить із заземленого стану, коли його вертикальна швидкість перевищує певне позитивне значення.

Оновлення:

  • З точки зору мирян, фізика Ньютона говорить, що загальна енергія до та після зіткнення повинна відповідати. Коли два об’єкти врізаються один в одного, їх енергія перерозподіляється. Енергія - це поєднання швидкості та ваги: ​​важчі, швидші речі мають більше енергії. Це інтуїтивно. Однак, що не інтуїтивно зрозуміло, це саме те, як ваги впливають на перерозподіл енергії.
  • Швидкості обміну - це ярлик лише для двох динамічних, нефіксованих тіл, які мають однакову масу (статичні, нерухомі об'єкти мають дуже великі, нескінченні маси).
  • Ярлик, коли фіксується одне статичне тіло: інший динамічний, нефіксований корпус зберігає однакову швидкість; змінюється лише кут (уявіть більярдний стіл, коли куля потрапляє в рейки. Поруч по суті має дуже велику, нескінченну масу).
  • В інших випадках, як три або більше об'єктів, повинні бути вирішені повні рівняння ньютонівського руху (збереження імпульсу та збереження кінетичної енергії).
  • Я не впевнений, чи можна розв’язувати рівняння ньютонівського руху для більш ніж двох тіл. На щастя, однак, три об’єкти майже ніколи не стикаються в той самий час. Досить обробити перші два тіла, що стикаються, а потім обробити будь-які наступні зіткнення, використовуючи нові швидкості попередніх дозволів зіткнення. Це хороший привід, щоб утримувати часові кроки з фізики якомога менше і впоратися зіткненнями до того, як трапляться будь-які проникнення.
  • Ви помітите в моїй демонстрації астероїдів багато тіл створені, як більші скелі розбиті на менші. Однак я завжди керуюсь зіткненнями між парами тіл; ніколи прямо не керуючись зіткненням з більш ніж двома тілами.

Дякуємо за детальну відповідь. Щось я не розумію, хоча швидкість заміни працює добре при зіткненні з двома тілами - однак, я не бачу, як це може працювати, коли множина тіл (а також статичні тіла) стикаються одночасно. Навіть без тяжкості, коли динамічне тіло стикається одночасно зі статичним тілом, а інше динамічне тіло викликає проблеми. Оскільки швидкість змінюється, все залежить від порядку зіткнення. Якщо статичне тіло зіткнеться останнім, воно перестане рухатися. Якщо динамічний - тіло знову рухатиметься. Як це виправлено?
Вітторіо Ромео

@Vee: Хороші запитання! Три + тіла та статичні тіла - це два окремих питання. Я звернувся до обох у оновленнях. Короткий зміст: керуйте зіткненнями двох об'єктів одночасно; статичні тіла мають дуже велику, нескінченну масу.
Лефтій

Ваша модель для відпочинку контактів дивна. Відпочиваючі контакти - це не лише сила тяжіння, вони повинні працювати на будь-яку силу. Найпростіший спосіб роботи - це просто зняти швидкість, отриману завдяки прискоренню в попередньому кадрі при контакті. Крім того, для невеликих швидкостей ви можете видалити реституцію повністю, хоча ваші розрахунки не враховують реституцію. Такий підхід працює на всі сили, його легко здійснити і виглядає досить добре.
дрета

16

Вирішення цієї проблеми вимагає регулювання положення та, можливо, швидкості. Двигуни фізики твердих тіл мають вирішувач, який рухається по об'єктах уперед за часом, використовуючи закони руху Ньютона, одночасно вирішуючи обмеження проникнення та тертя. Ці двигуни можуть обчислити правильне поєднання лінійного та кутового руху для створення правдоподібних траєкторій.

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

Я рекомендую отримати свої GDC-презентації 2006 та 2007 років тут:

http://code.google.com/p/box2d/downloads/list

Також ви можете подивитися на Box2D Lite для спрощеної реалізації.


+1 за зауваження про необхідність коригування позиції. Мало хто балується цим, але для додання стабільності імітації більшість двигунів обманюють, регулюючи положення безпосередньо. Загалом, якщо це правдоподібно, він працює для ігор.
теодрон

Дякую за відповідь. Мені хотілося дізнатись щось, що я, мабуть, пропустив у презентації: чи статичні тіла обробляються особливим чином у Box2D? Я маю на увазі - що відбувається, коли динамічне тіло потрапляє у статичне тіло?
Вітторіо Ромео

2

введіть тут опис зображення

У реальному світі не існує сили, яка «виштовхує» одне тіло поза іншого тіла, оскільки предмети ніколи не проникають одне в одне. Найближче - нормальна сила : створена в момент контакту в зіткненнях реального світу, вона перешкоджає в першу чергу проникненню.

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

Хоча можна чітко моделювати нормальну силу, простіше моделювати лише її ефекти:

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

Я описав це дещо інакше в іншій своїй відповіді, яка стосується загалом колізій .

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