Разрешить столкновение с силами

14

В моем 2D физическом движке я могу обнаружить столкновения AABB и AABB и разрешить их, найдя кратчайший вектор проникновения и добавив его в позицию AABB.

Выполнение этого «выталкивает» первую AABB за пределы второй AABB, но вообще не имеет дело с изменениями скорости / ускорения.

Если я добавлю ускорение силы тяжести в моё моделирование, скорость первой динамической AABB будет продолжать расти, даже когда она лежит поверх второй статической AABB. В конце концов, скорость станет слишком большой, и столкновение не будет обнаружено (динамическая AABB провалится через статическую).

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

Я читал в Интернете, что разрешение столкновений путем ручной работы над положением или скоростью не является правильным. Я попытался реализовать силы (масса - «жестко закодированная» 1 на данный момент):

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 основан на импульсах, он работает на скоростях напрямую, он может быть не «правильным», но он достаточно хорош. Работа с изменениями скорости в импульсном двигателе очень проста, поэтому вы можете указать, хотите ли вы определенно решение, основанное на силе, или достаточно простое решение, основанное на импульсах.
13
Лично я бы предложил взять книгу по физическим движкам, хотя бы прочитать первые несколько глав по ньютоновской физике. Ваши предположения неверны, и попытка ответить на этот вопрос будет означать необходимость обучения основам физики при попытке объяснить алгоритмы высокого уровня для решения столкновений.
2013 года
@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 провалится через статическую).

Что в действительности должно произойти, так это сила ускорения, которая движется в противоположном направлении, поскольку гравитация должна нейтрализовать гравитацию. (Это называется нормальной контактной силой). Суть в том, чтобы просто не применять гравитацию к телам, которые не находятся в воздухе:

  • Один из способов сделать это - сохранить «заземленное» состояние:
    • Не наносите гравитацию на предметы в заземленном состоянии.
    • Если объект сталкивается с объектом снизу и его скорость очень мала, он переходит в заземленное состояние.
    • Объект выходит из заземленного состояния, когда его вертикальная скорость превышает определенное положительное значение.

Обновить:

  • С точки зрения непрофессионала, ньютоновская физика говорит, что полная энергия до и после столкновения должна совпадать. Когда два объекта сталкиваются друг с другом, их энергия перераспределяется. Энергия - это сочетание скорости и веса: более тяжелые и быстрые вещи обладают большей энергией. Это интуитивно понятно. Однако, что не является интуитивным, так это то, как веса влияют на перераспределение энергии.
  • Обмен скоростями является сокращением только для двух динамических нефиксированных тел, имеющих одинаковую массу (статические неподвижные объекты имеют очень большие бесконечные массы).
  • Сочетание, когда одно статическое тело зафиксировано: другое динамическое, нефиксированное тело сохраняет ту же скорость; изменяется только угол (представьте себе бильярдный стол, когда мяч ударяется о рельс. Рельс по существу имеет очень большую бесконечную массу).
  • Для других случаев, таких как три или более объектов, должны быть решены полные уравнения движения Ньютона (сохранение импульса и сохранение кинетической энергии).
  • Я не уверен, могут ли уравнения Ньютона для движения быть решены для более чем двух тел. К счастью, однако, три объекта почти никогда не сталкиваются в одно и то же время. Достаточно обработать первые два тела, которые сталкиваются, а затем обрабатывать любые последующие столкновения, используя новые скорости из предыдущих разрешений столкновения. Это хорошая причина, чтобы ваши физические временные шаги были как можно меньше и обрабатывать столкновения до того, как произойдет какое-либо проникновение.
  • В моей демонстрации астероидов вы увидите, что многие тела создаются, когда большие камни делятся на более мелкие. Тем не менее, я всегда обрабатываю столкновения между парами тел; никогда явно не обрабатывать столкновения с более чем двумя телами.
