Matrix

Aus DGL Wiki
Wechseln zu: Navigation, Suche

Matrix / Matrizen

Übersicht

Eine Matrix ist im wesentlichen nichts anderes als das, was man in der Programmierung als zweidimensionales Array kennt. Dabei beschreibt eine Matrix eine lineare Abbildung, was als Information bei Rechnungen sehr wichtig ist.

Wichtig: Für den Einstieg in OpenGl ist ein tiefergehendes Verständnis von Matrizen noch nicht notwendig um bereits interessante Ergebnisse zu erzielen. Es genügt am Anfang zu wissen, dass man damit Verscheibungen, Drehungen und Streckungen beschreiben kann und dass die Reihenfolge der Befehle zum Manipulieren der Matrix wichtig ist. Wer also noch seine ersten Erfahrungen mit OpenGl macht, kann sich zuerst in unseren Tutorials informieren und erst anschließend hier wieder vorbeischauen.

Anmerkung: Wir wollen mit den Definitionen hier nur soweit gehen, wie es für ein Verständnis von OpenGl Geometrie wichtig ist. In der Linearen Algebra werden einige der hier gegebenen Begriffe deutlich genauer und häufig auch abstrakter betrachtet. Dies würde jedoch unseren kleinen Rahmen deutlich sprengen.

Definition

Matrizen sind Abbildungen auf Vektorräumen ganzzahliger Dimension. Für alle weiteren Betrachtungen seien deshalb die Zahlen n,m und r aus dem Bereich {1,2,3,4,5,...}, also den natürlichen Zahlen ohne Null, fest vorgegeben.

Rn Vektorräume

Um Matrizen definieren zu können, müssen wir zuerst Vektorräume definieren. Ein Vektorraum (V,*,+) ist eine Menge Vektoren V zusammen mit einer Skalar-Multiplikation * und einer Addition auf Vektoren, auf denen man vernünftig Vektorrechnung betreiben kann.

Hat man also zwei Vektoren v und w, so kann man diesen eindeutig einen Summevektor x zuordnen:

Vektor summe.png

Außerdem kann man sie mit einem Skalar c aus den reelen Zahlen zu einem Vektor x' strecken:

Vektor skalar.png

Beispiel: Der Standardvektorraum Rn: Ein Vektor v aus dem Rn besteht aus n reelen Zahlen ( seinen Komponenten vi), deren Reihenfolge wichtig ist und auch n-tupel genannt wird. Man kann also v auch in Form seiner Komponenten schreiben:

Vektorkomponenten.png

Häufig wird kein Unterschied dahingehend gemacht, ob der Vektor als Zeile oder als Spalte geschrieben wird. Bei der später definierten Matrixmultiplikation wird dies jedoch durchaus interessant, wir wollen uns also erstmal darauf beschränken, dass auch die Schreibweise

Vektortranspos.png

für unseren Vektor v eine legitime, als Text einfacher verfassbare Schreibweise darstellt. Bei der später definierten Multiplikation mit einer Matrix der Vektor aber immer als Spalte betrachtet wird.

Um unseren Vektorraum zu vervollständigen, brauchen wir nach Definition nun auch noch eine Addition und eine (Skalar-)Multiplikation. Die Addition geschieht komponentenweise. Hat man also einen zweiten Vektor b=(b1,...,bn), so ist die Addition definiert durch:

Vektoraddition.png

Die Multiplikation eines Vektors v mit einem reellen Faktor λ entspricht einer Streckung des Vektors um λ, was durch Multiplikation aller Komponenten von v mit λ erreicht wird:

Vektorskalarmultiplikation.png

Es ergeben sich die von den normalen reelen Zahlen bekannten Rechenregeln:

Vektorassoz.png

D.h. man kann Skalare einfach aus Klammern ausmultiplizieren oder wieder hineinziehen. Man beachte aber, dass die Multiplikation von Vektoren mit Vektoren nicht definiert ist (Siehe auch Vektorprodukt, Standard Skalarprodukt).

Ist unser n gerade die Zahl 3 bzw. 2, so kann man durch den Rn gerade den 3-Dimensionalen bzw. 2-Dimensionalen Anschauungsraum darstellen. Vektoren kann man dann sogar zeichnen und bekommt eine bildliche Vorstellung. Vektoren werden zu einer Darstellung von Pfeilen, die eine Richtung beschreiben oder ausgehend vom Nullpunkt des Koordinatensystems einen Punkt definieren:

Vektorvorstellung.jpg

Lineare Abbildungen auf dem Rn in den Rm

Weiter kann man Abbildungen f, die als Parameter Vektoren des Rn annehmen und diese in den Rm abbilden, definieren. Insbesondere kann man Abbildungen definieren, die linear sind, d.h. dass f folgende Eigenschaften erfüllt:

Lineare Abbildungen.png

und zwar für alle a,b aus Rn und alle λ aus den reellen Zahlen R. Interessant ist, dass solche Abbildungen die Rechenregeln aus unserer Vektorraumdefinition erhalten. Sehr wichtig ist jedoch: Solche Abbildungen existieren. Die einfachste ist die, die alle Vektoren aus Rn auf die 0 abbildet ( die 0 ist der Vektor des Rm, in dem alle Komponenten gleich 0 ist. ). Tatsächlich gibt es deutlich mehr dieser Abbildungen und alle lassen sich als Matrizen darstellen. Und umgekehrt: Mit Matrizen lassen sich alle lineare Abbildungen auf unseren Vektorräumen beschreiben.

mxn-Matrizen und ihre Anwendung auf Vektoren

Wie bereits angesprochen, sind Matrizen also 2 Dimensionale Felder aus rellen Zahlen:

mxnMatrix.png

Die aij werden dann die Koeffizienten der Matrix genannt. Nun wollen wir das Anwenden der Matrix A aus Rmxn auf einen Vektor x definieren:

mxnMatrixAnwendungaufx.png

Beispiel:

AnwendungsbeispielMatrizen.png

Am Bild erkennt man auch, warum die Matrix-Vektor Multiplikation ( " Anwendung " ) auch als Zeile mal Spalte bezeichnet wird, denn die Koeffizienten einer Zeile der Matrix werden der Reihe nach mit den Koeffizienten der "Spalte" des Vektors multipliziert. Dieses Verfahren kann man erweitern, indem man Vektoren als Matrizen interpretiert, die nur eine Spalte haben. Schreibt man mehrere Vektoren nebeneinander, kann man auf jede dieser Spalten die Matrix A darauf anwenden:

mxn-nxr-Matrix-Matrix Multiplikation

Man hat also eine mxn-Matrix A und eine nxr-Matrix B, die man Spaltenweise als Vektoren versteht:

zerlegungMatrixInEinzelvektoren.png

Bei der Multiplikation von A mit B, wird dann einfach A auf die Vektoren bi angewendet.

MatrixMatrixMultiplikation.png

Beispiel:

MatrixMatrixMultiplikationBeispiel.png

Eigenschaften

Diese Multiplikation hat eine Reihe von Eigenschaften:

  • Versteht man die Matrizen A,B als lineare Abbildungen auf Vektoren x aus dem Rn und y aus Rr, also f(x) = A*x und g(y) = B*y und ist A eine mxn-Matrix, sowie B eine nxr Matrix, dann ist die Abbildung f(g(y)) eine Lineare Abbildung, die beschrieben ist durch
