Die naive Methode der Schnittpunktsuche führt eine lineare Suche auf allen Objekten der Szene durch, um den nächstgelegenen Schnittpunkt zu finden. Dies kann durch verschiedene Verfahren im Mittel, d.h. für eine Menge von Strahlen, beschleunigt werden.
Man kann den Schnittpunkttest in zwei Phasen unterteilen:
Man erreicht dies durch die Einführung von BoundingVolumes, d.h. einfachen geometrischen Körpern, die das eigentliche Objekt möglichst gut umschließen. Man wählt z.B. Kugeln oder achsenparallele Quader.
Um nun zu entscheiden, welches BoundingVolume man benutzt, eignet sich
die Definition der Passgenauigkeit:
Sei ein Objekt,
ein entsprechendes BoundingVolume.
Ferner sei
![]() |
die Anzahl der Teststrahlen, |
die das Volumen ![]() |
|
![]() |
die Testkosten für einen Strahl mit ![]() |
![]() |
die Anzahl der Treffer von ![]() ![]() |
![]() |
die Schnittkosten für einen Strahl mit ![]() |
Das Erstellen dieser Hierarchie kann einerseits
Quader eignen sich besser als Kugeln zum Aufbau hierarchischer BoundingVolumes, da im Mittel bei der Vereinigung zweier Quader das Volumen des resultierenden Quaders nicht so sehr ansteigt, wie es bei Kugeln der Fall ist.
Die Suchzeit kann pro Strahl weiterhin linear in der Anzahl der Objekte sein kann (man stelle sich die Objekte in einer Art Perlenkette aufgereiht vor).
Die Laufzeit bleibt also im schlechtesten Fall linear, im Mittel ist sie allerdings wesentlich geringer. Da die Verwendung der BoundingVolume auf jeden Fall eine Beschleunigung mit sich bringt, gehen wir in den folgenden Raumunterteilungsverfahren stets davon aus, dass mit BoundingVolumes gearbeitet wird (allerdings nicht notwendigerweise hierarchisch).
Unter einer Raumunterteilung verstehen wir die Unterteilung des dreidimensionalen Raumes, in dem sich die Objekte befinden, in kleinere Unterräume. Sind die Unterräume achsenparallele Quader, dann heißen die Unterräume Voxel. Zwei Voxel heißen ähnlich, wenn sie durch gleiche Skalierung der drei Achsen ineinander übergeführt werden können. Sind alle Voxel, die bei einer Aufteilung entstehen, ähnlich, sprechen wir von einer uniformen Unterteilung, im andern Fall von einer nicht-uniformen Unterteilung. Handelt es sich um eine mehrstufige Unterteilung, sprechen wir von einer hierarchischen Unterteilung, sonst von einer nicht-hierarchischen Unterteilung.
Damit ist klar, dass es verschiedene Raumunterteilungsverfahren gibt. Ziel jeder Unterteilung ist es, den Suchraum bei der Schnittpunktberechnung einzuschränken, indem jedem Unterraum nur die in im liegenden Objekte zugeordnet werden (hierzu sind eventuell Kopien notwendig). Durchstreift ein Strahl den Unterraum, brauchen nur diese wenigen Objekte als Kandidaten für einen Schnittpunkt untersucht zu werden.
Um zu verhindern, dass der exakte Schnittpunkt eines Strahls mit einem Objekt mehrfach berechnet wird, wenn das Objekt mehrere Voxel schneidet, merkt man sich Strahlnummern und die zuletzt berechneten Schnittpunkte. Vor einer erneuten Schnittpunktberechnung testet man nun zuerst die Strahlnummer mit dem aktuellen Strahl und spart sich so eine erneute Berechnung. Weiterhin muss man darauf achten, dass der Schnittpunkt im aktuellen Voxel liegt. Dies ist eine notwendige Bedingung für den nächsten Schnittpunkt.
Bemerkung: Die hier verwendeten Definitionen entsprechend nicht den in der Literatur sonst üblichen Definitionen. Dort wird meist das, was hier hierarchisch ist, als nicht-uniform und das, was hier nicht-hierarchisch ist, als uniform bezeichnet.
Die Beschreibung enthält stets eine grobe Abschätzung des Aufwandes, der bei der Schnittpunktberechnung notwendig ist. Dabei wird immer von einer regelmäßigen oder zufälligen Anordnung vieler relativ kleiner Objekte ausgegangen. Zufällig soll hier nicht formal eingeführt werden, sondern damit soll lediglich gesagt werden, dass man erwartet, in einem beliebigen, nicht zu kleinen, aber konstantem Raumvolumen im Wesentlichen die gleiche Anzahl von Objekten vorzufinden, die diesen Unterraum schneiden.
Die Anzahl der Objekte der Szene sei . Müssen durch die
Raumunterteilung Objektinformationen kopiert werden, so bezeichne
den Faktor, um den sich die Objektinformation erhöht.
Als Beispiel nehme man an, dass jedes Voxel einen Zeiger auf jedes
Objekt enthält, welches das Voxel schneidet. Müssen 10 % der
Zeiger dupliziert werden, ist
.
Desweiteren sei
die Anzahl der Unterräume, die ein Strahl
im Mittel trifft, wenn er die Szene durchläuft.
Die Schnittpunktsuche beginnt in dem Voxel, das den Aufpunkt des Strahles enthält. Trifft er kein Objekt innerhalb des Voxels, wird das nächste Voxel mithilfe eines modifizierten BRESENHAM-Algorithmus bestimmt und die Suche dort fortgesetzt.
Grobe Abschätzung des Berechnungsaufwandes:
Gehen wir von vielen Voxeln aus. In jedem Voxel liegen dann
viele Objekte.
Für einen Strahl sind im Mittel
Voxel zu testen. Bei einer
Durchquerung der Szene können höchstens
viele Voxel geschnitten werden.
Für sehr dicht besetzte Szenen kann man davon
ausgehen, dass die Anzahl der durchquerten Voxel unabhängig von
ist; die Anzahl der geschnittenen Voxel kann dann sogar als Konstante
auftreten.
Als Berechnungszeit für die Schnittpunktbestimmung ergibt sich also zu
Im Falle ,
und
ergibt sich also eine Reduzierung auf
das 0.0065-fache der Zeit der naiven linearen Testmethode.
Hierbei wurden weitere Konstanten vernachlässigt. Allerdings sind diese
nicht wesentlich größer als bei der linearen Suche, da man genau
diese innerhalb der Voxel auch benutzt und das Finden der Voxel mithilfe
des BRESENHAM-Algorithmus sehr schnell geht.
Der Speicherplatz erhöht sich linear, da für jedes
Objekt ein Verweis in mindestens einem Voxel gehalten werden muss.
Sind allerdings Kopien notwendig, erhöht sich der Platz auf
, was im schlechtesten Fall zu
führen kann.
Die Laufzeitabschätzung ist ähnlich der des Grid, nun jedoch mit
unterschiedlichen Einteilungen in den drei Raumrichtungen. Man
erhält also
Für den BRESENHAM-Algorithmus müssen nun auch die
Intervallängen der Einteilungen in X-, Y- und Z-Richtung
gespeichert werden, was den Platzbedarf um erhöht
(was bei vielen Objekten vernachlässigt werden kann).
Ansonsten steigt der Platzbedarf wie beim Grid.
Die Abbildung zeigt einen Quadtree (das zweidimensionale Analogon) mit der Abbruchbedingung, dass keine weitere Unterteilung im Falle von zwei Objekten im Unterraum stattfindet.
Wiederum werden jedem Voxel als Blatt im Baum `seine' Objekte mitgeteilt. Dies bedeutet, dass ebenfalls Information kopiert werden muss, wenn ein Objekt mehrere Voxel schneidet.
Wenn sich Objekte überlappen können, muss ein weiteres Kriterium als Rekursionsabbruch beim Aufbau des Octree berücksichtigt werden, da die vorgegebene minimale Anzahl nicht notwendigerweise erreicht werden muss: es kann vorkommen, dass eine weitere Unterteilung keine Reduktion der Objektanzahl in einem Voxel mit sich bringt.
Als mögliche Kriterien können z.B. genutzt werden:
Die Schnittpunktberechnung startet wieder in dem Voxel, welches den Aufpunkt des Strahles enthält. Dieses wird durch einen `top-down'-Lauf durch den Baum gefunden. Das Auffinden des nächsten Voxel, das der Strahl beim Verlassen des vorhergehenden betritt, wird wie folgt gefunden:
Grobe Abschätzung des Berechnungsaufwandes:
Sei die Baumtiefe des Octree. Da die Objekte regelmäßig/zufällig
verteilt sind, ist der Baum im Wesentlichen balanciert. Es gibt somit
Voxel als Blätter, die Objektinformation enthalten müssen.
Sei
der Faktor auf den sich die Objektanzahl bei der Unterteilung
eines Voxel erhöht. Für einen Baum der Tiefe
erhöht sich
die Objektanzahl auf
Für jeden Voxel muss
ein `top-down'-Lauf durch den Baum implementiert werden, was langsamer
als ein Auffinden des nächsten Voxel mithilfe des BRESENHAM-Algorithmus
ist: man erhält , also als Maximum mit
ergibt sich
.
Ist die Anzahl der Voxel als Blätter des Octree gleich der Anzahl der
Voxel im Grid, dann ergeben sich die gleichen Laufzeiten bei der
Schnittpunktsuche. Nur im Auffinden des nächsten geschnittenen Voxels
verliert man mehr Zeit beim Octree als beim Grid. Der Faktor des
Grid entspricht dem Faktor
des Octree, da die
Blätter des Octree den Raum analog zu einem Grid aufteilen.
Somit ist klar, dass der Octree dem Grid nicht überlegen ist, wenn es sich um regelmässige/zufällige Szenen handelt. Der Octree gewinnt erst, wenn es sich um unregelmäßige, clusterartige Objektansammlungen handelt und man durch den Octree schnell große Raumbereiche durchdringen kann. In diesem Fall ist es möglich--durch nicht balancierte Bäume--die Zahl der in einem Blatt gespeicherten Objekte für alle Voxel als Blätter eher gleich zu halten oder auch sehr klein.
Die Schnittpunktsuche erfolgt analog zu dem Verfahren, wie es für den Octree beschrieben worden ist. Die Laufzeitabschätzung für einen BSP-tree entspricht bei der vorgegebenen Szenenbeschreibung der des Octree, da aufgrund der Objektverteilung die Schnittebenen mehr oder weniger an die gleiche Stelle gelegt werden.
Ein BSP-tree hat also auch nur den Vorteil, eine gleichmäßigere Aufteilung der Objekte auf die Voxel als Blätter zu ermöglichen. Dies erweist sich jedoch bei clusterartigen Objektanordnungen als deutlicher Vorteil.
PlaneTraversal arbeitet wie folgt. Jede Seitenfläche eines
BoundingVolumes (wir setzen Quader als BoundingVolumes voraus)
definiert eine Ebene. Man erhält also
viele
Ebenen. Jede Ebene kennt ihr Objekt. Die Ebenen sind entsprechend
ihrer Koordinate sortiert. Der Strahl durchläuft das Voxel--dabei
werden die Ebenen geschnitten--und
aktiviert bzw. deaktiviert ein entsprechendes Bit je Koordinate
pro BoundingVolume
je nachdem, ob das BoundingVolume des Objektes potentiell in dieser
Koordinate betreten oder verlassen wird. Sind alle drei Bits aktiviert,
wird das BoundingVolume getroffen und ein Schnittpunkttest kann erfolgen.
Man kann die Suche abbrechen, sobald eine Ebene getroffen wird, die
hinter dem letzten gefundenen Schnittpunkt liegt.
Da dieses Verfahren sehr effizient implementiert werden kann, arbeitet es bis zu einer gewissen Objektanzahl schneller als ein Verfahren mit hierarchischen BoundingVolume.
Überlappen sich BoundingVolume stark, ist es nicht unbedingt sinnvoll ein übergeordnetes BoundingVolume zu konstruieren, da für die meisten Strahlen sowieso beide getestet werden müssen. In diesem Fall erweitert man die hierarchische BoundingVolume-Struktur dadurch, dass man an den Knoten mehr als zwei Söhne zulässt. Bei der Schnittpunktsuche muss dann jedoch stets die gesamte Liste der Söhne durchsucht werden. Dies kann jedoch wiederum schnell mit PlaneTraversal erfolgen.
Eine einfache Modifizierung des Octree, die nicht nur 8 Unterräume pro Unterteilung eines Voxels erzeugt und damit eventuell Objektinformation kopieren muss, besteht darin, alle durch Schnittebenen des Octree (oder auch eines BSP-tree) geschnittenen Objekte in ein eigenes Voxel (Universum) zusammenzufassen. Dabei können also je Unterteilungsschritt bis zu 27 Unterräume entstehen. (In jedem Unterraum sind die Objekte zusammengefasst, die durch die gleichen Schnittebenen des Octree geschnitten werden.)
Man beachte, dass sich nun die entstandenen Voxel durchdringen können, und man somit das oben erläuterte Verfahren mit sich überlappenden BoundingVolumes nutzen muss.
Die Raumunterteilung erfolgt nun rekursiv, abwechselnd in den fünf Dimensionen. Die Hauptachsenrichtung spielt natürlich auch eine Rolle und bewirkt eine Multiplikation mit 6. In den ersten drei Dimensionen entstehen Voxel analog zum Octree-Verfahren. In den anderen beiden Dimensionen entstehen Pyramiden. Die Objekte werden wiederum jedem Raumbereich zugeordnet. In den Pyramiden werden die Objekte zusätzlich in der Richtung der Pyramide sortiert, so dass der nächstgelegene Schnittpunkt schneller gefunden werden kann.
Das Verfahren traversiert also den entstehenden Baum und bestimmt jeweils in welchen Raumbereich der Strahl fällt. An einem Blatt wird dann der Schnittpunkt berechnet. Der Speicherplatzverbrauch dieser Methode ist erheblich, da sich die Pyramiden deutlich überlappen. Man kann fast sagen, dass jedes nur durch die ersten drei Raumdimensionen erzeugte Voxel den gesamten Objektraum sieht, d.h. die Anzahl der Blätter eines Octree (bezüglich der X-, Y- und Z-Koordinate entsteht gerade ein Octree) bestimmt, wie oft die Objektinformationen kopiert werden müssen, da man von einem solchen Voxel, den gesamten Raum sehen kann. Eine Reduzierung erhält man durch einen adaptiven Aufbau der Datenstruktur mit `caching'-Strategien (`lazy evaluation'). Einen interessanten Beschleunigungseffekt erhält man auch durch die Begrenzung der Ausdehenung der Pyramiden. Jeder Raumpunkt sieht praktisch nur eine gewisse Distanz weit, d.h. für jeden Punkt können sehr weit entfernte Objekte vernachlässigt werden. Bei den Lichtquellen wurde diese Methode weiter oben bereits vorgestellt: es wird nur das erste getroffene Objekt in einem Raumwinkel gespeichert, da alle dahinterliegenden automatisch in Schatten liegen.
Als grobe Laufzeitanalyse erhält man, wiederum für eine große Anzahl regelmäßig/zufällig verteilter, kleiner Objekte:
Wir nehmen an, dass der Baum balanciert aufgebaut ist. Dann liegen
in jeder Pyramide etwa gleich viele Objekte.
Sei wiederum der
Faktor, der angibt um wieviel die Anzahl der Objekte vergrößert
werden muss, wenn eine Unterteilung in allen fünf Dimensionen
erfolgt ist. Wir nehmen der Einfachheit wegen an, dass
in jedem Rekursionsschritt die Anzahl der Objektinformationen
um den gleichen Faktor
steigt.
Sei die Tiefe des Baumes, wobei in jeder Dimension unterteilt
worden ist. Mit jedem Rekursionsschritt wächst die Anzahl der Blätter also
um den Faktor
.
In einer Pyramide als Blatt liegen also
Bei der Schnittpunktberechnung wird ein Pfad des Baumes mit
Länge (wegen der Unterteilung in allen Dimensionen)
durchlaufen, allerdings braucht nur ein Blatt untersucht zu werden, da
der Strahl ganz in einer Pyramide verläuft. Man erhält also: