www.rolandk.de
- Aktuelle Themen zu .Net -
Achtung: Hier handelt es sich um meine alte Seite.
Die aktuelle ist unter folgendem Link erreichbar: www.rolandk.de/wp/
Home Artikel Grafikprogrammierung Grundlagen über Matrizen und Vektoren




















































Grundlagen über Matrizen und Vektoren
Samstag, den 23. Oktober 2010 um 15:40 Uhr

 

 

Allgemeines

Programmiert man mit XNA, SlimDX oder einer anderen Bibliothek an 3D-Spielen oder -Visualisierungen, so trifft man recht schnell auf die mathematischen Begriffe Matrix und Vektor. Matrizen und Vektoren, das kennt man eventuell aus der Schulzeit. Wichtig an dem ersten Satz ist das "eventuell", ich selbst habe dort nämlich nie etwas von Matrizen gehört. Das lag wohl daran, dass ich mich damals für eine kaufmännische Ausrichtung entschieden habe. Unabhängig davon schrecken alleine die Begriffe "Matrix" und "Vektor" den Einen oder Anderen vom Thema 3D-Entwicklung ab. In diesem Artikel will ich zeigen, dass die Grundlagen dahinter im Prinzip recht einfach sind und dass sich der Entwickler um die Berechnungen im Hintergrund gar nicht kümmern braucht.

 

Vektoren

Ein Vektor ist nichts anderes als ein Pfeil oder eine Koordinate im 3D-Raum. Er hat i. d. R. 3 Komponenten: X, Y und Z. X und Y kennt man bereits aus dem 2D-Bereich (siehe System.Drawing). Z erweitert die Koordinatenachsen um eine dritte Achse, die in den Bildschirm hinein geht. Eine einfache Vektor-Struktur könnte in C# also wie folgt aussehen:

  1. public struct Vector3
  2. {
  3. public float X;
  4. public float Y;
  5. public float Z;
  6. }

In den meisten Bibliotheken gibt es diese Klasse bereits und bietet noch eine ganze Menge zusätzlicher Funktionen. So werden zum Beispiel folgende Standardvektoren angeboten:

  1. public static readonly Vector3 Empty = new Vector3();
  2. public static readonly Vector3 AxisX = new Vector3(1f, 0f, 0f);
  3. public static readonly Vector3 AxisY = new Vector3(0f, 1f, 0f);
  4. public static readonly Vector3 AxisZ = new Vector3(0f, 0f, 1f);
  5. public static readonly Vector3 MinValue = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  6. public static readonly Vector3 MaxValue = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);

Weitere Standardfunktionen sind das Addieren, Subtrahieren und das Multiplizieren von Vektoren. Nichts besonderes also. Wichtig zu wissen ist aber, dass es unter der Vielzahl der möglichen Vektoren auch Besondere gibt, zum Beispiel die in der 3D-Programmierung sehr wichtigen Normals. Ein Normal ist ein Vektor mit der Länge 1 und gibt in der Regel eine Richtung an. Im Screenshot ganz oben sind in der Mitte jedes Dreiecks jeweils 3 Normals sichtbar. Zwei davon kleben direkt auf der Fläche des Dreiecks und einer zeigt davon weg. Eines der wichtigsten Einsatzgebiete von Normals sind Lichtberechnungen, denn nur über Normals weiß die Grafikkarte, in welche Richtung ein Dreieck zeigt und kann so Lichtreflektionen berechnen.

 

Matrizen

Eine Matrix ist zunächst nichts anderes als eine Tabelle von Zahlenwerten, es gibt also x Spalten und Y Zeilen. In der 3D-Programmierung werden i. d. R. 4x4 Matrizen verwendet. Grundsätzlich könnte eine 4x4 Matrix in C# codiert etwa so aussehen:

  1. public struct Matrix4
  2. {
  3. public float M11;
  4. public float M12;
  5. public float M13;
  6. public float M14;
  7. public float M21;
  8. public float M22;
  9. public float M23;
  10. public float M24;
  11. public float M31;
  12. public float M32;
  13. public float M33;
  14. public float M34;
  15. public float M41;
  16. public float M42;
  17. public float M43;
  18. public float M44;
  19. }

Die wichtigste Aufgabe von Matrizen ist es, die bereits weiter oben beschriebenen Vektoren zu transformieren. Was heißt transformieren? Nehmen wir an, eine Matrix beschreibt einen Punkt im Raum. Wird ein Vektor mit dieser Matrix transformiert, so zeigt der Vektor immer noch auf die gleiche Stelle, allerdings ist dann der von der Matrix beschriebene Punkt der 0-Punkt für den Vektor. Im Screenshot weiter oben sind 4 Würfel sichtbar. Die Eckpunkte aller Würfel sind mit den selben Vektoren beschrieben, wurden pro Würfel aber mit einer anderen Matrix transformiert. Jeder Würfel besitzt also seine eigene Transformationsmatrix.

 

