Rilevamento delle collisioni: un mucchio di casi speciali?


8

Sto scrivendo un semplice motore fisico in 2D. Il mio primo obiettivo è far funzionare il rilevamento delle collisioni. So che i miei oggetti alla fine saranno costituiti da forme primitive, ma mi chiedevo: una libreria di rilevamento delle collisioni sarebbe composta da un gruppo di funzioni di casi speciali, come "rayAndLine", "rectangleRectangle", "rectangleCircle" ecc., Oppure è esiste un framework comune sottostante per il rilevamento delle collisioni che funziona indipendentemente dalle primitive utilizzate per creare la forma?


Ti chiedi di un framework sottostante, ma dichiari espressamente che ti piacerebbe costruire questa porzione da solo. Puoi chiarire l'ultima frase in cui si svolge la tua domanda effettiva, al fine di separare in modo più specifico la tua preoccupazione in merito alla sua costruzione, dall'uso del framework di qualcun altro che hanno creato. Fornirò anche una risposta.
Joshua Hedges,

Punto valido. Intendevo la teoria di base da cui deriva tutto il rilevamento delle collisioni. In altre parole, se sto scrivendo un sottosistema di rilevamento delle collisioni, devo scrivere una funzione per ciascun tipo di collisione primitiva / primitiva, oppure esiste un'unica funzione generica che funziona indipendentemente dalla primitiva?
Michael Stachowsky,

Una specie di. Ho appena risposto. Ci sono alcuni che generalizzano le soluzioni davvero bene, come SAT funziona per qualsiasi poligono convesso e qualsiasi poligono concavo può essere scomposto in poligoni convessi, il che lo fa funzionare per qualsiasi poligono con qualche lavoro. Dopodiché dovresti specializzarti contro curve, sfere e ovali. L'ho delineato di seguito. È un argomento importante da affrontare, quindi è lungo. Fammi sapere se hai domande su dettagli o altro
Joshua Hedges,


1
Più codice condiviso, meglio è. Se ti ritrovi mai a usare copia e incolla, controlla seriamente te stesso!
corsiKa

Risposte:


9