MatrixMatrixMultiplikationLinear.png
  • Daraus ergibt sich, da schon die Definitions-Vektorräume verschieden sind, dass in den meisten Fällen nicht gilt: A*B=B*A . Wer sich dies genauer überlegt, stellt fest, dass das 2. Produkt nur dann definiert ist, wenn A und B beides nxn-Matrizen sind. Aber selbst in diesem Fall ist es im Allgemeinen ein Unterschied, ob ich A*B oder B*A rechne (Das führt schließlich zu der Tatsache, dass man in OpenGL aufpassen muss, ob man zuerst rotiert und dann verschiebt (transliert) oder umgekehrt: Diese Operationen werden durch Matrizenmultiplikationen implementiert. Zu diesem Thema findet man am Ende des Tutorial_Matrix2 einige Bilder.).
  • Anderfalls gelten die Distributiv-, Assoziativ- und Kommutativgesetze:
MatrixMatrixMultiplikationLinear2.png
  • Man nennt eine Gleichung A*x = b ein Lineares Gleichungssystem, wenn A und b bekannt und x gesucht ist. Es interessiert dann, ob und - wenn ja - wie viele Lösungen es für x gibt.

Siehe Auch

Es gibt noch eine Menge weiterer Eigenschaften, und Funktionen, die in Bezug auf Matrizen höchst interessant sind:

Matrixtransposition, Determinante, Matrixinversion, Gauss-Algorithmus, Matrizenmultiplikation


Matrizen in OpenGL

Die drei OpenGL Matrizen

In OpenGL gibt es drei 4x4-Matrizen welche alle mit Hilfe von glTranslate, glScale, glRotate,glMultMatrix,glLoadMatrix und glLoadIdentity bearbeitet werden können. Welche Matrix von diesen Funktionen beeinfusst wird, kann durch glMatrixMode gesteuert werden.

Die 3 Matrizen sind:

GL_PERSPECTIVE

Sollte nur für die Festlegung der Perspektive genutzt werden.

GL_MODELVIEW

Legt Position und Größe des zu zeichnenden Primitiven fest

GL_TEXTURE

Beinhaltet Informationen wie Texturen dargestellt werden.

Noch mehr Informationen zu den Matrizen und was sie bewirken gibts im Tutorial Matrix2.

Aufbau einer OpenGL-Matrix

Möchte man mit OpenGL an einer bestimmten Stelle etwas zeichnen, so kann man mit Hilfe von glTranslate und glRotate die Modelview-Matrix so manipulieren, dass etwa der mit glVertex übergebene Eckpunkt (0/0/0) im Weltkoordinaten System nicht mehr in der Mitte liegt. Alle Punkte erscheinen scheinbar in einen zweiten Koordinaten System welches etwas verdreht, vegrößert oder verrutsch liegen kann.

Dieses zweite Koordinaten-System wird durch eine 4x4-Matrix, also einem zwei dimensionenlen Array mit vier Spalten und Zeilen, beschrieben.

Damit besser verstanden werden kann, wie dies funktioniert, wird die Funktionsweise anhand eines zwei dimensionalen Koordinaten System demonstiert.

Möchte man in einem einfachen 2D Koordiaten-System den Punkt (X/Y) antragen, so hängt man X mal den Vektor der X-Achse aneinander, und Y mal den Vektor der Y-Achse.

KoordinatenSystemA.png

Um die Lage und Größe eines Koordinatensystems zu beschreiben werden also einmal die Vektoren benötiget die 1 Längen Einheit meiner Achsen beschreiben, sowie ein Vektor der ihre Position in Anhängigkeit zum übergeordneten Koordinatensystems beschreibt.

KoordinatenSystemB.png

Wie bereits bemerkt, müssten die Matrizen eigentlich 3x3-Matrizen sein, da sie ja auf dem 3D-Raum operieren sollen. Damit lassen sich jedoch keine Verschiebungen beschreiben, weswegen man bei der Übergabe von Vertexdaten mit glVertex im Hintergrund eine 4. Koordinate w neben (x,y,z) einführt. Diese hat, wenn nicht explizit über glVertex4x angegeben, den Wert 1. So lassen sich mit 3x3 Matrizen (aus denen jetzt durch Hinzunahme von w, 4x4 Matrizen geworden sind) auch Verschiebungen beschreiben:

X X X X
Y Y Y Y
Z Z Z Z
W W W W

