Un OBB è uno scafo convesso. Uno scafo convesso è una forma 3D che non ha "fessure" sulla sua superficie. Ogni "protuberanza" (vertice) sullo scafo convesso sporge verso l'esterno , mai verso l'interno. Se tagli un piano attraverso uno scafo convesso otterrai (solo uno) poligono convesso. Se ti trovi all'interno di uno scafo convesso e spari un laser rivolto verso l'esterno, perforerai la superficie dello scafo solo una volta (mai due volte).
Il test del teorema sull'asse di separazione può essere utilizzato per rilevare la collisione degli scafi convessi. Il test SAT è semplice. Funziona in 2D e 3D. Sebbene le immagini sottostanti siano in 2D, potrebbero essere altrettanto facilmente applicate al 3D.
Concetto
Questo è il concetto chiave che stai usando con SAT:
- Due forme si intersecano solo se si sovrappongono quando "proiettate" su ogni asse normale di entrambe le forme .
La "proiezione" di una forma su un vettore 1D assomiglia a questo (quello che chiamo "schiacciamento")
Una forma con verbi rossi e un asse
"Proiettare la forma sull'asse" significa far cadere una perpendicolare da ciascun punto della forma per atterrare sull'asse. Puoi pensare a questo come a "schiacciare" i punti con una mano che raccoglie tutto e lo schiaccia perpendicolarmente sull'asse.
Cosa ti rimane: punti su un asse
SAT dice:
Affinché 2 scafi convessi si intersecino, devono sovrapporsi su ogni asse (dove ogni normale su entrambe le forme conta come un asse che dobbiamo controllare).
Prendi queste 2 forme:
Vedi che non si intersecano, quindi proviamo alcuni assi per mostrare se non si verifica una sovrapposizione .
Cercando il massimo normale del pentagono:
Queste sono le estensioni. Si sovrappongono.
Prova a sinistra del rettangolo. Ora non si sovrappongono in questo asse, quindi NESSUNA INTERSEZIONE.
Algoritmo:
Per ogni faccia normale su entrambe le forme:
- Trova le estensioni minima e massima (valore più grande e più piccolo) della proiezione di tutti i punti d' angolo del vertice di entrambe le forme su quell'asse
- Se non si sovrappongono, nessun incrocio .
E questo è tutto. Il codice per far funzionare SAT è molto breve e semplice.
Ecco un codice che mostra come eseguire una proiezione dell'asse SAT:
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;
}
}
Prefisso telefonico:
// 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 ;
}