Möglicherweise erhalten Sie falsche Positive. Kollisionen erkannt, aber nicht wirklich kollidierend.
Die Nummer 15 kommt von
- 3 Achsen von Objekt A (Flächennormalen)
- 3 Achsen von Objekt B (Flächennormalen)
- 9 Achsen von allen Kantenpaaren von A und Kanten von B (3x3)
- = 15 insgesamt
Die 9 Achsen bestehen aus Kreuzprodukten der Kanten von A und Kanten von B
- Ae1 x Be1 (Kante 1 von A, Kreuzkante 1 von B)
- Ae1 x Be2
- Ae1 x Be3
- Ae2 x Be1
- ... und so weiter
Die ersten 6 Achsen (von den Flächennormalen) werden verwendet, um zu prüfen, ob eine Ecke eines Objekts eine Fläche des anderen Objekts schneidet. (oder genauer gesagt, um solche Kollisionen zu vermeiden)
Der Satz von 9 Achsen, der durch die Kreuzprodukte von Kanten gebildet wird, wird verwendet, um die Erkennung von Kanten auf Kanten zu berücksichtigen, wenn kein Scheitelpunkt das andere Objekt durchdringt. Wie die "fast" Kollision auf dem Foto unten. Nehmen wir für den Rest dieser Antwort an, dass die beiden Kästchen im Bild nicht tatsächlich kollidieren, sondern durch einen winzigen Abstand voneinander getrennt sind.
Schauen wir uns an, was passiert, wenn wir nur die 6-Gesichts-Normalen für SAT verwenden. Das erste Bild unten zeigt eine Achse aus der blauen Box und 2 Achsen aus der gelben Box. Wenn wir beide Objekte auf diese Achsen projizieren, erhalten wir eine Überlappung für alle drei. Das zweite Bild unten zeigt die verbleibenden zwei Achsen der blauen Box und die verbleibende Achse der gelben Box. Wenn Sie erneut auf diese Achsen projizieren, werden alle drei Achsen überlappt.
Wenn Sie also nur die 6-Flächen-Normalen überprüfen, werden Überlappungen auf allen 6 Achsen angezeigt, was laut SAT bedeutet, dass die Objekte kollidieren, da wir keinen Abstand finden konnten. Aber natürlich kollidieren diese Objekte nicht. Der Grund, warum wir keine Trennung gefunden haben, ist, dass wir nicht genau genug nachgesehen haben!
Wie können wir diese Lücke finden? Das Bild unten zeigt eine Achse, auf der die Projektion beider Objekte eine Trennung erkennen lässt.
Woher bekommen wir diese Achse?
Wenn Sie sich vorstellen, ein Stück steife Karte in die Lücke zu schieben, ist diese Karte Teil der Trennebene. Wenn wir auf die Normalen dieser Ebene projizieren (schwarzer Pfeil im Bild oben), sehen wir den Abstand. Wir wissen, was diese Ebene ist, weil wir zwei Vektoren haben, die auf dieser Ebene liegen.) Ein Vektor ist an der Kante von Blau ausgerichtet, und der andere Vektor ist an der Kante von Gelb ausgerichtet. Wie wir alle wissen, ist die Normale zu einer Ebene einfach die Kreuzprodukt zweier im Flugzeug liegender Vektoren.
Für OOBBs müssen wir also jede Kombination (9 von ihnen) von Kreuzprodukten der Kanten der beiden Objekte überprüfen, um sicherzustellen, dass keine Kanten-Kanten-Abstände fehlen.
Kens Antwortnotizen :
Es ist etwas verwirrend, sich auf die Kanten zu beziehen, da es 12 Kanten im Vergleich zu 6 Normalen gibt, wenn Sie genauso gut die drei Hauptnormalen für die gleiche Ausgabe verwenden können - die Kanten sind alle an den Normalen ausgerichtet, daher empfehle ich, sie stattdessen zu verwenden !
Beachten Sie auch, dass Normalen, die auf dieselbe Achse, jedoch in eine andere Richtung zeigen, ignoriert werden und somit drei eindeutige Achsen übrig bleiben.
Eine andere Sache, die ich hinzufügen möchte, ist, dass Sie diese Berechnung optimieren können, indem Sie vorzeitig beenden, wenn Sie eine Trennachse finden, bevor Sie alle Achsen berechnen, die Sie testen möchten. Also, nein, Sie müssen nicht in jedem Fall alle Achsen testen, aber Sie müssen bereit sein, sie alle zu testen :)
Hier ist eine vollständige Liste der zu testenden Achsen mit zwei OBBs A und B, wobei sich x, y und z auf die Basisvektoren / drei eindeutigen Normalen beziehen. 0 = x-Achse, 1 = y-Achse, 2 = z-Achse
Es gibt auch eine kleine Einschränkung, die Sie beachten sollten.
Das Kreuzprodukt ergibt einen Nullvektor {0,0,0}, wenn zwei Achsen zwischen den Objekten in die gleiche Richtung zeigen.
Da dieser Teil weggelassen wurde, ist hier meine Implementierung, um zu prüfen, ob sich die Projektion überlappt oder nicht. Es gibt wahrscheinlich einen besseren Weg, aber das hat bei mir funktioniert! (Verwenden von Unity und seiner C # -API)
quelle
funktionierendes C # -Beispiel basierend auf Acegikmos Antwort (unter Verwendung einiger Unity-APIs):
quelle