Ebene

Aus DGL Wiki
Wechseln zu: Navigation, Suche
Wie man sich die Vektoren aus dem Text unten vorzustellen hat. Das grüne Gitter liegt auf der Ebene.
Neben Vektoren und Matrizen gehören Ebenen (englisch: Planes) zu den mathematischen Dingen, die man als 3D-Grafikprogrammierer unbedingt kennen sollte.

Was ist eine Ebene?

Ebenen kann man sich vorstellen wie unendlich große Vierecke (oder Dreiecke). Zum besseren Verständnis, kann dir der Bildschirm dienen, vor dem du, liebe(r) Leser(in), gerade sitzt. Stell dir vor, er wäre nicht nur ca. 50 cm breit und 30 cm hoch, sondern in beide Richtungen unendlich. Ist das nicht ein schöne Vorstellung? :D Nunja, an dieser Stelle muss ich deine eventuelle Hoffnung, nach diesem Artikel mehr Platz auf deinem Bildschirm zu haben, leider wieder zunichte machen. Ich wollte dir nur ein Bild dafür geben, wie man sich eine Ebene vorstellen kann.

Zumal es auch gravierende Nachteile hätte, wenn dein Bildschirm tatsächlich eine Ebene wäre. Denn eine Ebene hat keinen Rand - es geht ja in jede Richtung unendlich weit weiter. Somit würdest du nie mit dem Mauszeiger zur Taskleiste gelangen. Ecken hat eine Ebene natürlich genau so wenig.

Mathematisch betrachtet

Für Mathematiker ist eine Ebene nichts anderes als eine unendliche Menge von Punkten mit bestimmten Eigenschaften. Diese Eigenschaften lassen sich mit einer Gleichung beschreiben - der Ebenengleichung. Ein Punkt, der die Ebenengleichung erfüllt, liegt in (oder auf) der Ebene. Wenn er sie nicht erfüllt, d.h. wenn die Gleichung eine Ungleichung ist, liegt der Punkt nicht auf der Ebene.

Info DGL.png Zur besseren Unterscheidung werde ich im folgenden Fließtext Vektoren fett schreiben und Skalare normal. Dies gilt aus technischen Gründen nicht für die Gleichungen in den grauen Kästen.
Info DGL.png Es ist mathematisch nicht 100%ig korrekt, Punkte wie Vektoren zu behandeln und diese in eine Gleichung zu stecken. Mein Mathelehrer würde mich schlagen, wenn er das folgende lesen würde... Für das Verständnis von Ebenen ist diese Haarspalterei aber nicht nötig und würde nur zu mehr Unübersicht führen.

Parameterdarstellung

Es gibt mehrere äquivalente Arten, die Ebenengleichung aufzuschreiben. Eine sehr anschauliche Variante ist die Parameterdarstellung. Jeder Punkt x einer Ebene E lässt sich als so genannte Linearkombination zweier Richtungsvektoren darstellen:

E: x = p + s*u + t*v

Dabei ist p ein beliebiger Punkt, von dem man weiß, dass er auf der Ebene liegt. s und t sind zwei Skalare, also einfach reelle Zahlen. u und v sind linear unabhängige Richtungsvektoren. Stell dir z.B. ein dreidimensionales Koordinatensystem vor, dessen Achsen mit x, y und z beschriftet sind. Alle Punkte, an denen z=0 ist, liegen in einer Ebene. Um diese auch xy-Ebene genannte Ebene mit unserer Gleichung zu beschreiben, kann man z.B. den Koordinatenursprung (0,0,0) für p wählen - oder jeden anderen Punkt, bei dem z=0 ist. Der Einfachheit halber würde man nun u = (1,0,0) und v = (0,1,0) wählen. Egal welchen Punkt x du nun testest - wenn dieser in der Ebene liegt, wirst du immer ein s und ein t finden, sodass die Gleichung wahr ist.
Aus Programmierersicht ist diese Art der Ebenendarstellung zwar anschaulich, aber nicht sehr effizient. Schließlich müssten wir für jede Ebene 3 Vektoren à 3 Komponenten speichern - das ist Verschwendung, wie du im nächsten Abschnitt sehen wirst. Außerdem lassen sich viele Berechnungen in dieser Form nur sehr umständlich durchführen.

Normalenform

Eine bessere, aber noch nicht perfekte Darstellung benötigt nur noch zwei Vektoren, nämlich einen Normalenvektor und einen Punkt, der auf der Ebene liegt - also p aus dem vorigen Abschnitt. Der Normalenvektor n steht senkrecht auf der Ebene und würde in unserem Beispiel mit der xy-Ebene in Richtung der z-Achse zeigen. Es ist sehr leicht, von der Parameterform in die Normalenform umzurechnen. Denn p ändert sich nicht und n lässt sich mit dem Kreuzprodukt berechnen:

