Binary Space Partitioning (BSP; deutsch binÀre Raumpartitionierung oder BSP-Baum) ist eine Technik in der Informatik zur Partitionierung multidimensionaler Daten durch eine Menge von Hyperebenen. Die so erstellte Datenstruktur ist ein BinÀrbaum und wird BSP-Baum genannt.
Die wohl verbreitetste Anwendung von BSP-BĂ€umen ist die rĂ€umliche Unterteilung geometrischer Objekte. BSP findet vor allem Verwendung bei Grafik-Engines von Computerspielen fĂŒr Objekte oder Teile der âWeltâ, die sich wĂ€hrend des Spiels geometrisch nicht mehr verĂ€ndern. Eine weitere Anwendung findet sich beim Raytracing.
Ein Spezialfall der BSP-BĂ€ume sind k-d-BĂ€ume, oft auch als axis-aligned BSP-Trees (achsenparallele BSP-BĂ€ume) bezeichnet. Bei kd-BĂ€umen sind die unterteilenden Hyperebenen immer entlang der Achsen des Koordinatensystems ausgerichtet.
Verfahren
[Bearbeiten | Quelltext bearbeiten]Beim BSP wird der gesamte Raum anfangs durch eine (zunĂ€chst beliebig wĂ€hlbare) Teilungsebene in zwei Teile geteilt. FĂŒr beide HalbrĂ€ume wird dann das gleiche gemacht wie zuerst mit dem gesamten Raum, das heiĂt, die Welt wird rekursiv immer weiter unterteilt. Jeder innere Knoten des BinĂ€rbaumes reprĂ€sentiert somit eine Teilungsebene, wĂ€hrend die zwei TeilbĂ€ume eines inneren Knotens dann jeweils einen Teil des Raums reprĂ€sentieren. Das Ende der Unterteilung ist meist dann erreicht, wenn in einem Teilraum nur mehr ein Datenelement der Ausgangsmenge (z. B. ein geometrisches Grundobjekt wie ein Dreieck oder Polygon) vorhanden ist.
Die Teilungsebenen fallen aus praktischen GrĂŒnden oft mit den Polygonen der geometrischen Objekte zusammen. Beim Erstellen des BSP-Baums wird dann ein Polygon aus dem aktuellen Teilraum gewĂ€hlt, mit dessen Ebene der Teilraum weiter unterteilt wird. Dabei wird einerseits darauf geachtet, dass sich ungefĂ€hr gleich viele Polygone auf jeder Seite der gewĂ€hlten Ebene befinden, andererseits, dass möglichst wenige Polygone des Teilraumes durch die Ebene zerschnitten werden, weil das Zerschneiden zu mehr Polygonen fĂŒhrt, wodurch sich die benötigte Zeit erhöht, um z. B. die Polygone zu zeichnen. Ziel bei der Erstellung des BSP-Baumes ist es, einen Baum zu erzeugen, welcher bei der spĂ€teren Traversierung ein optimales Laufzeitverhalten aufweist. Ăblicherweise wird versucht, dies durch die Erzeugung eines balancierten Baumes zu erreichen.
Die Daten der Ausgangsmenge können entweder ausschlieĂlich in den BlĂ€ttern des Baumes oder sowohl in den BlĂ€ttern als auch in den inneren Knoten gespeichert sein â beispielsweise, indem das Polygon, das zur Teilung verwendet wurde, einem der beiden entstandenen TeilrĂ€umen zugeschlagen wird oder direkt im gleichen Datenelement wie die Ebene gespeichert wird. Man nennt den BSP-Baum dann leaf-based (âblattbasiertâ) bzw. node-based (âknotenbasiertâ).
Anwendungen und Alternativen
[Bearbeiten | Quelltext bearbeiten]Durch die BSP-Technik können viele Berechnungen, wie Kollisionserkennung oder die Verdeckungsberechnung von Polygonen, wesentlich schneller erfolgen. Beispiele fĂŒr die Verwendung von Binary Space Partitioning in Computerspielen sind die Game Engine der Super-NES-Version von Wolfenstein 3D,[1] sowie die Game Engines von Doom (dabei handelt es sich um zweidimensionales BSP, d. h. die Teilungsebenen sind Teilungsgeraden), der Quake-Reihe und von Doom 3.
Beim Raytracing werden BSP-BĂ€ume als Beschleunigungstechnik verwendet, um nur bei möglichst wenigen Primitiven einen Schnittpunkttest durchzufĂŒhren.
Weitere Methoden zur hierarchischen Unterteilung des Raumes sind Quadtrees und Octrees.
Algorithmus fĂŒr eine Liste von Polygonen
[Bearbeiten | Quelltext bearbeiten]Der folgende rekursive Algorithmus erstellt einen BSP-Baum fĂŒr eine Liste von Polygonen in der Ebene:[2]
- WĂ€hle ein Polygon P aus der Liste aus.
- Erzeuge einen Knoten N im BSP-Baum und fĂŒge P in die Liste der Polygone an diesem Knoten hinzu.
- FĂŒhre fĂŒr jedes andere Polygon in der Liste folgende Schritte aus:
- Wenn dieses Polygon vollstÀndig vor der Ebene liegt, die P enthÀlt, verschiebe dieses Polygon in die Liste der Knoten vor P.
- Wenn dieses Polygon vollstÀndig hinter der Ebene liegt, die P enthÀlt, verschiebe dieses Polygon in die Liste der Knoten hinter P.
- Wenn dieses Polygon von der Ebene geschnitten wird, die P enthÀlt, teile es in zwei Polygone auf und verschiebe sie in die jeweiligen Listen von Polygonen hinter und vor P.
- Wenn dieses Polygon in der Ebene mit P liegt, fĂŒgen Sie es der Liste der Polygone an Knoten N hinzu.
- Wende diesen Algorithmus auf die Liste der Polygone vor P an.
- Wende diesen Algorithmus auf die Liste der Polygone hinter P an.
Die Abbruchbedingung fĂŒr die Rekursion ist erreicht, wenn die Liste der Polygone vor P oder die Liste der Polygone hinter P leer ist.
Beispiel 1
[Bearbeiten | Quelltext bearbeiten]Aufbauen des Baumes
[Bearbeiten | Quelltext bearbeiten]
In Abbildung 1 ist ein Beispiel fĂŒr die Zerlegung eines Raumes mit vier Strecken zu sehen. In dem rötlichen Kasten sieht man den daraus resultierenden binĂ€ren Baum.
ZunĂ€chst teilt Strecke 1 den Raum in zwei HalbrĂ€ume (gekennzeichnet durch die blau gestrichelte Linie) und die Strecke 2 in die beiden Teilstrecken 2a und 2b. Die Orientierung der Normalen der Strecken klassifiziert die beiden HalbrĂ€ume nun als einen Halbraum vor der Strecke und einen Halbraum dahinter. Folglich werden die (Teil)-Strecken, die sich davor befinden, in den linken, die, die sich dahinter befinden, in den rechten Teilbaum des Baumes eingefĂŒgt und mit den beiden entstehenden HalbrĂ€umen fortgefahren.
Betrachtet man zunĂ€chst die Strecke 2b, so teilt diese den Raum wieder in zwei HalbrĂ€ume vor Strecke 1. Jedoch befindet sich keine weitere Strecke im selben Halbraum vor ihr (Strecke 4 wurde durch die Zerlegung von Strecke 1 in den Bereich hinter Strecke 1 âverbanntâ). Hinter Strecke 2b befindet sich mit der gleichen Argumentation ebenfalls nichts mehr, das in den Baum eingeordnet werden mĂŒsste und das Verfahren terminiert fĂŒr diesen Teilbaum.
Strecke 2a hingegen teilt den Raum wieder in zwei TeilrÀume und Strecke 4 wird in den Halbraum davor, Strecke 3 in den Halbraum dahinter eingeordnet.
Die Strecken 3 und 4 zerteilen den Raum zwar erneut in jeweils wieder zwei HalbrĂ€ume, fĂŒgen jedoch nichts weiter in den Baum ein, so dass der Baum im rötlichen Kasten entstanden ist.
Durchlauf des Baumes
[Bearbeiten | Quelltext bearbeiten]Nimmt man nun den Betrachter dort an, wo sich der Kasten mit dem BSP-Baum befindet (die Blickrichtung ist hier nicht weiter wichtig), so ergibt sich die Durchlauf- und damit Zeichenreihenfolge der Strecken wie folgt:
Beginnend von der Wurzel (Knoten 1), werden zunĂ€chst die Knoten, die vom Betrachter aus gesehen hinter dieser Strecke liegen, gezeichnet, anschlieĂend die Strecke selbst und danach die Strecken, die sich vor der Strecke â also auf der Seite des Betrachters â befinden.
Im vorliegenden Fall sieht der Durchlauf des Baumes wie folgt aus:
3, 2a, 4, 1, 2b
ZunĂ€chst betritt man den Baum ĂŒber die Wurzel (1). Nun muss man zunĂ€chst alle Strecken hinter der Strecke 1 zeichnen und begibt sich also in den rechten Teilbaum und landet dort bei der Wurzel 2a. Nun muss man auch dort erst die Knoten hinter dieser Wurzel zeichnen und steigt wieder in den rechten Teilbaum ab und landet beim Knoten 3. Dieser ist ein Blatt und kann sofort ausgegeben werden. Danach wird Strecke 2a gezeichnet und anschlieĂend die Knoten davor â also 4. Nun ist auch dieser Teilbaum abgearbeitet und man zeichnet schlieĂlich die Knoten 1 und 2b.
Beispiel 2
[Bearbeiten | Quelltext bearbeiten]
In der Computergrafik wird der BSP-Baum hĂ€ufig auch zum Speichern von Informationen ĂŒber die Geometrie eines Objektes benutzt. Derartige BSP-BĂ€ume werden manchmal als leaf-storing BSP trees bezeichnet, da die Informationen vorrangig in den BlĂ€ttern abgelegt werden. Die nebenstehende Abbildung beschreibt die Erstellung eines solchen Baumes. Es ist zu beachten, dass die Normale der Kanten (werden fĂŒr die Zuordnung auf der Vorder- oder RĂŒckseite) alle in Richtung inneres des Objektes (Raumes) zeigen.
Aufbauen des Baumes
[Bearbeiten | Quelltext bearbeiten]Zu Beginn wird das Objekt an einer beliebigen Kante, hier die Kante D, unterteilt und als Wurzel fĂŒr den BSP-Baum benutzt. Es ist zu beachten, dass die Auswahl der Startkante mit entscheidend fĂŒr die spĂ€tere Traversierungsgeschwindigkeit ist, welche deutlich besser bei einem balancierten Baum ist. Im Folgenden werden alle verbleibenden Kanten in vor bzw. hinter dem Knoten D gelegen eingeteilt. FĂŒr diese Entscheidung wird hĂ€ufig, wie auch hier, die Normale der Gerade genommen, welche in Richtung vor dem Objekt zeigt. Wie bereits zuvor erwĂ€hnt, zeigen alle Normalen der Kanten in diesem Beispiel in das Innere des Objektes. Wie in diesem ersten Schritt zu sehen ist, wird die Kante A und die Kante G in jeweils zwei Teile unterteilt, da diese sich mit der ins Unendliche verlĂ€ngerten Kante D schneiden. Damit ergibt sich der aktuelle Baum:
D
/ \
A1,G2,H,I,J,K,L,M,N,O,P A2,B,C,E,F,G1
Im Folgenden werden nun die TeilbĂ€ume wieder unterteilt. In dem Beispiel der Teilbaum: A1,G2,H,I,J,K,M,N,O,P. Es wird die Kante N ausgewĂ€hlt und die restlichen Kanten des Teilbaumes wieder entsprechend in Vorder- und RĂŒckseite der Kante N eingeteilt. Auch in diesem Schritt mĂŒssen wieder Kanten (Kante A1 und Kante K) unterteilt werden. Das TeilstĂŒck A1 der Kante A wird noch einmal in zwei Teile unterteilt.
Damit ergibt sich der aktuelle Baum:
D
/ \
N A2,B,C,E,F,G1
/ \
A12,G2,H,I,J,K1 A11,K2,L,M,O,P
Unter der Verwendung der Kante I wird der linke Teilbaum unterhalb von Knoten N wieder nach oberem Schema unterteilt. Dies ergibt den folgenden Baum:
D
/ \
N A2,B,C,E,F,G1
/ \
I A11,K2,L,M,O,P
/ \
A12 G2,H,J,K1
Da der linke Teilbaum nur ausschlieĂlich aus dem Knoten A12 besteht, kann der linke Ast nicht weiter unterteilt werden, und somit wird der rechte Zweig vom Knoten I abgearbeitet. Es wird die Kante J fĂŒr die Unterteilung gewĂ€hlt und die Kanten in diesem Teilraum entsprechend wieder in linker und rechter Teilbaum eingeordnet. Hieraus ergibt sich der folgende Baum:
D
/ \
N A2,B,C,E,F,G1
/ \
I A11,K2,L,M,O,P
/ \
A12 J
/ \
K1 G2,H
Nachdem nun der linke Teilbaum unter Knoten J vollstĂ€ndig verarbeitet wurde, der linke Teilbaum besteht nur aus einem Knoten, hier K1, wird mit dem rechten Teilbaum fortgefahren. Es wird Kante H gewĂ€hlt und der resultierende Baum sieht folgendermaĂen aus:
D
/ \
N A2,B,C,E,F,G1
/ \
I A11,K2,L,M,O,P
/ \
A12 J
/ \
K1 H
/
G2
Identisch wird fĂŒr alle weiteren TeilbĂ€ume, welche mehr als einen Kind-Knoten besitzen, vorgegangen. Am Ende wĂ€re eine mögliche Lösung fĂŒr den BSP-Baum:
D
/ \
/ \
/ \
/ \
/ \
/ \
/ \
N E
/ \ / \
/ \ / \
/ \ / \
/ \ / \
I O F C
/ \ / \ / /
A12 J P L G1 B
/ \ / / /
K1 H A11 M A2
/ /
G2 K2
Es ist zu beachten, dass der vorhergehend erstellte BSP-Baum nur eine mögliche Lösung darstellt. Da eine Kante fĂŒr die Unterteilung des Baumes gewĂ€hlt werden muss, beginnend mit der Kante fĂŒr die Wurzel, hin zu einer Kante fĂŒr die Unterteilung der Kinder eines jeden Knotens, kann eine Vielzahl von BSP-BĂ€umen konstruiert werden, welche den Raum korrekt unterteilen. Je nach Anwendung kann die LeistungsfĂ€higkeit im Hinblick auf Traversierung der verschiedenen BSP-BĂ€ume stark schwanken. In den meisten FĂ€llen wird versucht, die Erzeugung eines entarteten Baumes zu vermeiden.
Siehe auch
[Bearbeiten | Quelltext bearbeiten]Literatur
[Bearbeiten | Quelltext bearbeiten]- Henry Fuchs u. a.: On Visible Surface Generation by A Priori Tree Structures. In SIGGRAPH â80 Proceedings, S. 124â133. ACM, New York 1980, ISBN 0-89791-021-4
- Christer Ericson: Real-Time Collision Detection (The Morgan Kaufmann Series in Interactive 3-D Technology). Verlag Morgan Kaufmann, S. 349â382, Jahr 2005, ISBN 1-55860-732-3
- Fabien Sanglard: Game Engine Black Book â DOOM. 1.2. Auflage. 2022, ISBN 979-83-6246944-3, 5.12 3D Renderer (englisch, sowie online https://github.com/fabiensanglard/gebbdoom).
Weblinks
[Bearbeiten | Quelltext bearbeiten]- BSP FAQ (englisch)
- Java-Applet zu BSP
Einzelnachweise
[Bearbeiten | Quelltext bearbeiten]- â Fabien Sanglard: Game Engine Black Book â Wolfenstein 3D
- â GeeksforGeeks: Binary Space Partitioning
