Metody symulacji fizyki dla dużych czasów delta?

9

Jakie metody symulacji fizyki są najbardziej odpowiednie dla naprawdę dużego czasu delta (od godzin do tygodni)?

Ponadto, czy miałbym jakieś problemy z łączeniem różnych metod dla dużych i małych czasów delta?

fread2281
źródło
1
W dużej mierze zależy to od obszaru docelowego. Trudno coś powiedzieć, nie wiedząc więcej o swoich prawdziwych celach. Zbyt szeroki.
Kromster
To pytanie jest powiązane.
Anko,
Zasadniczo właściwy harmonogram zależy od tego, czego doświadcza gracz. Czy chcesz, aby była dokładna w tygodniowych odstępach czasu i aby gracz mógł z nią współdziałać w czasie rzeczywistym? Jest to o wiele trudniejsze niż zmuszenie go do pracy w skali tygodniowej, której gracz doświadcza wielokrotnie w czasie rzeczywistym ( tj. Jedna sekunda doświadczenia gracza to jeden tydzień czasu rzeczywistego).
mklingen
jeśli symulujesz ruchy chmur lub zmienne termodynamiczne w komórkach o szerokości setek metrów, z dt 10 minut, jest to uzasadnione. ale sztywne ciało w zwykłej skali, nie za dużo. jaka jest aplikacja
v.oddou
Aplikacja jest mechaniką „nadrabiania zaległości”, w której przeprowadzana jest symulacja od ostatniego załadowania (części świata), logika gry opiera się na wywołaniach zwrotnych, w których wywołania zwrotne są licznikami czasu lub wywołaniami kolizji, chcę mieć możliwość uruchomienia fizyki do następnego efektywnie oddzwanianie czasomierza, a symulacja fizyki radzi sobie z oddzwanianiem od kolizji. Kolizje są stosunkowo mało prawdopodobne, ale chciałbym, aby oddzwanianie kolizji miało dostępny stan gry (fizyki) w momencie kolizji.
fread2281,

Odpowiedzi:

5

Prawdopodobnie będziesz używać stałego przyspieszenia dla tych dużych okresów czasu (które może być przyspieszeniem zerowym). Pochodna stałego przyspieszenia względem czasu wynosi 0. Oznacza to, że nie zmienia się w odniesieniu do czasu, więc nie ma znaczenia, jak duży jest twój czas delta.

Ta niewielka integracja w odniesieniu do czasu zapewnia potrzebne równania.

a = a
v = at + v0
s = .5at^2 + v0*t + s0

Gdzie: a = przyspieszenie, v = prędkość, v0 = prędkość początkowa, s = pozycja, s0 = pozycja początkowa, t = czas

Korzystając z tej strategii, możesz użyć przedziałów czasowych od milisekund do tygodni, jeśli chcesz. Ich połączenie zostanie załatwione w parametrach v0i s0równaniu.

Aby poradzić sobie z kolizjami, musisz wdrożyć strategie podobne do tych stosowanych w przypadku małych obiektów o dużej prędkości . Najpierw oblicz nową pozycję za pomocą powyższego równania, a następnie przeciągnij między starą i nową pozycją dla wszystkich obiektów. Ponieważ jeden z tych obiektów mógł się przecinać (kilka minut lub dni wcześniej), może to być bardzo skomplikowane. Jest prawdopodobne, że skoro masz tak duże czasy delta, mam nadzieję, że będziesz miał mnóstwo czasu na przetworzenie tych potencjalnych kolizji.

MichaelHouse
źródło
co z kolizjami?
fread2281,
Zaktualizowałem odpowiedź, aby uwzględnić strategie radzenia sobie z kolizjami.
MichaelHouse
to nieprawda. Wiadomo, że integracja Eulera różni się w przypadku ciągłej integracji, podczas gdy Verlet (lub RK2, RK4) nie.
v.oddou
@ v.oddou Biorąc pod uwagę, że te symulacje dotyczą gier, nie uważam, że wymagana dokładność jest konieczna. Dodatkowa złożoność i trudność dodawania kolizji dla Verlet sprawia, że ​​integracja Euler jest najlepszym wyborem.
MichaelHouse
2

Weźmy przykład z grawitacją.

W poniższej funkcji załóżmy, że mamy zmienne składowe klasy dla pozycji i prędkości. Musimy je aktualizować z powodu siły grawitacji co dt sekund.

void update( float dt )
{
   acceleration = G * m / r^2;
   velocity = velocity + acceleration * dt;
   position = position + velocity * dt;
}

Ponieważ dtstaje się coraz mniejsza, nasza symulacja staje się coraz bardziej dokładna (chociaż jeśli dtstaje się zbyt mała, możemy napotykać błędy precyzji podczas dodawania małych liczb do dużych liczb).

Zasadniczo musisz określić maksimum, jakie dtmoże obsłużyć symulacja, aby uzyskać wystarczająco dobre wyniki. A jeśli to, dtco wchodzi, jest zbyt duże, po prostu podziel symulację na mniejsze kroki, przy czym każdy krok jest maksymalnym dtdozwolonym.

void update( float dt )
{
   acceleration = G * m / r^2;
   velocity = velocity + acceleration * dt;
   position = position + velocity * dt;
}

// this is the function we call. The above function is a helper to this function.
void updateLargeDt( float dt )
{
    const float timeStep = 0.1;
    while( dt > timeStep   )
    {
        update( timeStep  );
        dt -= timeStep ;
    }

    update( dt );  // update with whatever dt is left over from above
}

Tak więc dzięki tej strategii możesz po prostu dostosować się timeStep do dowolnej wierności, której potrzebujesz ( ustaw ją na sekundę, minutę, godzinę lub cokolwiek jest potrzebne, aby uzyskać dokładne odwzorowanie fizyki.

domyślna
źródło
1

Większość gier ma tendencję do korzystania z prostej metody Eulera całkowania do przodu (to znaczy, zintegrowania prędkości z pozycją w czasie i zintegrowania przyspieszenia z prędkością). Niestety metoda Eulera jest odpowiednia tylko w bardzo małych skalach czasowych i krótkich seriach.

Istnieją bardziej złożone metody, które są dokładniejsze w bardzo długich skalach czasowych. Najpopularniejszym i najłatwiejszym do wdrożenia jest być może Runge-Kutte-4 . RK4 określa pozycję w przyszłości, próbkując cztery pozycje i prędkości w przeszłości i interpolując. W dłuższych skalach czasowych jest on znacznie bardziej dokładny niż metoda Eulera, ale jest bardziej kosztowny obliczeniowo.

Na przykład, jeśli chcesz obliczyć fizykę prawdziwej orbitującej planety aktualizowanej co kilka dni w czasie rzeczywistym, metoda Eulera spowoduje, że planeta wystrzeli w przestrzeń kosmiczną po kilku orbitach z powodu błędów numerycznych. RK4 ogólnie utrzymuje planetę na orbicie w przybliżeniu w tym samym kształcie wiele tysięcy razy, zanim zgromadzi zbyt dużo błędów.

Jednak implementowanie kolizji w RK4 może być bardzo trudne ...

Mklingen
źródło