Ein OBB ist eine konvexe Hülle. Ein konvexer Rumpf ist eine 3D-Form, die auf ihrer Oberfläche keine "Unebenheiten" aufweist. Jede "Erhebung" (Vertex) auf dem konvexen Rumpf ragt nach außen , niemals nach innen. Wenn Sie eine Ebene durch eine konvexe Hülle schneiden, erhalten Sie (nur ein) konvexes Polygon. Wenn Sie sich in einer konvexen Hülle befinden und einen nach außen gerichteten Laser abfeuern, können Sie die Oberfläche der Hülle nur einmal (niemals zweimal) durchstoßen .
Der Separating Axis Theorem Test kann verwendet werden, um Kollisionen von konvexen Hüllen zu erkennen. Der SAT-Test ist einfach. Es funktioniert in 2D und 3D. Obwohl die Bilder unten in 2D vorliegen, können sie genauso gut in 3D angewendet werden.
Konzept
Dies ist das Schlüsselkonzept, das Sie mit SAT verwenden:
- Zwei Formen kreuzen sich nur, wenn sie sich überlappen, wenn sie auf jede normale Achse beider Formen "projiziert" werden .
Die "Projektion" einer Form auf einen 1D-Vektor sieht so aus (was ich "Quetschen" nenne)
Eine Form mit roten Ecken und einer Achse
"Projizieren der Form auf die Achse" bedeutet, dass von jedem Punkt der Form eine Senkrechte abgesetzt wird, um auf der Achse zu landen. Sie können sich das so vorstellen, als würden Sie die Punkte mit einer Hand "zerquetschen", die alles sammelt und senkrecht zur Achse zerquetscht.
Was Ihnen noch bleibt: Punkte auf einer Achse
SAT sagt:
Damit sich zwei konvexe Rümpfe schneiden, müssen sie sich auf jeder Achse überlappen (wobei jede Normale auf einer der beiden Formen als zu überprüfende Achse gilt).
Nimm diese 2 Formen:
Sie sehen , dass sie sich nicht schneiden, kann so versuchen , ein paar Achsen zu zeigen wurde eine Überlappung nicht passieren.
Versuch der oberen Normalen des Fünfecks:
Das sind die Ausmaße. Sie überschneiden sich.
Versuchen Sie es mit der linken Seite des Rechtecks. Jetzt überlappen sie sich in dieser Achse nicht, daher KEINE SCHNITTSTELLE.
Algorithmus:
Für jedes Gesicht normal auf beiden Formen:
- Ermitteln Sie die minimale und maximale Ausdehnung (größter und kleinster Wert) der Projektion aller Eckpunkte beider Formen auf diese Achse
- Wenn sie sich nicht überlappen, keine Kreuzung .
Und das war's auch schon. Der Code, mit dem SAT funktioniert, ist sehr kurz und einfach.
Hier ist ein Code, der demonstriert, wie eine SAT-Achsenprojektion durchgeführt wird:
void SATtest( const Vector3f& axis, const vector<Vector3f>& ptSet, float& minAlong, float& maxAlong )
{
minAlong=HUGE, maxAlong=-HUGE;
for( int i = 0 ; i < ptSet.size() ; i++ )
{
// just dot it to get the min/max along this axis.
float dotVal = ptSet[i].dot( axis ) ;
if( dotVal < minAlong ) minAlong=dotVal;
if( dotVal > maxAlong ) maxAlong=dotVal;
}
}
Vorwahl:
// Shape1 and Shape2 must be CONVEX HULLS
bool intersects( Shape shape1, Shape shape2 )
{
// Get the normals for one of the shapes,
for( int i = 0 ; i < shape1.normals.size() ; i++ )
{
float shape1Min, shape1Max, shape2Min, shape2Max ;
SATtest( normals[i], shape1.corners, shape1Min, shape1Max ) ;
SATtest( normals[i], shape2.corners, shape2Min, shape2Max ) ;
if( !overlaps( shape1Min, shape1Max, shape2Min, shape2Max ) )
{
return 0 ; // NO INTERSECTION
}
// otherwise, go on with the next test
}
// TEST SHAPE2.normals as well
// if overlap occurred in ALL AXES, then they do intersect
return 1 ;
}
bool overlaps( float min1, float max1, float min2, float max2 )
{
return isBetweenOrdered( min2, min1, max1 ) || isBetweenOrdered( min1, min2, max2 ) ;
}
inline bool isBetweenOrdered( float val, float lowerBound, float upperBound ) {
return lowerBound <= val && val <= upperBound ;
}