QuadTree: Nur Punkte oder Regionen speichern?

9

Ich entwickle einen Quadtree, um sich bewegende Objekte für die Kollisionserkennung zu verfolgen. Jedes Objekt hat eine begrenzende Form, sagen wir, es sind alle Kreise. (Es ist ein 2D-Top-Down-Spiel)

Ich bin mir nicht sicher, ob ich nur die Position jedes Objekts oder die gesamte Begrenzungsform speichern soll.

Wenn Sie mit Punkten arbeiten, ist das Einfügen und Unterteilen einfach, da Objekte niemals mehrere Knoten umfassen. Andererseits kann eine Näherungsabfrage für ein Objekt Kollisionen übersehen, da die Abmessungen der Objekte nicht berücksichtigt werden. Wie berechne ich den Abfragebereich, wenn Sie nur Punkte haben?

Kollision zwischen Objekten benachbarter Knoten

Wie gehe ich bei der Arbeit mit Regionen mit einem Objekt um, das mehrere Knoten umfasst? Sollte es in den nächsten übergeordneten Knoten eingefügt werden, der es vollständig enthält, auch wenn dies die Kapazität des Knotens überschreitet?

Welcher Knoten soll das rote Objekt enthalten?

Vielen Dank.

Alekop
quelle

Antworten:

4

Wenn erweiterte Objekte (Regionen) in einem Quadtree gespeichert werden, sollte auf das Objekt von allen Blattknoten verwiesen werden, die es berührt. Ich würde nicht versuchen, den am wenigsten verbreiteten Vorfahren zu finden und dort zu speichern, da dann beispielsweise ein kleines Objekt, das zufällig eine Grenze auf hoher Ebene überschreitet, in einem sehr hohen Knoten landet und gegen alles andere in diesem großen Knoten getestet werden muss , Knoten auf hoher Ebene, wenn Sie Kollisionsabfragen und dergleichen ausführen.

Sie müssen jedoch auch vorsichtig sein, da große Objekte möglicherweise von vielen Knoten referenziert werden, was die Aktualisierung teuer macht, wenn sie sich bewegen, und dazu führt, dass sie viele Male auf Kollisionen usw. überprüft werden. Abhängig von Ihrem Anwendungsfall Es könnte sich lohnen, eine Art Heuristik zu verwenden, um große Objekte auf einer höheren Ebene im Baum zu speichern, aber dies würde die Algorithmen komplizieren, sodass ich mich wahrscheinlich nicht darum kümmern würde, wenn Sie nicht feststellen, dass es sich in Ihrem speziellen Fall wirklich um ein Leistungsproblem handelt.

Um eine Region abzufragen, sollte die Abfrage alle Blattknoten betrachten, die die abgefragte Region berührt.

Diese verwenden im Grunde den gleichen Algorithmus, der mit einer Region beginnt und diese durch den Baum nach unten drückt, um die Blattknoten zu finden, die sie berührt. Es ist eine Tiefenüberquerung, aber an jedem Knoten können Sie alle Kinder beschneiden, die die Region nicht berühren. Sie müssen einen Stapel verwalten, um zu verfolgen, wo Sie sich in der Durchquerung befinden.

Nathan Reed
quelle
Danke, das macht Sinn. Sicher, die Verarbeitung knotenübergreifender Objekte wäre langsamer als Objekte, die sich vollständig innerhalb eines Knotens befinden, aber ich sehe keinen Weg daran vorbei. Ich könnte die Knotenkapazität erhöhen, um die Fragmentierung gering zu halten, aber dies würde die Anzahl der Objekte erhöhen, die in der Kollisionserkennung enthalten sind. Ich werde damit herumspielen, um eine gute Balance zu finden.
Alekop
4

Sie müssen es auf dem kleinsten Knoten speichern, der es vollständig enthält - auch wenn dies die Kapazität überschreitet (verwenden Sie einen Container mit veränderbarer Größe).

DeadMG
quelle
2

Ich würde dies als Kommentar als Antwort auf die Antwort von @Nathan Reed hinzufügen, außer es ist zu groß, um ein Kommentar zu sein, und es ist vielleicht auf jeden Fall wert, eine separate Antwort zu sein.

Wir haben genau das getan, was in seiner Antwort vorgeschlagen wurde, und haben tatsächlich einen Kommentar in der Quelle, die auf diese Seite verweist. Zum größten Teil hat es sehr gut funktioniert, außer dass wir alle zwei oder drei Monate zufällig einen Server verloren haben, der aufgrund der massiven Dauer von Suchanfragen nicht mehr reagiert.

Die Hauptursache des Problems wurde mir bei einer Leistungsprüfung bewusst, um herauszufinden, was dies verursacht hat. Dies ist wahrscheinlich nur dann ein Problem, wenn Sie überlappende Objekte zulassen. In unserem Spiel tun wir dies, und im schlimmsten Fall führt dies gelegentlich zu einem Leistungsspitzen-Tiefenschub.

Wir hatten einen Randfall, in dem ungefähr 100 Objekte, alle mit Begrenzungsscheiben, in sehr unmittelbarer Nähe gruppiert waren. Dies führte zu dem Problem einer sehr tiefen Spitze im Baum, da wir an einem Punkt angelangt waren, an dem Objekte größer waren als der von den Quadtree-Knoten abgedeckte Bereich, sodass jedes neue Objekt in mehreren Knoten angezeigt wurde, was zu einer massiven Unterteilung des Baums führte Baum, wodurch das Problem außer Kontrolle gerät.

Die Konsequenz daraus ist, dass Sie, wenn Sie zulassen, dass sich Objektbereiche überlappen, die Dinge genau beobachten, wenn Sie enge Gruppen von Objekten erhalten, um sicherzustellen, dass Ihr Baum nicht zu tief wird.

Die Lösung, die ich derzeit untersuche, besteht darin, Objekte als Punkte zu speichern und dann bei einer Suche die Grenzen des Suchrechtecks ​​um den im Baum gespeicherten maximalen Radius zu erhöhen. Das sollte für uns funktionieren, da der Baum eine Suche in einem ersten Durchgang ist. Anschließend führen wir zusammen mit einigen anderen Kriterienprüfungen eine wahrheitsgemäße kreisförmige Bereichsprüfung durch, damit die zusätzlichen Fehlalarme herausgefiltert werden.

Ihr tatsächlicher Kilometerstand kann variieren.

dgnuff
quelle