Dreidimensionale Spielewelten - Die dritte Dimension Themen: • Beschreibung der dreidimensionalen Spielewelt durch Vektoren • Dreidimensionale Wetltransformationen durch Matritzen • Schnelle Quadratwurzelberechnung • Schnelle Berechnung von Rotationsmatritzen Softwaretechnologie II - M. Thaller Wintersemester 2005 / 2006 Referentin: Tanja Lange 1 Koordinatensysteme 2 Arten der Erweiterung des zweidimensionalen Koordinatensystems in die Dritte Dimension: Für DirectX-Programmierer: Linkssystem = positive z-Achse zeigt in Monitor Rechtssystem = z-Achse zeigt in entgegengesetzte Richtung 2 Grundbegriffe: Definition Vektor ein Vektor ist eine Liste von Zahlen ! ein Vektor ist eine gerichtete, orientierte Strecke im Raum Vektoren werden durch Pfeile repräsentiert. Länge des Pfeils = Betrag des Vektors In der Geometrie ist ein Vektor eine Klasse von Pfeilen gleicher Länge (Betrag), gleicher Richtung und gleicher Orientierung. Um beispielsweise das Dreieck ABC in der Figur an die Position A'B'C' zu verschieben, muss jeder Punkt um 7 Einheiten nach rechts und 3 nach oben verschoben werden. Da diese Pfeile in Länge, Richtung und Orientierung alle übereinstimmen, fasst man sie zu einer Klasse (Vektorklasse) zusammen. Man beschreibt die Klasse durch die Verschiebung, die ihre Pfeile bewirken, im Beispiel: im dreidimensionalen Raum entsprechend mit 3 Koordinaten. 3 Grundbegriffe: Zeilenvektor: Bsp.: (3,-2,4) 3 Spaltenvektor: Bsp.: -2 4 ein Punkt P wird durch Komponenten (Ax, Ay, Az) beschrieben Basisvektoren = senkrecht aufeinander stehende (orthogonale) Vektoren Hilfestellung: Dreifinger-Regel ! Basisvektoren eines dreidimensionalen, rechtwinkligen Koordinatensystems: Basisvektor, der die x-Achse repräsentiert: i = (1 0 0) Basisvektor, der die y-Achse repräsentiert: j = (0 1 0) Basisvektor, der die z-Achse repräsentiert: k = (0 0 1) Ortsvektor = gebundener Vektor hat Ursprung bzw. Ausgangspunkt Einheitsvektor = Vektor mit Betrag 1 = normiert Bezeichnung: ex, ey, ez 4 Grundbegriffe: Nullvektor = Vektor mit Betrag 0 Ursprung Gegenvektor = gleicher Betrag, - Richtung, andere Orientierung Translation = Verschiebung Verschiebungsvektor Verbindungsvektor = zw. 2 Punkten P (=Schaft) und Q (=Spitze) Skalare = Beträge von Vektoren = gerichtete Größe kollinear = Parallel, Schreibweise: a || b, Antiparallel = entgegengesetzt Linearkombination = Summe vom Vielfachen von Vektoren Determinante = in der linearen Algebra eine spezielle Funktion, die jeder quadratischen Matrix eine Zahl zuordnet. Matrix = stellt Anordnung von Elementen in mehreren Richtungen dar In der Informatik entspricht eine Matrix einem n-dimensionalen Feld In der linearen Algebra ist eine Matrix (Plural: Matrizen) eine Anordnung von Zahlenwerten (oder Operatoren) in Tabellenform. Man spricht von den Spalten und Zeilen der Matrix, und bezeichnet selbige auch als Vektoren (d.h. Zeilenvektoren und Spaltenvektoren). Die Objekte, die in der Matrix angeordnet sind, nennt man Komponenten oder Elemente der Matrix. 5 Vektorprodukt (Kreuzprodukt) ein weiteres Produkt (Vektor c) zweier Vektoren a und b steht senkrecht auf a und b c = a • b c = 0 für a || b ! Nicht verwechseln: ! Skalarprodukt (Punkt-): a • b = |a| • |b| • cosα a • b = 0 für a ┴ b a • b = |a| • |b| für a || b Betrag Vektor c = Flächeninhalt A |c| = |a| • |b| • sinα |c| = |a| • |b| für a ┴ b, weiter gilt: c ┴ a, b Fläche A ist vorzeichenbehaftet: Winkel > 180° negatives Vorzeichen, c entgegengesetzte Richtung Beim arbeiten mit negativem Winkel wird Reihenfolge der Multiplikation der Vektoren a und b festgelegt Da Vektoren c1 und c2 antiparallel sind 6 Berechnung des Vektorprodukts mit Hilfe von Determinanten, Bsp.: eine 3x3 Determinante: Zur Berechnung wird Determinante mit Hilfe von Laplaceschen Entwicklungssatz zerlegt: 1. Zeile: Basisvektoren 2. Zeile: Komponenten des Vektors a 3. Zeile: Komponenten des Vektors b In Spaltenform: DirectX-Funktion: D3DXVector3* D3DXVec3Cross( ) Hilfsmethode zur Berechnung der Komponenten: d.h.: 1 4 2 1 4 2 -1 5 6 -1 5 6 = (1 · 5 · 3) + (4 · 6 · 2) + (2 · (-1) · (-8)) – (1 · 6 · (-8)) – (4 · (-1) · 3) – (2 · 5 · 2) = 119 2 -8 3 2 -8 3 7 Polarkoordinaten (Kugelkoordinaten) für Konstruktion von 3D-Szenarien einer Weltraumsimulation Bsp.: 30° nach rechts drehen; 40° nach oben drehen; 0,5 aU geradeaus fliegen leichter zu interpretieren als kartesische Koordinaten (x-, y-, z-) Für eine dreidimensionale Polarkoordinatendarstellung benötigt man zwei Winkel sowie die Länge des Ortsvektors x = Entfernung * cos(Vertikalwinkel) * sin(Horizontalwinkel) y = Entfernung * sin(Vertikalwinkel) z = Entfernung * cos(Vertikalwinkel) * cos(Horizontalwinkel) Horizontalwinkel = Drehung nach rechts (positiver Wert) oder links (negativer Wert) Vertikalwinkel = Drehung nach oben (positiver Wert) oder unten (negativer Wert) 8 Quadratwurzelberechnung häufige Rechenoperation in einem Spiel im Zusammenhang mit der Normierung und Längenberechnung von Vektoren Entwicklung eigener, schneller Quadratwurzel-Routinen Prozessorleistung Näherungsverfahren durch unsigned long *ptr = NULL; Iterationsverfahren nach dem float Value; alten Heron: inline float FastWurzelExact(float r) { if(r==0.0f) return 0.0f; if(r<0.0f) r = -r; Value = r; halfValue = 0.5f*r; ptr = (unsigned long*)&r; *ptr = (0xbe6f0000-*ptr)>>1; temp1Wurzel = r; Da Zeiger ptr vom Typ unsigned long*, werden Bits als die einer Ganzzahl interpretiert Prüfen, ob Wurzel von Null berechnet werden soll (da bei Division durch Null evtl. Programmabsturz) Prüfen, ob Zahl zur QWB positiv ist Divisionen durch Multiplikation ersetzen ! temp1Wurzel *= 1.5f-temp1Wurzel*temp1Wurzel*halfValue; temp1Wurzel *= 1.5f-temp1Wurzel*temp1Wurzel*halfValue; return Value*temp1Wurzel; } 9 Längenberechnung & Normierung von Vektoren Funktion für die Berechnung des Vektorbetrags (unter Verwendung der FastWurzelExact( ) – Funktion): inline float Calculate3DVectorLength(D3DXVec3* pVectorIn) { if(*pVectorIn == NullVector) { return 0.0f; } tempNorm = D3DXVec3LengthSq(pVectorIn); tempNorm = FastWurzelExact(tempNorm); return tempNorm; } // Quadratische Länge des Vektors mittels // DirectX-Funktion D3DXVec3LengthSq( ) // berechnet Normierung eines Vektors: inline float NormalizeVector( ) { If (tempNorm != 1.0f) // prüfen, ob Vektor überhaupt normiert werden muß { tempNorm = FastWurzel(tempNorm); // es ist nicht immer erforderlich } // Vektor exakt zu normieren } 10 Manipulation der 3D-Welt Transformation von Vektoren mit Hilfe von Matrizen DirectX-Funktion: D3DXVector3* D3DXVec3TransformCoord( ) Durch DirectX keine einzelnen Transformationen mehr notwendig Nur Adresse der Transformationsmatrix an DirectX-Funktion SetTransform( ) mit Hinweis auf Weltkoordinatensystem (Welttransformation) übergeben die grafische Darstellung (Renderprozess) des Objekts erfolgt dann in korrekter Größe (Skalierung), Ausrichtung und Verschiebung ! 11 Manipulation der 3D-Welt Translationsmatrix für die Bewegung im Raum Erweiterung der Translationsmatrix T für die Bewegung im Raum: DirectX-Funktion: D3DXMatrix* D3DXMatrixTranslation( ) Skalierungsmatrix Skalierungsmatrix S lässt sich ohne Probleme um eine Dimension erweitern: DirectX-Funktion: D3DXMatrix* D3DXMatrixScaling( ) Einheitsmatrix Alle Transformationsmatritzen werden stets als Einheitsmatrix initialisiert: DirectX-Funktion: D3DXMatrix* D3DXMatrixIdentity( ) 12 Rotationsmatrizen für Drehung Im dreidimensionalen Raum kann sich ein Objekt um eine beliebig orientierte Achse drehen Rotation eines Vektors um x-Achse lässt sich durch drei Gleichungen beschreiben: xneu = x yneu = ycosα - zsinα zneu = ysinα + zcosα Zugehörige Matrix Rx hat folgenden Aufbau: -y Bsp. anhand dreier Winkel (0°, 90°, 180°) α2 α 1-z Gleichung 1: Rotation um x-Achse beeinflußt x-Komponenten des Vektors nicht Gleichung 2: Drehung um 0° überführt alte y-Komponente in neue yKomponente, Drehung um 90° überführt negative z-Komponente in neue yKomponente, Drehung um 180° überführt y-Komponente in negative yKomponente Gleichung 3: Drehung um 0° überführt alte z-Komponente in neue zKomponente, Drehung um 90° überführt y-Komponente in neue z-Komponente, 13 Drehung um 180° überführt z-Komponente in negative z-Komponente Rotationsmatrizen für Drehung Rotation eines Vektors um y-Achse: Zugehörige Matrix Ry: Rotation eines Vektors um z-Achse: Zugehörige Matrix Rz: xneu = xcosα + zsinα yneu = y zneu = -xsinα + zcosα xneu = xcosα - ysinα yneu = xsinα + ycosα zneu = z DirectX-Funktion: D3DXMatrix* D3DXMatrixRotationX( )/…Y( )/…Z( ) 14 Rotationsmatrizen für Drehung Rotation um beliebige Achse: Trick zur Aufstellung der Matrixgleichung: Rotationsachse auf eine bekannte Achse (z.B. z-Achse) transformieren (Drehung wird so zur Drehung um z-Achse mit gleichem Winkel), Rücktransformation in die ursprüngliche Rotationsachse mit inverser x- und y-Achsen-Rotationsmatritzen (= rückgängig machen der Transformation einer Matrix, d.h. Rotationsmatrix Drehung von 10° um x-Achse inverse Rotationsmatrix Drehung von -10° um x-Achse) DirectX-Funktion: D3DXMatrix* D3DXMatrixInverse( ) Rotationsmatrix für eine Drehung um beliebige Achse: x, y, z = Komponenten der normierten Rotationsachse DirectX-Funktion: D3DXMatrix* D3DXMatrixRotationAxis( ) 15 Frame-Rotationsmatrizen & Gesamtrotationsmatrizen Zwei Typen von Rotationsmatrizen: Gesamtrotationsmatrix: verantwortlich für endgültige Ausrichtung eines Objekts aus dessen Anfangsorientierung Frame-Rotationsmatrix: beschreibt nur Drehung während des aktuellen Frames neue Gesamtrotationsmatrix nach Framedrehung durch Multiplikation FrameRotationsmatrix mit Gesamtrotationsmatrix des vorangegangenen Frames (Multiplikationsreihenfolge abhängig von gegebenem Problem!) Für Rotation von Planeten, Wolken und Asteroiden folgende Multiplikation: R(neue Rotationsmatrix) = R(alte Rotationsmatrix) * R(für Drehung pro Frame) Gesamtrotationsmatrix R muß zu Beginn des Spiels als Einheitsmatrix initialisiert werden D3DXMatrixIdentity( ) Zur Kurvenbewegung eines Raumschiffs wird Multiplikationsreihenfolge umgedreht: R(neue Rotationsmatrix) = R(für Drehung pro Frame) * R(alte Rotationsmatrix) 16 Simulation von Bewegung Bsp. für den Gebrauch (Simulation der Bewegung eines Asteroiden durch den Weltraum): Variablen zur Beschreibung der Bewegung: D3DXVector3 Ortsvektor, Eigenverschiebung, Rotationsachse; float Rotationsgeschwindigkeit Matrizen zur Transformation: D3DXMatrix Transformationsmatrix, Scalematrix, Rotationsmatrix, FrameRotationsmatrix, Translationsmatrix als Einheitsmatrizen initialisieren: D3DXMatrixIdentity( ) Skalierungsmatrix erzeugen: Scalematrix._11 = scaleX, … Rotationsachse und –geschwindigkeit festlegen Rotationsmatrix für Rotation von Frame zu Frame: D3DXMatrixRotationAxis( ) aktueller Ortsvektor: Ortsvektor = Ortsvektor + Eigenverschiebung aktuelle Translationsmatrix mit Hilfe von Ortsvektor erzeugen: Translationsmatrix._41 = Ortsvektor.x, … aktuelle Rotationsmatrix: Rotationsmatrix = Rotationsmatrix * FrameRotationsmatrix Gesamttransformationsmatrix zur korrekten Darstellung im Raum: Transformationsmatrix = Scalematrix * Rotationsmatrix * Translationsmatrix 17 Schnelle Berechnung von Rotationsmatrizen Mehrere Funktionen zur Erzeugung von Rotationsmatrizen Problem: bei Berechnung der Sinus- und Kosinuswerte relativ langsame API-Funktion Computer werden immer schneller, trotzdem keine unnötige Rechenzeit verschwenden ! Rotationsmatrizen mit Look-up-Tabellen erzeugen Problem: Drehungen finden in zwei Richtungen statt (Drehwinkel positiv oder negativ) Speicherverschwendung (für Bereich -360° bis +360°) negative in positive Winkel umwandeln! Winkel -10° = 350° (360° + (-10°)) merke folgende Regel: 360° + neg. Winkel = pos. Winkel Rotationsmatrizen mit gleichbleibendem Rotationswinkel falls diese ständig benötigt werden einmal erzeugen und immer wieder verwenden (einfache Optimierungsmethode, die oft vergessen wird) 18 Schnelle Berechnung von Rotationsmatrizen Rotationsmatrizen mit Hilfe von vorberechneten Sinus- und Kosinuswerten erzeugen statt Winkel vorberechnete Sinus- und Kosinuswerte an entsprechende Funktion übergeben (Richtung beachten! für z.B. -10° einfach neg. Wert übergeben) inline void CreateRotMatrix( ) Rotationsmatrizen für kleine Winkel Objekte drehen sich in einem Frame nur um kleine Winkel Frame-Rotationsmatrizen mit Sinus- und Kosinusnäherungen für kleine Drehwinkel berechen Sinuswert für kleine Winkel (bis 10°) mittels Geradengleichung sin (α) ~ α (Näherung (Approximation) ist Winkel im Bogenmaß!) Kosinusfunktion für kleine Winkel mittels Parabelfunktion cos (α) ~ 1 – 1.5·α² (Näherung ist Winkel im Bogenmaß!) inline void CalcRotXMatrixS( ) inline void CalcRotAxisMatrixS( ) { NormalizeVektor_If_Necessary( ) } 19 Schnelle Berechnung von Rotationsmatrizen Rotationsmatrizen für beliebige Winkel Berechnung der Sinus- und Kosinuswerte muß um paar Glieder erweitert werden für Winkel im Bereich -180° bis +180° positive Winkel > 180° müssen wegen Rechengenauigkeit in negative umgerechnet werden (Winkel – 360°), negative < 180° umgekehrt (360° + Winkel) Hinweis: bei der praktischen Anwendung Division durch Multiplikation ersetzen ! inline void CalcRotXMatrix( ) inline void CalcRotAxisMatrix( ) { NormalizeVektor_If_Necessary( ) } 20 Literatur BÜCHER: 3D-Spiele mit C++ und DirectX in 21 Tagen, Alexander Rodolph, Markt + Technik Verlag, München, 2003 INTERNET: https://www.htw-saarland.de/fb-gis/labore/strahlenschutz/ folder.2005-06-14.6092569165/physkriptEtechnikteil1.pdf iva.uni-ulm.de/physik/repetitorium/MATHEMATIK/10/10.html-4k de.wikipedia.org/wiki/Vektor - 41k 21