Wann ist ein Quadtree dem räumlichen Hashing vorzuziehen?

11

Ich mache einen 2D-Plattformer mit vielen Objekten gleichzeitig. Sie sind alle AABB-Kollisionen erkannt. Ich habe zuerst einen Quadtree versucht, um die Anzahl der zu überprüfenden Objekte zu verringern, habe einige verschiedene Konfigurationen ausprobiert, aber es hat sich nicht als so effektiv erwiesen, wie ich es brauchte. Ich habe einen räumlichen Hash implementiert und es ist viel effizienter. Die Anzahl der Objekte, die bei jeder Kollision überprüft werden müssen, ist drastisch gesunken.

Gibt es einen Fall, in dem eine 2D-Kollisionserkennung mit einem Quadtree dem räumlichen Hashing vorzuziehen ist? Nach meinen Tests scheint räumliches Hashing immer dazu zu führen, dass weniger Objekte auf Kollision getestet werden müssen.

Ich habe die Algorithmen nicht zeitlich festgelegt, aber ist Hashing einfach sehr teuer oder schwierig zu implementieren, wenn Sie beispielsweise in C codieren? Bemerkenswert ist, dass ich das Spiel in Javascript schreibe, wo Sie "kostenlos" Hashing haben.

Hier ist der Vergleich, habe ich etwas übersehen? http://zufallsgenerator.github.io/2014/01/26/visually-comparing-algorithms/

Chris
quelle

Antworten:

11

Der Hauptvorteil eines Quad-Baums besteht darin, dass Sie ganze Gruppen von Eimern sehr schnell aus der Betrachtung entfernen können.

Nehmen wir zum Beispiel an, ich habe einen Quad-Baum mit sechs Ebenen. Auf der niedrigsten Ebene sind das 32x32-Boxen. 1024 Kisten mit dieser untersten, detailliertesten Ebene. Zum Vergleich betrachten wir auch einen "räumlichen Hash" - ein flaches Gitter, das auch 32x32-Boxen enthält, insgesamt 1024 Boxen. (Der Quad-Baum hat insgesamt mehr als 1024 Boxen, da er auf seinen höheren Ebenen auch größere Boxen enthält.)

Nehmen wir an, dass das System keine kollidierbaren Objekte enthält - alle Kästchen unseres Quad-Baums und unseres flachen Gitters sind vollständig leer.

Wenn Sie die Kollisionen von etwas testen, das groß genug ist, dass sein Begrenzungsrahmen alle diese Kästchen schneidet, und Sie ein flaches Raster verwenden, müssen Sie jedes einzelne dieser 1024 Kästchen überprüfen, um festzustellen, ob überhaupt etwas darin ist Sie.

Wenn Sie jedoch einen verschachtelten Quad-Baum verwenden, kann Ihnen die oberste Ebene mitteilen, dass sich keine anderen Objekte im System befinden. Sie müssen sich also nur diese einzelne Box ansehen, um zu wissen, dass Sie keine Kollisionen finden tiefer im Baum - Sie können den Test sofort beenden.

Wenn die Objekte nur in bestimmten Regionen des Quad-Baums vorhanden sind, führt der Quad-Baum Ihre Suche natürlich nur durch potenziell relevante Kästchen, während Sie im Raster jedes einzelne geschnittene Kästchen überprüfen müssen, da Sie keine Möglichkeit haben, dies im Voraus zu wissen Welche Gitterquadrate enthalten Objekte? Wenn ein Großteil Ihres Quad-Baums leer ist und Sie große, komplizierte Abfragen durchführen (z. B. große Kamerastöße anstelle kleiner, einfacher Rechtecke), werden Sie möglicherweise feststellen, dass Sie insgesamt weit weniger Felder durchlaufen, wenn Sie dies tun Tests gegen etwas mit einer Baumstruktur anstelle eines flachen Gitters. Und das kann einen großen Unterschied machen.

All dies bedeutet natürlich nicht, dass eine Baumstruktur immer die richtige Wahl ist. Flache Gitter sind ideal für die Situation, die Sie in Ihrem Beispiel haben - dichte Wolken von Objekten verteilen sich ziemlich gleichmäßig überall auf der Welt, und wir führen einfache, kostengünstige Kollisionstests durch. In diesem Fall ist ein Raster wahrscheinlich der optimale Ansatz!

Trevor Powell
quelle
5
Lakonische Zusammenfassung für extrem Faule: Quadtrees verarbeiten Objekte unterschiedlicher Größe schneller.
Anko
Danke, das ist eine ausgezeichnete Antwort! Die einheitliche Größe der Objekte war etwas, das ich vermutete.
Chris
Tatsächlich müssen Sie normalerweise alle Ebenen des Quad-Baums durchsuchen, um zu überprüfen, ob keine Objekte vorhanden sind, da eine Ebene im Allgemeinen nur Informationen zu Objekten enthält, die beide vollständig in die Grenzen dieser Ebene passen und nicht in eine niedrigere Ebene passen.
Malthe
1
@malthe Wenn Sie darauf bestehen, eine Quad-Tree-Implementierung zu verwenden, die bei dieser Art von Abfrage nicht frühzeitig eingesetzt werden kann, verwenden Sie stattdessen unbedingt einen räumlichen Hash. Sie sparen 33% der Speicherkosten, und Sie hätten sowieso keinen Nutzen daraus gezogen. Alternativ können Sie Ihre idealogische Reinheit nur mit einem Hauch lockern und einen Quad-Baum verwenden, der frühzeitig ausgeführt werden kann, indem jeder Knoten die Anzahl der Entitäten in seinen untergeordneten Elementen verfolgt oder einen spärlichen Quadtree verwendet, sodass leere Knoten vorhanden sind vom Baum getrennt, bis sie gebraucht werden. Tatsächlich. Mehr als fünf Jahre später.
Trevor Powell
@ TrevorPowell natürlich hast du recht. Ich bin gerade über Ihre Garantie gefallen, dass Sie sich nur eine einzige Schachtel ansehen mussten. Dies ist einfach nicht wahr, weil Sie diese Zählungen verfolgen müssen. Sie können Kollisionen höher und weiter unten im Baum finden, soweit ich das beurteilen kann.
Malthe