Перекрытие тел в двумерном физическом моделировании (Java) - PullRequest
1 голос
/ 27 января 2012

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

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

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

Я думаю, что проблема возникает потому, что, если окружность окружена, она может получить обновленную скорость в окружности позади нее, в то время как окружность позади нее также получает обновленную скорость в прежнюю окружность. Другими словами, двум кругам говорят двигаться навстречу друг другу, даже если они уже соприкасаются. Как только они перекрываются таким образом, я не знаю, почему они не отменяют свое перекрытие.

Я попытался восстановить сценарий касания, если они перекрываются, находя расстояние, на которое они перекрываются, а затем раздвигая их друг от друга; каждый перемещается на половину расстояния перекрытия. Это не меняет скорость круга, только его положение.

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

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

Дополнительная информация:

Гравитация не учитывается при расчете новых скоростей после столкновения.

1 Ответ

4 голосов
/ 27 января 2012

Похоже, ваши догадки о том, что является причиной проблемы, верны в обоих случаях.

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

Трудно написать хороший физический движок, есть веская причина, что на рынке есть много учебников по этому предмету!

Дешевое «решение» вашей проблемы - сократить интервал обновления - например, вместо обновления физики с шагом 33 мс (~ 30 кадр / с), попробуйте обновить с шагом 16 мс (~ 60 кадр / с). Это не предотвратит проблему, но уменьшит вероятность ее возникновения. Сокращение вдвое временного шага также удвоит время, которое процессор должен тратить на обновление физики!

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

ОБНОВЛЕНИЕ: немного больше информации о «правильном» подходе.

Обновление будет выглядеть примерно так:

  1. Начать обновление фрейма. Допустим, мы хотим обновить до времени tF.
  2. Для каждой пары кругов работайте, когда вы ожидаете столкновения (игнорируя все остальные круги). Давайте назовем это время tC.
  3. Найдите наименьшее значение tC. Скажем, это для столкновения между кругами A и B, и давайте назовем это столкновение cAB.
  4. Если tC <= <code>tF, обновите все кружки до времени tC. В противном случае перейдите к шагу 6. ​​
  5. Разрешить столкновение cAB. Вернитесь к шагу 2!
  6. Обновить все круги до времени tF.

Как вы можете себе представить, это может быть довольно сложно. Шаг 2 может быть довольно сложным (и дорогостоящим в вычислительном отношении) для некруглых объектов (особенно когда вы включаете такие вещи, как момент импульса и т. Д.), Хотя здесь есть много хитростей, которые можно сделать для его ускорения. Также в принципе невозможно узнать, сколько раз вы будете выполнять цикл между шагами 2 и 5.

Как я уже сказал, делать хорошее физическое моделирование сложно. Делать это в режиме реального времени еще сложнее!

...