Alternative di partizionamento spaziale 2D a hash spaziali e quadrifici


11

Ho cercato di implementare un algoritmo di partizionamento spaziale nel mio gioco, ma sia gli hash spaziali che i quadrifici non sono quello che sto cercando.

La mia dimensione di livello non dovrebbe avere un limite (solo limiti Int32). Ho bisogno di un algoritmo di partizionamento spaziale che non abbia bisogno di una "Larghezza di livello" e di "Altezza di livello".

Ho molti oggetti fisici in movimento. Ho bisogno che l'algoritmo sia abbastanza veloce da supportare oltre 500 oggetti.

Qualche alternativa?

Risposte:


13

Albero dinamico

Box2D è un motore ben ottimizzato progettato da un programmatore esperto di fisica / gioco . Originariamente Box2D utilizzava una griglia di hash che richiedeva un'altezza e una larghezza fisse.

Quando Erin passò a un algoritmo a larga fase migliore, andò con il btDbvt di Nathanael Presson. Questa è la fase utilizzata da Bullet Physics. Erin ha modificato e ottimizzato l'algoritmo per 2d.

Puoi leggere una panoramica di altissimo livello nel manuale Box2D (§4.11 o cercare la struttura dinamica).

Ecco un'eccezione dalla documentazione nel codice (che è molto buona considerando che non fa parte dell'API pubblica).

Un albero dinamico AABB a larga fase, ispirato al btDbvt di Nathanael Presson. Un albero dinamico organizza i dati in un albero binario per accelerare le query come query di volume e cast di ray. Le foglie sono proxy con un AABB. Nella struttura espandiamo il proxy AABB di b2_fatAABBFactor in modo che il proxy AABB sia più grande dell'oggetto client. Ciò consente all'oggetto client di spostarsi di piccole quantità senza attivare un aggiornamento dell'albero.

I nodi sono raggruppati e trasferibili, quindi utilizziamo gli indici dei nodi anziché i puntatori.

La mia comprensione dell'algoritmo di Dynamic Tree è questa. L'albero dinamico è l'incrocio tra un classico albero binario avl e un quadrifoglio. L'effetto finale è un quadrilatero che divide solo ogni nodo a metà e la linea di divisione non è fissa (le due metà non hanno le stesse dimensioni di un albero quad). AVL entra perché quadree con divisioni dinamiche può degenerare essenzialmente in un elenco (O (n) velocità di ricerca). L'AVL viene utilizzato per riequilibrare i sottotitoli in modo da garantire la velocità di ricerca di O lg (N).

Il migliore di tutti è il codice MIT, quindi sentiti libero di copiare / derivato / spudoratamente-rubare / ecc.


Sembra ... complesso! Lo darò un'occhiata, però. Qualcuno mi ha suggerito di usare la tecnica "sweep and prune" o "sort and sweep" ma non sono riuscito a trovare nulla su un'implementazione C # o .NET. Ho trovato un esempio di c ++ ma è confuso e non ha funzionato (ho provato comunque a implementarlo). Pensi che SAP sarebbe più facile da implementare? Esistono implementazioni .NET?
Vittorio Romeo,

8

Questo è molto vicino a una domanda simile posta qui su Gamedev, ma visto che sei preoccupato per le prestazioni e non per l'archiviazione dei file, forse la mia risposta ci sarà di maggiore utilità. Includerò la maggior parte di questo qui per completezza, ma la risposta originale fornisce un po 'più di profondità se vuoi esaminarlo.

Ho riscontrato un problema simile e ho deciso di creare la mia struttura per gestire i dati. Si basa vagamente su un quadrifoglio, ma ha un'espandibilità infinita (almeno grande quanto un Int) in tutte le direzioni. È stato progettato per gestire i dati basati su griglia che si sono espansi da un punto centrale, proprio come Minecraft ora fa. È efficiente in termini di spazio in memoria e molto veloce.

Il mio codice può essere trovato qui . Il codice è completo, testato (test di unità e di carico) e abbastanza ottimizzato. I meccanismi interni non sono ancora ben documentati, tuttavia, ma tutti i metodi pubblici sono quindi dovrebbe essere utilizzabile. Se qualcuno decide di provarlo, non esitare a contattarmi per domande o commenti.


1

Quando si lavora con un numero relativamente piccolo (<diverse migliaia) di oggetti piccoli (la maggior parte degli oggetti non è abbastanza grande da potersi scontrare potenzialmente con molti altri oggetti) trovo che un semplice elenco x di scatole di delimitazione allineate assialmente (AABB) funzioni abbastanza bene. Ho appena messo gli oggetti in un elenco, quindi ogni fotogramma dopo aver spostato gli oggetti, ho ordinato rapidamente l'elenco per valore x, quindi ho fatto un passaggio nell'elenco controllando la vicinanza di AABB. Per ogni oggetto, lo controllo contro gli oggetti che precedono nell'elenco fino a quando non raggiungo la fine dell'elenco o un oggetto che non rientra nell'intervallo x; vale a dire, il valore x del bordo sinistro è> valore x del bordo destro dell'oggetto da testare. Fondamentalmente divide dinamicamente lo spazio in sezioni di dimensioni AABB-x-larghezza talvolta sovrapposte. E'


0

Forse l' algoritmo r-tree è quello che stai cercando.

Lavoro davvero bene per la geometria statica, ma puoi anche usarlo per spostare oggetti rimuovendo e aggiungendo oggetti nelle loro nuove posizioni.


Ho provato un'implementazione in C # e le prestazioni sono state pessime quando "ho rimosso e aggiunto oggetti nella loro nuova posizione".
Vittorio Romeo,

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.