Как исправить «всплывающие» или дрожащие объекты в физическом движке?

11

У меня есть простой физический движок, который решает столкновения, просто исправляя положение перекрывающихся тел (пока просто кругов), а не просто изменяя скорость или применяя импульс. Скорость изменяется только после того, как воздействия уже разрешены, или во время части интеграции.

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

Я хотел исправить это, отсортировав объекты по их y-координате, чтобы столкновения разрешались снизу вверх. Но теперь, движок показывает странное поведение высовывания для объектов, которые на самом деле должны быть в состоянии покоя (см. Рисунок)

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

Не просто предоставив вам исходный код - что бы это могло быть?

TravisG
источник
5
В общем, это похоже на итеративное решение линейной системы уравнений (или нелинейной системы, в зависимости от ваших ограничений / условий / и т. Д.). В любом случае, вы видите эти артефакты, потому что они численно правильны: промежуточные состояния сходящегося процесса. Избежать этого довольно сложно и может повлечь за собой множество неприятных хаков (во всяком случае, это происходит в реальной жизни, на молекулярном уровне, и это то, что у вас есть, чтобы лучше всего походить на что-то в реальной жизни :)). Вероятно, стоит изучить box2d, чтобы увидеть их решение для импульсной динамики.
Теодрон
@TravisG как ты решил проблему? Я смотрю на похожую проблему, пытаясь реализовать очень простой физический движок.
говорит cheesus прекратить стрельбу модов 12.12.13
1
@cheeesus Прошло много времени с тех пор, как я работал над этим, но я думаю, что я просто использовал больше итераций с меньшими временными шагами.
TravisG

Ответы:

5

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

doPhysics();

int num_iterations = 5;
for(int iteration=0; iteration<num_iterations; ++iteration)
{
    float strength = float(iteration+1)/num_iterations;
    correctPositions(strength);
}

Таким образом, первая итерация имеет силу 1 / num_iterations, а последняя имеет силу 1. Это делает мои моделирования более плавными и стабильными, чем простое использование одного и того же числа итераций с фиксированной силой.

DaleyPaley
источник
2
Хорошее решение, но почему оно работает?
Густаво
5

Ваша проблема заключается в том, что у вас нет «состояния покоя» для вашего тела. Любая физическая система обладает количеством энергии, будь то кинетическая, тепловая и так далее. В действительности твердый объект слегка деформируется и преобразует некоторую кинетическую энергию в тепло, хотя это едва ли измеримо. Также стоит отметить, что на самом деле не существует такого понятия, как абсолютно твердый объект. Даже плотные материалы, такие как алмаз, имеют пространство между атомами, давая возможность структуре атома сгибаться и поглощать кинетическую энергию.

Чтобы сделать это соответствующим, покоящиеся тела находятся в состоянии, в котором единственными действующими силами является «нормальная сила», то есть сила, которая препятствует движению тел сквозь друг друга. Величина этой нормальной силы пропорциональна плотности объектов и тому, как далеко они проникли друг в друга.

Физические движки называют это значение «отстой».

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

Ян Янг
источник
0

Почему бы не добавить к ним «липкую» поверхность, чтобы они постепенно прилипали к положению покоя, и когда другой объект ударяется о него, он передает в него некоторую энергию, заставляя его двигаться, но липкая поверхность заставит его потерять часть этой энергии и остановить в состоянии покоя. GIF выглядит так, как будто у него нет трения.

скоро
источник