Leftium
источник
Спасибо за подробный ответ. Хотя есть кое-что, чего я не понимаю: обмен скоростями хорошо работает при столкновении с двумя телами - однако, я не вижу, как это может работать, когда несколько тел (а также статические тела) сталкиваются одновременно. Даже без гравитации, когда динамическое тело сталкивается одновременно со статическим телом, а другое динамическое тело вызывает проблемы. Поскольку скорость меняется, все зависит от порядка столкновения. Если статическое тело столкнется последним, тело перестанет двигаться. Если динамический, тело снова будет двигаться. Как это исправить?
Витторио Ромео
@Vee: Хорошие вопросы! Три + тела и статические тела - это две разные проблемы. Я обратился к обоим в обновлении. Резюме: обрабатывать столкновения двух объектов одновременно; статические тела имеют очень большую бесконечную массу.
Leftium
Ваша модель для отдыха контактов странная. Отдыхающие контакты не только для гравитации, они должны работать для любой силы. Самый простой способ, который работает, это просто удалить скорость, полученную благодаря ускорению в предыдущем кадре, при контакте. Также для малых скоростей вы можете полностью удалить реституцию, хотя ваши вычисления не учитывают реституцию. Этот подход работает для всех сил, он прост в реализации и выглядит достаточно хорошо.
Дрета
16

Решение этой проблемы требует корректировки положения и, возможно, скорости. У двигателей физики твердого тела есть решатель, который продвигает объекты во времени, используя законы движения Ньютона, а также решает проблемы непроникания и трения. Эти двигатели могут вычислить правильную комбинацию линейного и углового движения для создания вероятных траекторий.

Если вы хотите разрешить только перекрытие, вы можете использовать псевдоскорости, которые генерируют разделяющие траектории без добавления импульса. Это делается в решателе положения Box2D.

Я рекомендую получать мои презентации GDC с 2006 и 2007 здесь:

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

Кроме того, вы можете взглянуть на Box2D Lite для упрощенной реализации.

Эрин Катто
источник
+1 за замечание о необходимости корректировать положение. Мало кто потворствует этому, но, чтобы добавить к стабильности симуляции, большинство двигателей обманывают, регулируя положения напрямую. В общем, если это правдоподобно, это работает для игр.
Теодрон
Спасибо за ответ. Я хотел знать кое-что, что я, вероятно, пропустил в презентации: обрабатываются ли статические тела особым образом в Box2D? Я имею в виду - что происходит, когда динамическое тело ударяет в статическое тело?
Витторио Ромео
2

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

В реальном мире нет силы, которая «выталкивает» одно тело за пределы другого, потому что объекты никогда не проникают друг в друга. Самая близкая вещь - нормальная сила : созданная в момент контакта в реальных столкновениях, она предотвращает проникновение в первую очередь.

Угол этой нормальной силы перпендикулярен поверхности контакта двух сталкивающихся объектов. Величина зависит от того, сколько сил необходимо для предотвращения проникновения. (Обратите внимание, что следует использовать только компонент y нормальной силы, если только другие силы, такие как сила трения, также не смоделированы).

Хотя можно явно моделировать нормальную силу, проще моделировать только ее эффекты:

  1. Предотвратить пересечение объекта:
    • Регулировка скоростей путем разрешения столкновений в момент удара. (Лучший)
    • Вручную настраивая положения тел, чтобы они не пересекались. (проще) Вы уже делаете это «находя кратчайший вектор проникновения и добавляя его к позиции AABB».
  2. Не применяйте гравитацию там, где была бы нормальная сила, нейтрализующая гравитационную силу.
    • Объект, соприкасающийся с другим объектом под ним, подвергается воздействию нормальной силы. Таким образом, это вопрос отслеживания этих объектов. (На самом деле к любым объектам, которые находятся в контакте, должна быть приложена нормальная сила, но не все из них будут иметь общий эффект в отношении силы тяжести.)
    • Если вы хотите добавить объекты, которые могут скользить вниз по другим объектам, находящимся под углом, вам нужно будет добавить силу трения и компонент x нормальной силы.

Я описал это немного иначе в своем другом ответе, который больше касается столкновений в целом .

Leftium
источник