Być może otrzymujesz fałszywe alarmy. Wykryto kolizje, ale tak naprawdę nie kolidują.
Liczba 15 pochodzi z
- 3 osie od obiektu A (normalne twarze)
- 3 osie od obiektu B (normalne twarze)
- 9 osi ze wszystkich par krawędzi A i krawędzi B (3x3)
- = 15 ogółem
9 osi składa się z iloczynu poprzecznego krawędzi A i krawędzi B
- Ae1 x Be1 (Krawędź 1 z A krzyżuje krawędź 1 z B)
- Ae1 x Be2
- Ae1 x Be3
- Ae2 x Be1
- ... i tak dalej
Pierwsze 6 osi (z normalnych ścian twarzy) służy do sprawdzania, czy róg jednego obiektu przecina ścianę drugiego obiektu. (lub bardziej poprawnie, aby wyeliminować tego rodzaju kolizje)
Zbiór 9 osi utworzonych przez iloczyny poprzeczne krawędzi służy do rozważenia wykrywania kolizji między krawędziami, gdy nie ma wierzchołka penetrującego inny obiekt. Podobnie jak kolizja „prawie” na poniższym zdjęciu. Przyjmijmy do końca tej odpowiedzi, że dwa pola na zdjęciu tak naprawdę nie kolidują, ale są oddzielone niewielką odległością.
Przyjrzyjmy się, co się stanie, jeśli użyjemy 6 normalnych twarzy dla SAT. Pierwsze zdjęcie poniżej pokazuje jedną oś z niebieskiego pola i 2 osie z żółtego pola. Jeśli rzutujemy oba obiekty na te osie, otrzymamy nakładanie się na wszystkie trzy. Drugi obraz poniżej pokazuje pozostałe dwie osie niebieskiego pola i pozostałą oś żółtego pola. Ponownie rzutowanie na te osie będzie nakładać się na wszystkie 3.
Tak więc tylko sprawdzenie 6 normalnych twarzy pokaże nakładanie się na wszystkich 6 osiach, co według SAT oznacza, że obiekty zderzają się, ponieważ nie byliśmy w stanie znaleźć separacji. Ale oczywiście te obiekty nie kolidują. Powodem, dla którego nie znaleźliśmy separacji, jest to, że nie spojrzeliśmy wystarczająco mocno!
Jak więc znaleźć tę lukę? Poniższy obraz pokazuje oś, na której rzut obu obiektów ujawni separację.
Skąd mamy tę oś?
Jeśli wyobrażasz sobie wsunięcie kawałka sztywnej karty w szczelinę, karta ta będzie częścią płaszczyzny oddzielającej. Jeśli rzutujemy na normalną płaszczyznę (czarna strzałka na zdjęciu powyżej), zobaczymy separację. Wiemy, czym jest ta płaszczyzna, ponieważ mamy dwa wektory, które leżą na tej płaszczyźnie. Jeden wektor jest wyrównany z krawędzią niebieskiego, a drugi wektor jest wyrównany z krawędzią żółtej, a jak wszyscy wiemy, normalna do płaszczyzny jest po prostu iloczyn krzyżowy dwóch wektorów leżących na płaszczyźnie.
Dlatego w przypadku OOBB musimy sprawdzić każdą kombinację (9 z nich) iloczynu krzyżowego krawędzi dwóch obiektów, aby upewnić się, że nie brakuje nam żadnych separacji krawędzi.
Notatki odpowiedzi Kena :
Odwoływanie się do krawędzi jest nieco mylące, ponieważ istnieje 12 krawędzi w porównaniu do 6 normalnych, gdy równie dobrze możesz użyć trzech głównych normalnych do tego samego wyniku - wszystkie krawędzie są wyrównane z normalnymi, więc zalecam ich użycie zamiast tego !
Zauważ też, że normalne wskazujące wzdłuż tej samej osi, ale w innym kierunku, są ignorowane, dlatego mamy trzy unikalne osie.
Inną rzeczą, którą chciałbym dodać, jest to, że możesz zoptymalizować to obliczenie, wychodząc wcześniej, jeśli znajdziesz oś oddzielającą, przed obliczeniem wszystkich osi, które chcesz przetestować. Więc nie, nie musisz testować wszystkich osi w każdym przypadku, ale musisz być gotowy do przetestowania ich wszystkich :)
Oto pełna lista osi do przetestowania, z dwoma OBB, A i B, gdzie x, y i z odnoszą się do wektorów podstawowych / trzech unikalnych normalnych. 0 = oś x, 1 = oś y, 2 = oś z
Jest też małe zastrzeżenie, o którym powinieneś wiedzieć.
Iloczyn krzyżowy da wektor zerowy {0,0,0}, gdy dowolne dwie osie między obiektami wskażą ten sam kierunek.
Ponadto, ponieważ ta część została pominięta, oto moja implementacja, aby sprawdzić, czy projekcja się pokrywa. Prawdopodobnie jest lepszy sposób, ale to zadziałało dla mnie! (Korzystanie z Unity i jego API C #)
źródło
działający przykład c # oparty na odpowiedzi Acegikmo (przy użyciu niektórych interfejsów API jedności):
źródło