Far funzionare il rilevamento delle collisioni è un ottimo primo obiettivo per il tuo motore fisico 2D. È positivo che tu abbia deciso che per ora stai lavorando specificamente in 2D, poiché non tutte le regole in 2D funzionano in 3D, nonostante la quantità di algoritmi relativi alla dimensione n, a un certo punto devi specializzarli (fai di più variante specifica come il modo in cui il prodotto incrociato soddisfa solo l'identità Jacobi in 3D).

La tua domanda riguarda intrinsecamente l'architettura e il design del framework e non la fisica 2D, quindi la preoccupazione di ciò che il tuo edificio dovrebbe essere separato nella tua mente per come vengono utilizzati quei pezzi. In sostanza, è necessario separare la mentalità di costruzione del motore / libreria / framework dal suo utilizzo in un altro progetto.

Architects motori di risoluzione: con qualsiasi motore matematico, essenzialmente vogliamo mettere i valori in qualche funzione e ci aspettiamo che i valori che risultano utili per realizzare una simulazione interessante.

Gli elementi chiave di questo processo dovrebbero essere il più astratti possibile mentre gli elementi atomici (i più piccoli pezzi utili di dati / metodi) dovrebbero essere specifici per scopi individuali ed essere utili per comporre insieme. Nel nostro caso quasi l'unico utile atomico è un vettore 2D, che dovrebbe essere una singola classe di oggetti che consente l'espressione di una struttura (x, y) e ha metodi per tutte le operazioni matematiche di base utili per i calcoli vettoriali in 2D. Addizione, sottrazione, normalizzazione, normale (perpendicolare), prodotto incrociato, punto prodotto, magnitudo / lunghezza e qualsiasi altra cosa si incontri che è inerentemente inerente al vettore -> operazioni vettoriali o vettore -> operazioni numeriche reali. Se stai usando un linguaggio di classe, un semplice class Vectorcon ognuno di questi come funzione membro o sovraccarico dell'operatore farebbe molto bene.

Dopo che tutti i tipi atomici sono stati costruiti, comporresti i loro algoritmi in un altro livello sopra il nostro tipo atomico Vector. Il mio go to sarebbe a Linee a Curve. Decideremo qui che a Curveè fuori portata per questo e richiede molta specializzazione (il concetto a cui si fa riferimento sopra come la creazione di molte funzioni di casi speciali). Da Vectorcomporrei anche a Rectanglecome Vectorprimitiva 4 , comporre Circledal vettore usando a Vectore a radius, e poi comporrei anche un Polygonda Vector. Polygondovrebbe essere fatto da Vectore non Linequi perché ogni linea condividerebbe un punto duplicato con l'ultima linea nel poligono.

Ora hai delle forme, ma non sappiamo cosa farne.

Collision Detection Il rilevamento delle collisioni non è una scienza esatta e non esiste un singolo algoritmo perfetto (o uno qualsiasi). Esistono molti metodi che possono essere utilizzati per ottenere una varietà di effetti di qualità o addirittura avere una maggiore precisione rispetto ad altri. Fondamentalmente, tuttavia, può essere separato in alcuni diversi livelli di preoccupazione e quindi in alcuni processi diversi.

Il rilevamento di collisioni a fase larga è l'atto di sezionare le aree in cui ci preoccupiamo di ciò che potrebbe / potrebbe / si scontrano e di separarle per il processo a fase stretta. In 2D in genere consiglierei di usare un albero quad per questo. Per questo avremo bisogno del nostro che Rectangleabbiamo costruito in precedenza e di fornire un rilevamento delle collisioni AABB. Questo sta per Axis Aligned Bounding Box e lo useremo per determinare che per una scatola non rotante in Acui non Besiste alcuna parte della scatola A. Dal presupposto che nessuna parte di Bpuò esistere all'interno di Auna collisione esiste se si intersecano.

Un albero quad è un processo ricorsivo in cui si determina una profondità massima o si consente invece alla quantità dell'oggetto di impedire una profondità di ricorsione infinita. Raggruppa i corpi fisici in 4 regioni (da cui il nome) e dovrebbe consentire di accedere a ciascun quad separatamente. Dovresti quindi entrare in ognuno di quei quattro quaderni ed eseguire lo stesso processo che non tratterò qui per brevità ma è disponibile qui: https://gamedevelopment.tutsplus.com/tutorials/quick-tip-use-quadtrees- gamedev-374 - a-probabili-collisioni-in-2d-spazio-rilevamento

Collisione a fase strettaè il processo di analisi dei gruppi di forme che abbiamo già determinato si scontrerà / potrebbe / farà scontrarsi e di eseguire un controllo delle collisioni più discreto, a questo punto iniziamo a preoccuparci se gli oggetti ruotano o meno (ho vinto ' coprire questo, quando si superano queste fasi di collisione, si cerca di rilevare la collisione con momento angolare) e la forma del loro corpo di collisione. Per eseguire questa parte della collisione devi specializzare i tuoi metodi come descritto sopra (creando funzioni specifiche per AABBvsCircle, OBBvsCircle, CirclevsCircle, PolygonvsPoint, PolygonvsCircle, PointvsCircle, ecc.) Tuttavia, questi stessi metodi possono anche essere eseguiti su più livelli come sopra.

I suoi controlli di separazione primitivi sono i discreti, i metodi di rilevamento delle collisioni specializzati o quelli generali come SAT seconda caso d'uso e dovrebbero essere tutti semplicemente restituire un valore true / false, o restituire un oggetto relazionale, come un Manifold, Joint, CollisionObjectecc, che avrebbe un collegamento con le due forme che si trovano a scontrarsi e tutte le informazioni su di esse necessarie per risolvere la collisione, ad esempio quanto in profondità si scontrano o a quale velocità (quali dati sono necessari nella varietà dipendono dal metodo di risoluzione utilizzato). Quell'oggetto si passa a un oggetto Solverche dovrebbe astrarre le differenze tra tutte le diverse forme che potrebbero scontrarsi, accettando solo una Manifolde non accettando alcuna informazione particolare sulle forme.

Sommario Il Solverprenderà il Manifoldprodotto facendo scontrare un po 'di primitiva Acon un po' di primitiva B, usando prima il raggruppamento di fase ampia (tutto vs mondo) e poi il rilevamento di fase stretta (A vs B) e se le forme sono non poligonali devono essere specializzate, Solverquindi produce sia nuove Vectors per le posizioni e le velocità delle forme in collisione, o un oggetto che il PhysicsEnvironmento Worldpuò quindi utilizzare per risolvere la collisione sui propri figli, quindi infine aggiornare QuadTreee ripetere questo processo sul fotogramma successivo. Se entrambe le forme in collisione sono poligoni, la specializzazione dovrebbe essere fatta solo per quanto riguarda l'aumento delle prestazioni, altrimenti semplicemente usando il teorema sull'asse di separazione


1
Ottima risposta, grazie. Sono curioso, però: inizialmente avevo considerato di basare il mio oggetto più primitivo sulla punta, quindi di costruire un vettore da lì. Vedo dalla tua risposta che questa non è stata necessariamente la scelta migliore. Perché?
Michael Stachowsky,

1
Il motivo è che in 2 dimensioni un vettore e un punto hanno effettivamente la stessa definizione. a Vector direction,Magnitudepuò essere preso come un Point x,yse semplicemente ignori alcune delle operazioni Vectorfornite. La parte migliore di questo, è solo perché ora puoi ignorare quelle operazioni, quando vuoi determinare cose come il momento angolare non stai cambiando i tipi di oggetti. Quindi è quasi una questione di gusti, perché quello che gli sviluppatori di giochi chiamano "punto" i matematici chiamano davvero un "vettore". Quindi chiamalo come vuoi, l'importante è quello che offre.
Joshua Hedges,

1
In un linguaggio in stile C, se volessi usare la definizione "Punto" per la leggibilità, in effetti lo farei semplicemente typedefda un Vettore, o alias il termine "Punto" per significare la stessa cosa di "Vettore".
Joshua Hedges,
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.