So wirkt jede Zeile der OpenGl-Matrix auf genau die entsprechende Koordinate des Vertex nach der Multiplikation mit einem Vertex (x,y,z,1). Ist die letzte Zeile der Matrix (0,0,0,1), hat also die Matrix die Form:

X X X X
Y Y Y Y
Z Z Z Z
0 0 0 1

Dann beschreibt die letzte Spalte der Matrix gerade die Verschiebung unseres Vertices, wie man mit der oben definierten Anwendung einer Matrix auf einen Vektor leicht überprüft. Am Ende wird die w-Koordinate, sofern sie 1 ist, wieder verworfen - was sie auch bleibt, denn die letzte Zeile der OpenGl Matrix ist gerade so gewählt, dass dies sichergestellt ist. Nur bei der endgültigen Darstellung auf den Monitor kommt der w-Koordinate noch eine weitere Bedeutung zu, weshalb Projektionsmatrizen ( erzeugt durch glOrtho, glFrustum, ... ) sich an Regel der letzten Zeile (0,0,0,1) nicht halten.

Folgendes Format könnte man nutzen, um eine Matrix mit glGetFloatv auszulesen oder mit glLoadMatrix zu setzen.

type
  TVektor = record
    X, Y, Z, W: glFloat;
  end;
  TMatrix = array[(mat_XAchse, mat_YAchse, mat_ZAchse, mat_Position)] of TVektor;
  PMatrix = ^TMatrix;

oder einfach

type
  TMatrix = array[0..3, 0..3] of glFloat;


Man beachte dabei, dass OpenGL Matrizen Spaltenweise im Speicher ablegt sind. Siehe dazu auch: glMultMatrix


Zum leichteren Verständnis

Dieser Abschnitt ist nicht für fortgeschrittene 3D Entwickler gedacht, sollte aber Anfängern die immer noch nicht wissen, was Matrizen eigentlich in OpenGL machen einen leichteren Einblick verschaffen.

Um sich Matrizen in OpenGL leichter vorzustellen, kann man folgendes Bild benutzen:

  • Die 3D-Welt ist in einer Art Glaskasten abgelegt in dem es keine Physik gibt (Dinge können in der Luft schweben u.ä.).
  • Matrizen sind Maschinen/Greifarme.
  • Matrizen sind die einzige Möglichkeit in den Glaskasten hinein zu greifen.

Wie wir weiter oben bereits gelernt haben sind Matrizen ja eigentlich Tabellen mit Zahlen. Diese Zahlen sind die Stellschrauben an unseren "Greifarmen". Mit diesen Stellschrauben können wir die Greifarme im Glaskasten positionieren. Durch den OpenGL-Befehl glMatrixMode können wir auswählen welchen der beiden Arme wir gerade steuern.

ModelView - Der Objektmanipulator

Wird diese Matrix auf ein Objekt angewendet, ändert sich je nach Einstellung der Matrix dessen Position, Ausrichtung, Größe usw. (Man kann sogar den kompletten Glaskasten damit verschieben.) (Beispiel: Wirft man einen Würfel in eine Drehungsmatrix, kommt am Ende ein gedrehter Würfel raus.)

PerspectivMatrix - Die Kameralinse

Diese Maschine ist nur für die Ausgabe zuständig. Man kann über die Stellschrauben einstellen, welche Art der Projektion (Parallel-, Perspektivisch-,...), und wie nah und wie weit Objekte maximal von der Kamera entfernt sein dürfen, um sichtbar zu sein.

Wer nun auf den Geschmack gekommen ist und mittels glLoadMatrix mal selber die Stellschrauben einer der beiden Matrizen ändern möchte, der sollte sich das sehr gute Mathe Script zum Thema Computer Geometrie einmal ansehen (siehe Links). Das eben vermittelte Bild mag zwar helfen. Die Theorie muss aber verstanden werden um damit arbeiten zu können.


Siehe auch

Links