Es gibt sehr viele Arten, wie Vektoren transformiert werden können, eine Translation etwa beschreibt eine einfache Verschiebung im Raum. Über Matrizen können Vektoren aber auch skaliert und rotiert werden. In der Regel gibt es in der Matrix-Struktur von XNA, DirectX, usw. entsprechende Methoden für jede Art von Transformation. Wichtig zu wissen ist auch, dass Matrizen beliebig verschmelzt werden können. Eine Matrix kann also gleichzeitig eine Translation, eine Rotation und dann wieder eine Translation enthalten. Auf diese Weise kann also auch eine einzige Matrix gebildet werden, die einen Punkt im 3D-Raum mit einer einzigen Transformation auf Bildschirmkoordinaten umrechnet. Um aber die Übersicht über verschiedene Transformationsmatrizen zu behalten, werden sie gerne in 3 Arten eingeteilt:

  • World-Matrix
  • View-Matrix
  • Projection-Matrix

Über die World-Matrix werden allgemeine Transformationen im 3D-Raum abgebildet. Die View-Matrix rechnet anschließend alle Vektoren relativ zur Koordinate der 3D-Kamera um und die Projection-Matrix kümmert sich um die Umrechnung in 2D-Bildschirmkoordinaten. Auf diese Weise behält man den Überblick und kann auch leicht in bestimmte Transformationen eingreifen.

 

Arten von Transformationen

Wie weiter oben schon beschrieben gibt es mehrere Arten von Transformationen. Nachfolgend ein paar Befehle, die dazu in den meisten Matrix-Strukturen implementiert sind:

  1. public static Matrix4 Translation(float transX, float transY, float transZ);
  2. public static Matrix4 RotationX(float angle);
  3. public static Matrix4 RotationY(float angle);
  4. public static Matrix4 RotationZ(float angle);
  5. public static Matrix4 RotationYawPitchRoll(float yaw, float pitch, float roll);
  6. public static Matrix4 Scaling(float scaleX, float scaleY, float scaleZ)

Eine Translation ist lediglich eine Verschiebung im Raum, daher werden Koordinaten übergeben, zu denen der Raum verschoben werden soll. Für eine Rotation gibt es mehrere Möglichkeiten, hier angeführt habe ich eine Rotations-Funktion pro Achse. RotationX heißt etwa, dass mit dem übergebenen Winkel um die X-Achse rotiert wird. RotationYawPitchRoll kann gleichzeitig um alle Koordinatenachsen rotieren. Yaw entspricht der Y-Achse, Pitch der X-Achse und Roll der Z-Achse. Abschließend erstellt die Methode Scaling eine Skalierung. Übergeben werden jeweils ein Skalierungsfaktor für die X-Achse, für die Y-Achse und für die Z-Achse.

 

Die bisher beschriebenen Transformationen beziehen sich auf die World-Matrix. Nachfolgend ein kurzes Beispiel, wie eine View- und eine Projection-Matrix erzeugt werden kann:

  1. m_view = Matrix4.LookAtLH(m_position, m_target, m_upVector);
  2. m_project = Matrix4.PerspectiveFovLH(
  3. (float)Math.PI / 4.0f,
  4. m_screenWidth / m_screenHeight,
  5. 0.1f, 100f);

Diese Matrizen werden i. d. R. innerhalb einer Kamera-Klasse erzeugt, da sie im Prinzip auch die Eigenschaften einer Kamera repräsentieren.

 

Zusammenfassung

Dieser Artikel gab eine kurze Einführung in das Thema Vektoren und Matrizen in der 3D-Programmierung. Das Beste an dieser Stelle ist, die verschiedenen Funktionen einfach mal auszuprobieren und einmal zu schauen, wie sich das Ergebnis am Bildschirm verhält. Denn so kompliziert die Funktion hinter einer 3D-Visualisierung auch ist, man hat den Vorteil, dass man sieht, wenn sich etwas anders verhält als erwartet. Diesem Artikel ist ein Beispielprogramm angehängt, dass eine eigene kleine Mathematik-Bibliothek mit den wichtigsten Strukturen und Funktionen implementiert. An dem Coding kann man dann auch genau sehen, was sich hinter den Matrix- und Vektorfunktionen verbirgt.

 

Siehe auch...

 

Kommentar hinzufügen

Ihr Name:
Kommentar: