OBB vs OBB Rilevamento collisioni


20

Supponiamo che tu abbia due oggetti Bounding Box ognuno dei quali memorizza i vertici correnti del box in un vettore con tutti i vertici dell'oggetto ruotati e tradotti rispetto ad un asse comune.

Ecco un'immagine per illustrare il mio problema:

Come posso capire se i due OBB si sovrappongono a qualsiasi link per aiutare a spiegare la soluzione del problema sarebbe il benvenuto. Niente di troppo contorto per favore ...

Risposte:


16

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

inserisci qui la descrizione dell'immagine

"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.

inserisci qui la descrizione dell'immagine

Cosa ti rimane: punti su un asse

inserisci qui la descrizione dell'immagine

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:

inserisci qui la descrizione dell'immagine

Vedi che non si intersecano, quindi proviamo alcuni assi per mostrare se non si verifica una sovrapposizione .

Cercando il massimo normale del pentagono:

inserisci qui la descrizione dell'immagine

Queste sono le estensioni. Si sovrappongono.

inserisci qui la descrizione dell'immagine

Prova a sinistra del rettangolo. Ora non si sovrappongono in questo asse, quindi NESSUNA INTERSEZIONE.

inserisci qui la descrizione dell'immagine

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 ;
}

Hullinator implementa il test SAT per gli scafi convessi
bobobobo

spiegazione fantastica! Grazie. Penso che si può avere un errore di battitura nella linea: "così lascia provare un paio di assi di mostrare erano una sovrapposizione non accade.", Perché poi si procede a dare esempi in cui si fanno sovrappongono. grazie ancora!

Non hai bisogno di fare i test anche per tutti i prodotti incrociati delle normali? Lo dice questo articolo geometrictools.com/Documentation/DynamicCollisionDetection.pdf .
iNFINITEi

Vale la pena affermare che questo specifico metodo di SAT funziona solo in 2D. In 3D devi ottenere qualcosa in più delle normali di ogni viso. Una volta che hai le normali giuste, tuttavia, il resto del processo (progetto, confronto) è esattamente lo stesso.
Fondi Monica's Lawsuit

Davvero difficile dire dalle tue immagini 2D quale direzione stanno andando le frecce.
WDUK,

7

Dovresti assolutamente cercare il teorema sull'asse di separazione . È per oggetti convessi. C'è una regola: "Se due oggetti convessi non si intersecano, allora c'è un piano in cui la proiezione di questi due oggetti non si intersecano".

Puoi trovare alcuni esempi sul wiki . Ma è un po 'più complicato rispetto al tuo caso.

Qui puoi trovare qualcosa di più adatto al tuo problema (due auto in collisione).


1

Altri articoli SAT .

L'ultimo articolo di questo sito include un codice completo, penso che sia in FLASH, non ne ho idea, ma ho avuto esattamente 0 problemi a convertirlo in C ++ quando ho dovuto usare SAT per la prima volta, non dovrebbe essere difficile fare lo stesso per altre lingue. L'unica cosa che dovrai aggiungere è la memorizzazione del vettore di spostamento su ogni calcolo (se è il più piccolo, ovviamente, lo capirai quando imparerai a conoscere SAT), il codice in questo tutorial non lo fa, quindi si finisce con l'ultimo vettore calcolato.

http://rocketmandevelopment.com/tag/separation-axis-theorem/

Buone vecchie esercitazioni su N-Game. Migliore teoria SAT sul web.

http://www.metanetsoftware.com/technique/tutorialA.html


È così irritante che nessuno pubblichi l'intera fonte di lavoro con tutte le classi richieste. Ho portato il suo codice in una mia demo ma non funziona. :( Questo è il mio progetto finora se qualcuno potesse aiutarmi a eseguire il debug sarebbe fantastico. Link
Joshua Barnett

cosa vuoi dire che non funziona? presta attenzione a come stai memorizzando i tuoi vertici, nell'immagine li hai in un sistema di coordinate cartesiane, nel tutorial egli memorizza i vertici come vettori relativi al centroide (tutto ciò che devi fare è sottrarre il centroide dai tuoi vertici o rimuovere le linee in cui modifica i propri vertici), funzioni come il punto prodotto che puoi creare da solo, non hai bisogno di una guida per quelle, il resto dovrebbe essere diretto, non è un materiale di copia incolla, impara SAT prima di provare a implementarlo
dreta,

Ecco come l'ho implementato: SAT.as , Shape2D.as , cosa intendi per centroide? Il centro del poligono come (x, y)?
Joshua Barnett,

Al momento ho una funzione getOBB () che restituisce vertici come dettagliato nella mia immagine originale. Questo viene calcolato dal vettore <b2Vec2> contenente i vertici della forma, una variabile d'angolo e una variabile di posizione.
Joshua Barnett,

sì, al centro, il modo in cui questo ragazzo crea i suoi poligoni è dando offset dal centro, idk AS3, ma da quello che vedo proietti i tuoi vertici così come sono, durante il calcolo del prodotto punto cerca di sottrarre centroide dai vertici (sottrazione vettoriale ), oltre a questo non stai controllando quale vettore di separazione sia il più piccolo ancora, ma memorizzi solo l'ultimo calcolato
dreta
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.