Jak rozwiązać problem penetracji dwóch zderzających się ciał

9

Wdrożyłem prosty silnik fizyki gier 3D. Mam już przyzwoite wykrywanie kolizji, teraz próbuję wymyślić część odpowiedzi na kolizję. Używam metody opartej na impulsach do obliczania prędkości po zderzeniu. Działa to całkiem dobrze, jednak nie całkowicie uniemożliwia ciałom wzajemne przenikanie się. Mam więc dodatkowy fragment kodu, aby rozwiązać problem penetracji. Obecnie po prostu przesuwam ciała wzdłuż kontaktu normalnego o połowę głębokości penetracji - pierwsze ciało w kierunku normalnego kontaktu, drugie ciało w przeciwnym kierunku.

Jest to w porządku przez większość czasu, ale są pewne niepożądane efekty. Na przykład wyobraź sobie wąski korytarz i poruszający się przez niego obiekt. Jeśli obiekt uderza w jedną ze ścian korytarza, rozdzielczość penetracji przenosi go do przeciwległej ściany, a następnie w następnej ramce z powrotem do pierwszej ściany i tak dalej. Efekt jest taki, że obiekt bardzo szybko wibruje między ścianami, co nie jest ładne.

Moje pytanie brzmi więc, czy istnieje lepszy sposób na rozwiązanie problemu penetracji? Być może nie poruszaj ciałami, po prostu dostosuj ich prędkości (oprócz obliczeń impulsowych), aby przestały się zbliżać, a penetracja ustąpi w następnych kilku klatkach. Po prostu zgaduję tutaj. Jakieś pomysły?

Adam
źródło

Odpowiedzi:

3

Po wykryciu kolizji określ czas / punkt, w którym ciała zaczęły kolidować, i traktuj kolizję w tym punkcie. W tym momencie nadal możesz mieć niewielką penetrację do rozwiązania, ale będzie ona znacznie mniejsza i [zwykle] nie spowoduje problemów z oscylacją, które masz.

Powiedzmy, że masz 100 ms kroków symulacji i że w niektórych klatkach masz dwie kule, które zderzają się w połowie (50 ms) z ramką. Po pierwsze, wykryjesz, że zderzyły się one w dowolnym punkcie kadru (co, jak ufam, już robisz skutecznie). Ustalą, w którym momencie podczas zderzenia zderzyli się. Teraz poradzimy sobie z kolizją, w tym z pierwszych 50 ms klatki, w której się nie zderzyły. Teraz będziesz mieć nowe prędkości kulek, a także możesz teraz podjąć kroki, aby upewnić się, że nie są penetrujące (powinny być bardzo małe, ponieważ „po prostu się zdarzyło”). W końcu symulujesz kolejne 50 lat rama. Należy pamiętać, że w tym okresie może równie dobrze dojść do kolejnego zderzenia z jedną lub obiema kulkami.

notlesh
źródło
1
Sugerujesz więc, aby wdrożyć ciągłe wykrywanie kolizji, a następnie obsłużyć penetracje, które pozostały w ten sam sposób, co ja, ponieważ prawdopodobnie będą one bardzo małe. To może działać, jak sądzę. Teraz muszę tylko wymyślić, jak sprawić, by moje wykrywanie kolizji było ciągłe :)
Adam
Nie jestem pewien, co rozumiesz przez ciągłe. Ściśle mówiąc, w symulacji fizyki nie ma niczego ciągłego, ponieważ wszystko jest zawsze podzielone na pewne dyskretne kroki. Robienie mniejszych kroków, co w zasadzie sugeruję, przyniesie znacznie mniejsze (i łatwiejsze do poprawienia) błędy. Innym sposobem myślenia na ten temat jest bezpośredni związek między wielkością kroku a błędami (takimi jak penetracja). Kiedy więc wykryjesz taki błąd, podziel go na mniejsze kroki, aż błąd będzie można w prosty sposób naprawić.
notlesh
Ciągłe wykrywanie kolizji oznacza, że ​​zamiast sprawdzania przecięcia między dwoma statycznymi obiektami (problem 3d), sprawdzasz kontakt dwóch ruchomych obiektów (w zasadzie problem 4d). Zwykle wystarczy wziąć pod uwagę tylko stałe prędkości, ponieważ można przybliżać trajektorie za pomocą częściowych krzywych liniowych. Zaletą jest to, że odległość penetracji będzie zawsze wynosić zero (lub blisko, z powodu błędów zaokrąglania liczby zmiennoprzecinkowej). Myślałem, że o tym mówisz, ale może źle zinterpretowałem twoją odpowiedź?
Adam
@adam Tak, właśnie o tym mówię.
notlesh
2

Sprawdź ten artykuł - który został tu opublikowany wiele razy, po prostu przeszukaj pytania i odpowiedzi dotyczące wykrywania kolizji - pokazuje, jak wykonać „ciągłą” rozdzielczość kolizji, o której mówił Stephelton:

http://www.gamasutra.com/view/feature/3383/simple_intersection_tests_for_games.php?page=3

Zasadniczo rozwiązujesz niektóre podstawowe równania kinematyczne dla dokładnego punktu czasowego, kiedy twoje dwa obwiednie zaczynają się przecinać. Rozwiązujesz kolizje dokładnie w tym momencie, a następnie kontynuujesz pozostały czas w ramce. Być może będziesz musiał ponownie zasymulować, co dzieje się po chwili zderzenia, ponieważ prędkości / przyspieszenia twoich obiektów ulegną zmianie. Ale i tak jest twój punkt wyjścia ... na zdrowie!

Mediokryt
źródło
Dzięki, sprawdziłem artykuł. Chodzi o to, że używam innej reprezentacji moich obiektów. Używam wypukłych wielościanów i testuję zderzenie za pomocą twierdzenia o osi oddzielającej. Można to rozszerzyć, aby obsługiwać ciała poruszające się ze stałymi prędkościami liniowymi (co wiem, jak to zrobić), ale nie mam pojęcia, jak obsługiwać również prędkości kątowe. Ale zadam osobne pytanie, czy zdecyduję się pójść tą drogą.
Adam