n = cross(u,v)

Doch wie sieht nun die Ebenengleichung mit n und p aus? Hier bedient man sich eines mathematischen Tricks: Das Punktprodukt zweier Vektoren, die senkrecht zueinander stehen, ist immer 0. Wir wissen bereits, dass n senkrecht auf der Ebene steht. Wenn x also in der Ebene liegt, dann ist der Verbindungsvektor von p zu x (also x-p) senkrecht zu n (denn p liegt per Definition in der Ebene). Und damit haben wir alles, was wir für die Gleichung brauchen:

E: dot(x-p, n) = 0

Wobei dot() die Funktion ist, die das Punktprodukt berechnet.

Hesseform

Die Hesseform ist die für den Programmierer optimale Darstellungsform einer Ebene. Sie benötigt lediglich einen Normalenvektor und einen Skalar. Wer will, kann das natürlich auch zu einem Vierkomponenten-Vektor zusammenfassen.
Unsere Gleichung in Normalenform lässt sich durch geschicktes Umformen in die Hesseform bringen. Wir starten bei

E: dot(x-p, n) = 0

Das dot() können wir auspacken:

E: (x1-p1)*n1 + (x2-p2)*n2 + (x3-p3)*n3 = 0

Dabei steht n1 für die erste Komponente von n (alternativ: n.x), p3 für die dritte Komponente von p (p.z) usw.
Weiteres Ausmultiplizieren erbgibt:

E: (x1*n1 + x2*n2 + x3*n3) - (p1*n1 + p2*n2 + p3*n3) = 0


Da der zweite Summand nicht von x abhängt, fassen wir ihn zusammen zum Koeffizienten d. Somit sieht die Gleichung so aus:

E: (x1*n1 + x2*n2 + x3*n3) + d = 0

Oder wieder anders geschrieben:

E: dot(x, n) + d = 0

Dabei ist

d = -(p1*n1 + p2*n2 + p3*n3) = -dot(p, n)


Diese Darstellungsform hat außer ihrer Speicherplatz-Sparsamkeit einen großen Vorteil: Wenn nämlich n die Länge 1 hat, dann lässt sich für jeden Punkt y der Abstand a zur Ebene mit dieser Formel berechnen:

a = dot(y, n) + d

Dir ist sicher aufgefallen, dass das genau die Gleichung von oben ist. Wenn man also wissen möchte, ob ein Punkt auf der Ebene liegt, prüft man eigentlich nur, ob der Abstand 0 ist. Logisch, oder? Aber mehr noch: Man kann auch prüfen, auf welcher Seite der Ebene ein Punkt liegt. Wenn für a nämlich ein positiver Wert herauskommt, dann liegt der Punkt "vor" der Ebene, bei einem negativen "hinter" ihr. "Vor" der Ebene heißt: Von der Ebene aus in Richtung des Normalenvektors n.

Ebene normalisieren

Eine Ebene ist normalisiert, wenn der Normalenvektor n die Länge 1 hat. Ist dies nicht der Fall, müssen wir n und d durch die Länge von n teilen. Die Hesseform einer normalisierten Ebene heißt hessesche Normalform. Wie bereits erwähnt, benötigt man die normalisierte Form, um den Abstand eines Punktes zur Ebene zu bestimmen. Wenn man nur wissen will, ob ein Punkt auf, vor oder hinter der Ebene liegt, ist die Normalisierung nicht notwendig!

Ebene eines Dreiecks bestimmen

Um eine Kollision zwischen Dreieck und einer Linie zu erkennen, muss man erst bestimmen, ob die Linie die Ebene des Dreiecks schneidet. Die Ebene E eines Dreiecks ist die Ebene, in der alle drei Eckpunkte - nennen wir sie a, b und c - liegen. Die Parameterform findet man folgendermaßen:

E: x = p + s*u + t*v

p = a;
u = b-a;
v = c-a;

Die Umformung in die Hesseform erfolgt dann, wie weiter oben beschrieben.

Anwendungsgebiete

Wie ich oben schon erwähnte, ist es für OpenGL-Programmierer unabdingbar, sich früher oder später mit Ebenen auseinanderzusetzen. Die Einsatzgebiete von Ebenen sind vielfältig. Hier ein paar Beispiele:

Naja, und wenn ihr aufs Gymnasium geht, werdet ihr es spätestens in der Oberstufe auch in der Schule brauchen.