nach langer Zeit beschäftige ich mich nun endlich mal wieder mit 3D Grafik/Programmierung und stoße sofort auf mein erstes Problem: Octrees Meine Implementierung läuft so ab, dass ich Zunächst alle Objekte (Daten) in die Wurzel speichere. Überschreiten diese eine gewisse Anzahl, so wird die Wurzel in 8 Teilbäume geteilt. Nun wird anhand von Bounding Boxes (Knoten VS Objekt) ermittelt, welches Objekt in welchen Teilbaum wandert. Ist hier wieder das Maximum überschritten, passiert das rekursiv so lange, bis alle Objekte ihren Platz gefunden haben. Ich glaube allerdigns nicht, dass das eine sonderlich schnelle Methode ist, einen Octree aufzubauen... Das Problem ist nun, dass die Anzahl der Kollisionen, die ich mit meinem Octree finde, nicht mit der tatsächlichen Anzahl an Kollisionen übereinstimmt. Zuerst waren es weniger, jetzt sind es mehr.
Die BoundingBoxes der Subbäume berechne ich wie folgt (sry leider Java):
Zunächst habe ich ein Array, in das ich alle 8 Richtungen speichere:
Code:
final static private Vector3d[] directions = { new Vector3d(-1, 1, -1), new Vector3d(-1, -1, -1), new Vector3d(1, -1, -1), new Vector3d(1, 1, -1), new Vector3d(-1, 1, 1), new Vector3d(-1, -1, 1), new Vector3d(1, -1, 1), new Vector3d(1, 1, 1)}; static private Vector3d size;
Die Variable size speichert die Größe des Octrees und wird so berechnet:
Code:
boundings = new BoundingBox(minimum, maximum); size = Vector3d.subtract(boundings.getMaximum(), boundings.getMinimum());
Und so bestimme ich die BoundingBoxes der Subbäume (ich denke hier liegt der Fehler):
Code:
private BoundingBox subTreeBounding(int index) { if ((index < 0) || (index >= 8)) { return null; } Vector3d a = Vector3d.add(boundings.getCenter(), Vector3d.multiply(directions[index], size.scale(0.5).abs())); Vector3d min; Vector3d max; if (Vector3d.lessThan(a, boundings.getCenter())) { min = a; max = boundings.getCenter(); } else { min = boundings.getCenter(); max = a; } return new BoundingBox(min, max); }
.abs() liefert den Vektor zurück, bei dem alle Komponenten positiv sind, also {|x|, |y|, |z|} und bei multiply handelt es sich um eine Komponentenweise Multiplikation. lessThan ist true, wenn alle Komponenten des ersten Vektors kleiner sind, als die des zweiten.
public Octree(Octree parent, BoundingBox b) { this.parent = parent; this.boundings = b; isLeaf = true; size = Vector3d.subtract(boundings.getMaximum(), boundings.getMinimum()); objects = new ArrayList<WorldObject>(); for (WorldObject wo : parent.objects) { if (boundings.intersect(wo.getBoundingBox())) { objects.add(wo); } }
divide(); }
Methode zum Zerlegen des Octrees:
Code:
private void divide() { if (objects.size() > limit) { isLeaf = false; for (int i = 0; i < 8; i++) { subTrees[i] = new Octree(this, subTreeBounding(i)); }
// TEST (ob alle Objekte ihren Platz gefunden haben) ArrayList<WorldObject> objs = new ArrayList<WorldObject>(); for (int i = 0; i < 8; i++) { for (WorldObject wo : subTrees[i].objects) { if (!objs.contains(wo)) { objs.add(wo); } } } if (objs.size() == objects.size()) { System.out.println("Korrekt"); // Das hier wird leider nie aufgerufen... :( } else { System.out.println(objs.size() + " sollte eigentlich " + objects.size() + " sein..."); } // TEST ENDE
objects.clear(); // erst löschen, wenn alle Subbäume durch sind } }
Also du hast mehr Objekte in objs als in objects, richtig? Wenn das der Fall ist liegt der Fehler nicht bei den BoundingBoxen, sondern wo anders. Dann selbst wenn die intersect-Methode immer true oder immer false zurück gibt bekommst du nicht mehr Objekte als vorher!
Bist du sicher das objs.contains(wo) wie erwartet funktioniert? Vielleicht ein Fehler beim überschreiben der equals-Methode?
Edit: Es ist ggf. sinnvoller statt diesen "directions" vielleicht lieben das Minimum der jeweiligen BoundingBox im Array zu haben. Das Maximum bekommst du dann indem du size drauf addierst. Das spart dir die ganzen min/max Operationen.
Meine Überlegung war ja, dass einer der beiden Eckpunkte der BoundingBox des Subbaums auf jeden Fall der Mittelpunkt der Boundingbox des Vaters sein muss. Aber das sollte bei deiner Überlegung eigentlich auch gewährleistet sein, ich werde das mal testen.
Zitat:
Edit: Es ist ggf. sinnvoller statt diesen "directions" vielleicht lieben das Minimum der jeweiligen BoundingBox im Array zu haben. Das Maximum bekommst du dann indem du size drauf addierst. Das spart dir die ganzen min/max Operationen.
Das habe ich leider nicht ganz verstanden, sry Diese Directions sollen mir eigentlich die (äußeren) Eckpunkte der neuen BoundingBoxes liefern. Die inneren Eckpunkte sind ja alle center.
Meine Überlegung war ja, dass einer der beiden Eckpunkte der BoundingBox des Subbaums auf jeden Fall der Mittelpunkt der Boundingbox des Vaters sein muss
Ne, eben nicht...C ist Center und X und Y sind die Ecken einer der BoundingBoxen. Es muss immer gelten Vector3d.lessThan(X,Y)! Die Achsen werden nach rechts bzw. oben größer.
Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.