www.codeworx.org/c++ tuts /Kongos rand() Tutorials, 2: Vektoren und Matrizen

Kongos rand() Tutorials, 2: Vektoren und Matrizen

Vektoren und Matrizen spielen in der 3D Programmierung eine große Rolle. Vektoren werden verwendet, um Punkte oder Bewegungen im Raum darzustellen. Es gibt natürlich 2D und 3D Vektoren, hier besprechen wir jedoch nur 2D Vektoren. 3D Vektoren funktionieren genau gleich.

Vektor Operationen

Ein 2D-Vektor setzt sich aus den x, y Koordinaten auseinander und sie werden so geschrieben: (x/y). Ein Punkt ist ein Typ eines Vektors. Der Unterschied zwischen einem Punkt und einem Vektor ist, das ein Punkt immer eine absolute Position hat. Das heißt, er geht immer vom Koordinatenursprung (0/0) aus. Ein Vektor muss jedoch nicht vom Ursprung ausgehen, sondern von irgendwo, wo wir wollen.

Ein Beispiel: Ein Rechteck kann durch zwei Punkte repräsentiert werden, nämlich den linken-oberen und den rechten-unteren. Jedoch kann man ein Rechteck auch durch den linken-oberen Punkt und einem Vektor mit der Höhe und Breite angeben.

 

Addition

Addition ist ganz einfach:

v1 + v2 = v3
(x1, y1) + (x2, y2) = (x1+x2, y1+y2) 

Man addiert die X-Koordinaten und die Y-Koordinante um das Ergebnis, also den Vektor zu bekommen.

Subtraktion

Die Subtraktion funktioniert genau wie die Addition.

v1 - v2 = v3 
(x1, y1) - (x2, y2) = (x1-x2, y1-y2) 

Das interessante bei der Subtraktion ist jedoch, dass v3 der Vektor von v2 zu v1 ist. Damit kann man den Vektor zwischen zwei Punkten berechnen.

Länge

Die Länge ergibt sich aus dem Satz von Pythagoras:

c2 = a2 + b2 

c ist dabei die Länge der Hypotenuse, a und b die Länge der Kathete bzw. Ankathete. In C++ müsste die Instruktion folgendermaßen lauten:

m = sqrt(x*x + y*y); 


Normalisieren

Wenn man einen Vektor normalisiert, bedeutet es, dass dieser Vektor die Länge 1 bekommt und trotzdem noch in die gleiche Richtung zeigt.

vnormalisiert = ( x / |vold|, y / |vold| ) 

Wir dividieren einfach die Koordinaten (x,y) durch die Länge des Vektors (|vold|). Und daraus entsteht der normalisierte Vektor.

Punktprodukt

Das Punktprodukt wird benötigt, um den Winkel zwischen zwei Vektoren auszurechnen. Dabei ist das Punktprodukt gleich der Mulitplikation der Länge des ersten Vektors mit der Länge des zweiten Vektors und dem Cosinus des Winkels zwischen den Vektoren.

v1 · v2 = |v1| * |v2| * cos(ø) 

Wir formen die Formel so um, dass wir den Winkel aus der Funktion bekommen:

ø = arccos( (v1 · v2) / (|v1| * |v2|) ) 

Und schon können wir den Winkel zwischen zwei Vektoren berechnen. Das einzige was noch fehlt, ist die Berechnung des Punktprodukts. Die Formel lautet:

v1 · v2 = x1*x2 + y1*y2 

Matrizen in der Direct3D-Programmierung

Unter Direct3D hat jedes Objekt ein eigenes (lokales) Koordinatensystem. Um dieses Koordinatensystem ist meistenes das Objekt genau zentral positioniert. Dabei besteht das Objekt nur aus Vektoren vom Koordinatenursprung zu seinem bestimmte Platz. Um nun dieses Objekt auf den Bildschirm zu bringen, muss es erst verschoben, rotiert und skaliert werden. Um diese Operationen wie das Rotieren zu berechnen, verwendet man Matrizen.

Gebe es die Matrizen nicht, müssten wir mehrere Formeln verwenden, damit das Objekt richtig positioniert wird. Das wären viele unnötige Berechnung, die den Computer nur ausbremsen. Wir erstellen zwar mehrere Matrizen um das Objekt zu bewegen, jedoch können wir diese miteinander multiplizieren. Damit bleibt uns am Schluß nur noch eine einzige Matrix über. In Direct3D schicken wir einfach unser Objekt mit dem lokalen Koordinatensystem an das Direct3D Device und dieses berechnet intern all dies für uns. Wir müssen Direct3D nur noch die Matrix bekannt geben.

