Ich bin gerade dabei eine Octree klasse zu programmieren und bin da auf ein kleines Problem gestoßen. Und zwar bin ich jetzt schon so weit das meine Welt immer weiter in Boxen aufgeteilt wird, aber ich weiß nicht genau wie man prüfen kann ob ein Vertex sich inerhalb einer Bounding Box befindet.
Ich hab mir da bis jetzt folgendes überlegt: Man erstellt für jede Fläche der Box eine Ebene und prüft dann ob das Vertex sich inerhalb dieser 6 Ebenen Befinden. Nur find ich im Internet nicht genügend Informationen über Ebenen. Kann mir jemand ne Formel sagen womit ich die Infos für eine Ebene anhand eines Dreieckes kriege(Normale hab ich schon ) und wie ich dann teste ob sich ein Vertex vor oder hinter dieser ebene befindet.
Das mit der BBox geht einfacher, wenn es eine AABB ist, also wenn die Box an den Achsen ausgerichtet ist. Dann hat man ja zwei Punkte min und max. Ein Punkt p liegt dann innerhalb der Box, wenn gilt:
Code:
(p.x>=min.x) and (xp.<=max.x) and
(p.y>=min.y) and (p.y<=max.y) and
(p.z>=min.z) and (p.z<=max.z)
Bei den Ebenen hat man die Normale n und die Entfernung zum Ursprung s. Die Ebenengleichung sieht dann so aus: (n dot x) + d=0
Um die Entfernung eines Punkte p von der Ebene auszurechnen setzt man p in die Gleichung für x ein:
|n.x*p.x+n.y*p.y+n.z*p.z+d|= Entfernung von p von der Ebene (n,d)
Es gibt außerdem noch ein Mathe Tutorial, ein Octree Tutorial und auch verschiedene Mathe Units hier auf der Seite.
Registriert: Mi Aug 20, 2003 22:26 Beiträge: 38 Wohnort: Dresden (noch)
LarsMiddendorf hat geschrieben:
Code:
(p.x>=min.x) and (p.x<=max.x) and
(p.y>=min.y) and (p.y<=max.y) and
(p.z>=min.z) and (p.z<=max.z)
So einen Code, der vermutlich sehr oft ausgeführt wird, kann man dann natürlich noch optimieren, damit ihn die CPU schneller bearbeiten kann.
Mal ein Beispiel:
Code:
Var TestValue:Single;
TestAccess:Cardinal absolute TestValue;
begin
Result:=False;
TestValue:=((p.x-min.x)*(max.x-p.x)); If TestAccess >= $80000000 then exit;
TestValue:=((p.y-min.y)*(max.y-p.y)); If TestAccess >= $80000000 then exit;
TestValue:=((p.x-min.z)*(max.x-p.z)); If TestAccess >= $80000000 then exit;
Result:=True;
Das ist jedenfalls das schnellste was mir in Delphi direkt einfällt.
Mit dem Inline Assembler könnte man vielleicht noch etwas mehr rausholen, aber ich hab bis jetzt noch keinen Code geschrieben, da meine Kollisionen mit der Kugelmethode gut funktionieren.
Und wo ist da jetzt der Vorteil?
Die Vergleiche ersetzt du durch Subtraktionen und fügst zusätzlich noch drei Multiplikationen und drei Integervergleiche hinzu. Zusätzlich verhinderst du effizient, dass Testvalue vom Optimizer in einem Fließkommaregister gehalten werden kann (und Testaccess natürlich auch nicht in einem CPU Register).
Der ursprüngliche Code kann auch früher abbrechen, da man normalerweise davon aus gehen kann, dass full boolean evaluation ausgeschaltet ist.
Registriert: Mi Aug 20, 2003 22:26 Beiträge: 38 Wohnort: Dresden (noch)
Ich hab's getestet, es ist wirklich etwas schneller.
Wenn du's mir nicht glaubst, ich hab den Ansatz aus einem Tutorial für Assembly-Optimierung.
Hauptsächlich wird die "FCOMP FSTSW SAHF JNB" Kombination zum Testen von Fließkommazahlen vermieden, die je nach Prozessor auch mal 9-14 Takte dauern kann.
Durch die Subtraktionen und die Multiplikation führe ich jeweils zwei Tests in 9 Takten aus, der Integervergleich(1 Takt) und der konditionelle Sprung brauchen dann noch 2-3 Takte.
Wieso sollte man TestValue denn in einem Register halten? Zum Beginn jedes neuen Testes muss der alte Wert doch eh verworfen werden.
Bis auf das eine Speichern und Neuladen als Integer werden die Register eigentlich sehr effizient genutzt. Der Wert $80000000 wird außerdem direkt aus dem Code gelesen und muss nicht geladen werden.
Mitglieder in diesem Forum: 0 Mitglieder und 7 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.