QuadTree: memorizzare solo punti o regioni?


9

Sto sviluppando un quadrifoglio per tenere traccia degli oggetti in movimento per il rilevamento delle collisioni. Ogni oggetto ha una forma di delimitazione, diciamo che sono tutti cerchi. (È un gioco top-down 2D)

Non sono sicuro se memorizzare solo la posizione di ciascun oggetto o l'intera forma del contorno.

Se si lavora con punti, l'inserimento e la suddivisione sono facili, poiché gli oggetti non si estenderanno mai su più nodi. D'altra parte, una query di prossimità per un oggetto potrebbe non rilevare le collisioni, poiché non terrà conto delle dimensioni degli oggetti. Come calcolare l'area della query quando si hanno solo punti?

Collisione tra oggetti di nodi vicini

Se si lavora con regioni, come gestire un oggetto che si estende su più nodi? Dovrebbe essere inserito nel nodo genitore più vicino che lo contiene completamente, anche se questo supera la capacità del nodo?

Quale nodo dovrebbe contenere l'oggetto rosso?

Grazie.

Risposte:


4

Se si memorizzano oggetti estesi (regioni) in un quadrifoglio, si dovrebbe fare riferimento all'oggetto da tutti i nodi foglia che tocca. Non proverei a trovare l'antenato meno comune e conservarlo lì, perché ad esempio un piccolo oggetto che capita di attraversare un confine di alto livello finirà in un nodo molto alto e deve essere testato contro tutto il resto in quella grande , nodo di alto livello quando si eseguono query di collisione e simili.

Tuttavia, devi anche fare attenzione perché gli oggetti di grandi dimensioni potrebbero finire per essere referenziati da molti nodi, rendendoli costosi da aggiornare quando si spostano e facendo in modo che vengano ricontrollati più volte per collisioni ecc. A seconda del tuo caso d'uso potrebbe valere la pena usare una sorta di euristica per archiviare oggetti di grandi dimensioni ad un livello superiore nella struttura, ma ciò complicherebbe gli algoritmi, quindi probabilmente non mi preoccuperei a meno che tu non stabilisca che è davvero un problema di prestazioni nel tuo caso particolare.

Allo stesso modo, per eseguire una query su una regione, la query dovrebbe esaminare tutti i nodi foglia toccati dalla regione interrogata.

Fondamentalmente usano lo stesso algoritmo, che è quello di iniziare con una regione e spingerla verso il basso attraverso l'albero per trovare i nodi foglia che tocca. È un attraversamento in profondità, ma in ogni nodo puoi potare tutti i bambini che non toccano la regione. Dovrai mantenere uno stack per tenere traccia di dove ti trovi nell'attraversamento.


Grazie, questo ha senso. Certo, l'elaborazione di oggetti tra nodi sarebbe più lenta degli oggetti che si trovano completamente all'interno di un nodo, ma non riesco a vederlo. Potrei aumentare la capacità del nodo per mantenere bassa la frammentazione, ma ciò aumenterebbe il numero di oggetti inclusi nel rilevamento delle collisioni. Ci giocherò per trovare un buon equilibrio.
alekop,

4

È necessario memorizzarlo nel nodo più piccolo che lo contiene completamente, anche se questo supera la capacità (utilizzare un contenitore ridimensionabile).


2

Vorrei aggiungere questo come commento in risposta alla risposta di @Nathan Reed, tranne per il fatto che è troppo grande per essere un commento, e forse è comunque degno di essere una risposta separata.

Stavamo facendo esattamente ciò che è stato proposto nella sua risposta, e in effetti abbiamo commentato nella fonte il link a questa pagina. Per la maggior parte, ha funzionato molto bene, tranne che una volta ogni due o tre mesi, abbiamo perso un server a caso che è diventato non reattivo a causa dell'enorme durata delle query di ricerca.

La causa principale del problema è venuta alla mia attenzione mentre eseguivo un controllo delle prestazioni per cercare di capire cosa lo causasse. Probabilmente è solo una preoccupazione se permetti oggetti sovrapposti. Nel nostro gioco lo facciamo e, nel peggiore dei casi, a volte porta a un picco di profondità che uccide le prestazioni.

Avevamo un caso limite in cui circa 100 oggetti, tutti con dischi di delimitazione, erano raggruppati nelle immediate vicinanze. Ciò ha portato al problema di un picco molto profondo nell'albero, perché siamo arrivati ​​al punto in cui gli oggetti erano più grandi dell'area coperta dai nodi quadrifogli, quindi ogni nuovo oggetto si presentava in più nodi, portando a una suddivisione massiccia del albero, quindi innescando il problema senza controllo.

Il risultato è che se permetti alle regioni di oggetti di sovrapporsi, tieni d'occhio le cose se ottieni ammassi ristretti di oggetti, per assicurarti che l'albero non diventi troppo profondo.

La soluzione che sto attualmente studiando è quella di archiviare oggetti come punti e quindi, quando si esegue una ricerca, aumentare i limiti del rettangolo di ricerca del raggio massimo memorizzato nella struttura. Ciò dovrebbe funzionare per noi, poiché l'albero è una ricerca di primo passaggio, quindi eseguiamo un controllo dell'intervallo basato su un vero cerchio, insieme ad alcuni altri controlli sui criteri, in modo che i falsi avvisi aggiuntivi vengano filtrati.

Il chilometraggio effettivo può variare.

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.