Nun, eine Matrix ist nichts anderes als eine Tabelle. Unter Direct3D verwendet man eine Matrix mit 4 Zeilen und 4 Spalten. Die sogennante 4x4 Matrix. Man kann Matrizen addieren, multiplizieren,...

Die Eiheitsmatrix

Die Einheitsmatrix ist das neutrale Element unter den Matrizen. Sie ist wie die 1, bei den normalen Zahlen.

   1  0  0  0 
   0  1  0  0 
   0  0  1  0 
   0  0  0  1 


Wenn wir irgendeine Matrix mit der Einheitsmatrix multiplizieren, kommt genau wieder die erste Matrix heraus.

Verschieben eines Objektes

Die Verschiebung ist denkbar einfach. Wir addieren einfach zu jedem Vektor eines Objekts die gewünschte Verschiebung. Wir wollen aber jeden Vektor nicht direkt ändern, sondern wir erstellen eine Matrix, die wir am Schluß Direct3D übergeben. Die Matrix sieht folgendermaßen aus:

   1  0  0  0 
   0  1  0  0 
   0  0  1  0 
   tx ty tz 1 


Wir erstellen einfach eine Einheitsmatrix und platzieren die Verschiebung auf den Achsen in der letzten Zeile. Jeder Vektor den wir mit dieser Matrix multiplizieren, wird nun korrekt um tx,ty,tz verschoben.

Rotieren eines Objektes

Um ein Objekt zu rotieren, benötigen wir für jede Achse genau eine Matrix. In den folgenden Beispielen drehen wir jeweils das Objekt um a RAD (Achtung: Direct3D rechnet in RAD nicht in Winkeln.):

x-Achse 
   1      0      0      0 
   0      cos(a) sin(a) 0 
   0     -sin(a) cos(a) 0 
   0      0      0      1
   
y-Achse 
   cos(a) 0     -sin(a) 0 
   0      1      0      0 
   sin(a) 0      cos(a) 0 
   0      0      0      1
   
z-Achse 
   cos(a) sin(a) 0      0 
  -sin(a) cos(a) 0      0 
   0      0      1      0 
   0      0      0      1 


Jetzt haben wir aber 4 Matrizen. Um genau eine Matrix daraus zu machen, müssen wir sie multiplizieren.

Multiplizieren

Das Multiplizieren von Matrizen ist schon nicht mehr so einfach. Man muss zwar nur Addieren und Multiplizieren können, jedoch ist eine Multiplikation einer 4x4 Matrix mit einer anderen Matrix ziemlich lang.

Wir wollen nun eine Matrix A mit einer Matrix B multiplizieren. Das Ergebnis ist die Matrix C. Es gibt jedoch eine Regel bei der Multiplikation. Die Matrix A muss so viele Spalten haben wie die Matrix B Zeilen hat. Da aber bei uns jede Matrix 4 Spalten und 4 Zeilen hat, ist dies kein Problem.

Ein Eintrag Cij (i = Zeile, j = Spalte) in der Matrix C ergibtt sich dann aus der Multiplikation der i'ten Zeile der Matrix A mit der j'ten Spalte der Matrix B. Die Multiplikation der Zeile mit der Spalte geht wie folgt: Betrachten wir die Zeile und die Spalte jeweils als einen Zahlenstrang, dann multiplizieren wir die beiden ersten Elemente der Stränge miteinander , addieren dazu die Multiplikation der beiden zweiten Elemente usw. Ein Beispiel mit 2x2 Matrizen:

|a11 a12| |b11 b12|     |a11*b11 + a12*b21 a11*b12 + a12*b22| 
         *           = 
|a21 a22| |b21 b22|     |a21*b11 + a22*b21 a21*b12 + a22*b22| 

Hier kannst du dir jeweils eine Klasse für Vektoren und Matrizen für Direct3D downloaden. Konnte die Klassen leider nicht überprüfen. Wenn ihr Fehler findet, schickt mir doch die optimierten Klassencodes an kongo@codeworx.org. Die Matrix-Klasse ist auch noch nicht fertig. Einige Operatoren gehören noch überladen. Achtung: Ich hab noch kein Bugfix gemacht. Da stecken sicher viele Fehler drinnen.

Copyright (c) by Kongo

Bei Fragen, Beschwerden, Wünschen schreib an kongo@codeworx.org

Tutorial vom 30.06.2001