190 likes | 332 Views
2D-Objekte in der 3D-Welt. Softwaretechnologie II - M. Thaller Wintersemester 2005 / 2006 Referentin: Tanja Lange Assistenz: Niklas Köhn. Worum geht´s heute?.
E N D
2D-Objekte in der 3D-Welt Softwaretechnologie II - M. Thaller Wintersemester 2005 / 2006 Referentin: Tanja Lange Assistenz: Niklas Köhn
Worum geht´s heute? • Zweidimensionale Objekte = Billboards (z. B. Rauch, Nebel, Wolken, Explosionen,…), die entsprechend der Blickrichtung in der dreidimensionalen Welt ausgerichtet werden • Transformationsfunktionen für derartige Billboardeffekte entwickeln
Kameradrehung im 3D-Raum (Blickrichtung des Spielers) • 3 Inline-Funktionen in Space3D.cpp // ----------------------------------------------------------- // Kameradrehung um die Blickrichtungsachse // ----------------------------------------------------------- inline void Player_Flugdrehung(float winkel) // Frame-Drehwinkel in Grad, um den sich Blickrichtung ändern soll, // als Parameter übergeben { winkel = winkel*D3DX_PI/180.0f; // Umrechnung ins Bogenmaß FlugdrehungsWinkel += winkel; // Bei Flugdrehung wird Frame-Drehwinkel zum Flugdrehungswinkel hinzuaddiert if( FlugdrehungsWinkel > D3DX_PI ) FlugdrehungsWinkel -= 6.283185308f; else if( FlugdrehungsWinkel < -D3DX_PI ) FlugdrehungsWinkel += 6.283185308f; CalcRotAxisMatrixS(&tempMatrix1, &PlayerFlugrichtung, winkel); // Berechnung Frame-Rotationsmatrix g_ObjectKorrekturMatrix = g_ObjectKorrekturMatrix*tempMatrix1; // damit wird Gesamtrotationsmatrix berechnet, // für Billboard-Transformationsfunktionen, // Ausrichtung 2D-Objekten MultiplyVectorWithRotationMatrix(&PlayerHorizontale, &PlayerHorizontale, &tempMatrix1); // neue horizontale + MultiplyVectorWithRotationMatrix(&PlayerVertikale, &PlayerVertikale, &tempMatrix1); // vertikale Drehachse // bestimmen NormalizeVector_If_Necessary(&PlayerHorizontale, &PlayerHorizontale); NormalizeVector_If_Necessary(&PlayerVertikale, &PlayerVertikale); D3DXMatrixLookAtLH(&matView, &NullVektor, &PlayerFlugrichtung, &PlayerVertikale); g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView); // Sichttransformation durchführen } Kameradrehung im 3D-Raum
Horizontale und vertikale Kameradrehung // -------------------------------------- // Horizontale Kameradrehung // -------------------------------------- inline void Player_Horizontaldrehung(float winkel) // Frame-Drehwinkel in Grad, um den sich Blickrichtung ändern // soll, als Parameter übergeben { winkel = winkel*D3DX_PI/180.0f; // Umrechnung ins Bogenmaß // neue Flugrichtung aus Gesamtrotationsmatrix bestimmen CalcRotYMatrixS( &tempMatrix1,winkel ); g_ObjectKorrekturMatrix = tempMatrix1*g_ObjectKorrekturMatrix; PlayerFlugrichtung.x = g_ObjectKorrekturMatrix._31; PlayerFlugrichtung.y = g_ObjectKorrekturMatrix._32; PlayerFlugrichtung.z = g_ObjectKorrekturMatrix._33; D3DXVec3Cross(&PlayerHorizontale, &PlayerVertikale, &PlayerFlugrichtung); // Berechnung neue horizontale // bzw. vertikale Drehachse NormalizeVector_If_Necessary(&PlayerHorizontale, &PlayerHorizontale); // neue Sichtmatrix matView (Kameramatrix) erstellen und zugehörige View-Transformation durchführen D3DXMatrixLookAtLH(&matView, &NullVektor, &PlayerFlugrichtung, &PlayerVertikale); g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView); } // ----------------------------------- // Vertikale Kameradrehung // ----------------------------------- inline void Player_Vertikaldrehung(float winkel) { … } Kameradrehung im 3D-Raum
Billboard-Transformationsfunktionen • in Datei BillboardFunctions.h • sind zuständig für: • Darstellung von Hintergrundobjekten (Sonne, Wolken, Hintergrundnebel und galaxien) im 3DRaum durch Angabe ihrer Polarkoordinaten • Darstellung von Explosionen, Partikeln, Lens Flares, elektrostatischen Nebelentladungen (NebulaFlash) und Text im 3DRaum durch Angabe des Ortsvektors • Darstellung von 2DObjekten durch Angabe des Ortsvektors sowie der Rotationsmatrix • Planarperspektivische Darstellung von Billboards durch Angabe des Ortsvektors Hinweis: • 3D-Raum – Kamera kann um drei orthogonale Achsen gedreht und beliebig im Raum verschoben werden • planarperspektivischen Raum - Kamera kann nach rechts/links bzw. oben/unten bewegt sowie an das Spielgeschehen heran bzw. vom Spielgeschehen weggezoomt werden. Billboard-Transformationsfunktionen
Funktion zum Ausrichten eines Billboards im 3D-Raum unter Verwendung des Billboard-Ortsvektors • normale Darstellung: inline void Positioniere_2D_Object(D3DXVECTOR3* pAbstand, float &scale) { // Hinweis: Die Verwendung von Zeigern und Referenzen als Parameter hat den Vorteil, // dass die Erzeugung von lokalen Kopien unterbleibt --> bessere Performance!! // aus Ortsvektor und Skalierungsfaktor wird Verschiebungs- und Skalierungsmatrix erzeugt g_VerschiebungsMatrix._41 = pAbstand->x; g_VerschiebungsMatrix._42 = pAbstand->y; g_VerschiebungsMatrix._43 = pAbstand->z; g_ScaleMatrix._11 = scale; g_ScaleMatrix._22 = scale; g_TransformationsMatrix = g_ScaleMatrix // beide Matrizen werden mit *g_ObjectKorrekturMatrix // Objektkorrekturmatrix multipliziert *g_VerschiebungsMatrix; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_TransformationsMatrix); // Welttransformation mit // Produktmatrix durchführen } Billboard-Transformationsfunktionen
Funktion zum Ausrichten eines Billboards im 3D-Raum unter Verwendung des Billboard-Ortsvektors sowie eines Drehwinkels • dreht das Billboard zusätzlich um einen vorgegebenen Winkel senkrecht zur Blickrichtung: inline void Positioniere_2D_Object_gedreht(D3DXVECTOR3* pAbstand, float &scale, float &winkel) { // Korrektur des Drehwinkels um FlugdrehungsWinkel um evtl. Flugdrehung bei Ausrichtung zu berücksichtigen korrigierter_Billboardwinkel = winkel-FlugdrehungsWinkel; if( korrigierter_Billboardwinkel > D3DX_PI ) korrigierter_Billboardwinkel -= 6.283185308f; else if( korrigierter_Billboardwinkel < -D3DX_PI ) korrigierter_Billboardwinkel += 6.283185308f; CalcRotAxisMatrix(&g_VerschiebungsMatrix2, // erzeugen einer Rotationsmatrix &PlayerFlugrichtung, // Rotationsachse = Blickrichtung des Spielers korrigierter_Billboardwinkel); g_VerschiebungsMatrix2._41 = pAbstand->x; // den Matrixelementen der Rotationsmatrix werden die g_VerschiebungsMatrix2._42 = pAbstand->y; // Ortskoordinaten des Billboards in x-, y- und z-Richtung g_VerschiebungsMatrix2._43 = pAbstand->z; // zugewiesen g_ScaleMatrix._11 = scale; g_ScaleMatrix._22 = scale; g_TransformationsMatrix = g_ScaleMatrix *g_ObjectKorrekturMatrix *g_VerschiebungsMatrix2; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_TransformationsMatrix); } Billboard-Transformationsfunktionen
Funktion zum Ausrichten eines Billboards im 3D-Raum unter Verwendung des Billboard-Ortsvektors und zufälligen Drehwinkel • dreht das Billboard um einen zufälligen Winkel senkrecht zur Blickrichtung: inline void Positioniere_2D_Object_fluktuierend(D3DXVECTOR3* pAbstand, float &scale) { CalcRotAxisMatrix(&g_VerschiebungsMatrix2, &PlayerFlugrichtung, Zufallswinkel->NeueZufallsZahl()); g_VerschiebungsMatrix2._41 = pAbstand->x; g_VerschiebungsMatrix2._42 = pAbstand->y; g_VerschiebungsMatrix2._43 = pAbstand->z; g_ScaleMatrix._11 = scale; g_ScaleMatrix._22 = scale; g_TransformationsMatrix = g_ScaleMatrix *g_ObjectKorrekturMatrix *g_VerschiebungsMatrix2; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_TransformationsMatrix); } Billboard-Transformationsfunktionen
Funktion zum Ausrichten eines Billboards im 3D-Raum unter Verwendung des Billboard-Ortsvektors + einer Rotationsmatrix • dreht das Billboard beliebig (nicht nur senkrecht zur Blickrichtung): inline void Positioniere_2D_Object(D3DXVECTOR3* pAbstand, D3DXMATRIX* pRotationsmatrix, float &scale) // zusätzlich Adresse einer entsprechenden Rotationsmatrix übergeben { g_VerschiebungsMatrix2 = *pRotationsmatrix; g_VerschiebungsMatrix2._41 = pAbstand->x; g_VerschiebungsMatrix2._42 = pAbstand->y; g_VerschiebungsMatrix2._43 = pAbstand->z; g_ScaleMatrix._11 = scale; g_ScaleMatrix._22 = scale; g_TransformationsMatrix = g_ScaleMatrix *g_VerschiebungsMatrix2; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_TransformationsMatrix); } Billboard-Transformationsfunktionen
Funktion zum Ausrichten eines Billboards im 3D-Raum unter Verwendung der Billboard-Polarkoordinaten • zur korrekten Positionierung sind zwei Drehungen notwendig: inline void Positioniere_2D_Object(D3DXVECTOR3* pAbstand, float &winkelHorizontal, float &winkelVertikal, float &scale) { CalcRotYMatrix(&tempMatrix1, winkelHorizontal); // Rotationsmatrix für die Drehung um die y Achse // (horizontale Drehung) wird erzeugt MultiplyVectorWithRotationMatrix(&temp1Vektor3, // mit Hilfe dieser Matrix wird die &PlayerHorizontaleOriginalNeg, // horizontale Drehachse für die &tempMatrix1); // vertikale Drehung berechnet CalcRotAxisMatrix(&tempMatrix2, &temp1Vektor3, winkelVertikal); // mit Hilfe der horizontale Drehachse // wird R.-Matrix für vert. Drehung berechnet g_VerschiebungsMatrix2 = tempMatrix1*tempMatrix2; // aus den beiden Rotationsmatrizen wird die // Gesamtrotationsmatrix gebildet g_VerschiebungsMatrix2._41 = pAbstand->x; g_VerschiebungsMatrix2._42 = pAbstand->y; g_VerschiebungsMatrix2._43 = pAbstand->z; g_ScaleMatrix._11 = scale; g_ScaleMatrix._22 = scale; g_TransformationsMatrix = g_ScaleMatrix*g_VerschiebungsMatrix2; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_TransformationsMatrix); } Billboard-Transformationsfunktionen
Funktion zum Ausrichten eines Billboards im 3D-Raum unter Verwendung der Billboard-Polarkoordinaten + eines Drehwinkels • dreht das Billboard zusätzlich um einen vorgegebenen Winkel senkrecht zum Ortsvektor: inline void Positioniere_2D_Object_gedreht(D3DXVECTOR3* pAbstand, float &winkelHorizontal, float &winkelVertikal, float &scale, float &blickwinkel) { CalcRotAxisMatrix(&tempMatrix, pAbstand, blickwinkel); // es wird eine weitere Rotationsmatrix benötigt CalcRotYMatrix(&tempMatrix1, winkelHorizontal); MultiplyVectorWithRotationMatrix(&temp1Vektor3, &PlayerHorizontaleOriginalNeg, &tempMatrix1); CalcRotAxisMatrix(&tempMatrix2, &temp1Vektor3, winkelVertikal); g_VerschiebungsMatrix2 = tempMatrix1*tempMatrix2*tempMatrix ; g_VerschiebungsMatrix2._41 = pAbstand->x; g_VerschiebungsMatrix2._42 = pAbstand->y; g_VerschiebungsMatrix2._43 = pAbstand->z; g_ScaleMatrix._11 = scale; g_ScaleMatrix._22 = scale; g_TransformationsMatrix = g_ScaleMatrix*g_VerschiebungsMatrix2; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_TransformationsMatrix); } Billboard-Transformationsfunktionen
Funktion z. Ausrichten d. Billboards im planar-perspektivischen Raum unter Verwendg. des Billboard-Ortsvektors • normale Darstellung : inline void Positioniere_2D_Object_Verschoben(D3DXVECTOR3* pAbstand, float &scale) { g_VerschiebungsMatrix._41 = pAbstand->x+g_VerschiebungsMatrix3._41*pAbstand->z; g_VerschiebungsMatrix._42 = pAbstand->y+g_VerschiebungsMatrix3._42*pAbstand->z; g_VerschiebungsMatrix._43 = pAbstand->z; g_ScaleMatrix._11 = scale; g_ScaleMatrix._22 = scale; g_TransformationsMatrix = g_ScaleMatrix*g_ObjectKorrekturMatrix*g_VerschiebungsMatrix; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_TransformationsMatrix); } Billboard-Transformationsfunktionen
Funktion z. Ausrichten d. Billboards im planar-perspektivischen Raum unter Verwendg. d. B.-Ortsvektors + Drehwinkel • dreht das Billboard zusätzlich um einen vorgegebenen Winkel senkrecht zur Blickrichtung des Spielers: inline void Positioniere_2D_Object_Verschoben_Gedreht(D3DXVECTOR3* pAbstand, float &scale, float &winkel) { CalcRotZMatrix(&g_VerschiebungsMatrix2, winkel); // Drehwinkel g_VerschiebungsMatrix2._41 = pAbstand->x+g_VerschiebungsMatrix3._41*pAbstand->z; g_VerschiebungsMatrix2._42 = pAbstand->y+g_VerschiebungsMatrix3._42*pAbstand->z; g_VerschiebungsMatrix2._43 = pAbstand->z; g_ScaleMatrix._11 = scale; g_ScaleMatrix._22 = scale; g_TransformationsMatrix = g_ScaleMatrix*g_ObjectKorrekturMatrix*g_VerschiebungsMatrix2; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_TransformationsMatrix); } Billboard-Transformationsfunktionen
Funktion z. Ausrichten d. Billboards im planar-perspektivischen Raum unter Verwendg. d. B.-Ortsvektors + sin-/cos-Wert • dreht das Billboard zusätzlich um einen vorgegebenen Winkel senkrecht zur Blickrichtung des Spielers: inline void Positioniere_2D_Object_Verschoben_Gedreht(D3DXVECTOR3* pAbstand, float &sin, float &cos, float &scale) { CreateRotZMatrix(&g_VerschiebungsMatrix2, sin, cos); // sin- und cos-Wert des Drehwinkels g_VerschiebungsMatrix2._41 = pAbstand->x+g_VerschiebungsMatrix3._41*pAbstand->z; g_VerschiebungsMatrix2._42 = pAbstand->y+g_VerschiebungsMatrix3._42*pAbstand->z; g_VerschiebungsMatrix2._43 = pAbstand->z; g_ScaleMatrix._11 = scale; g_ScaleMatrix._22 = scale; g_TransformationsMatrix = g_ScaleMatrix*g_ObjectKorrekturMatrix*g_VerschiebungsMatrix2; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_TransformationsMatrix); } Billboard-Transformationsfunktionen
Projektdateien und Klassenentwürfe • Für gesamtes Handling des 3DSzenarios ist wieder die Klasse C3DScenario zuständig in Datei 3D_Scenario_Class.h implementiert class C3DScenario { public: CCursor* Cursor; CNebula* Nebula; CStarfield* Starfield; C3DScenario() { Nebula = new CNebula[3]; // alle Elemente des 3D-Szenarios werden initialisiert Starfield = new CStarfield; Cursor = new CCursor; // TexturNummer (1-3), Horizontalwinkel, VertikalWinkel, Entfernung, ScaleFaktor, Nebelfarbe: rot; grün, blau Nebula[0].Nebula_Initialisieren(1, 0.0f, 0.0f, 2.0f, 1.2f, 255, 255, 255); Nebula[1].Nebula_Initialisieren(2, 120.0f, 40.0f, 2.0f, 1.2f, 255, 255, 255); Nebula[2].Nebula_Initialisieren(3, -120.0f, -40.0f, 2.0f, 1.2f, 255, 255, 255); } ~C3DScenario() { … } void New_Scene(void) // Rendern der 3D-Szene // zur Darstellung wird Methode durch Funktion Show_3D_Scenario( ) in Space3D.cpp aufgerufen { Starfield->Render_Starfield(); Nebula[0].Render_Nebula(); Nebula[1].Render_Nebula(); Nebula[2].Render_Nebula(); Cursor->Render_Cursor(); } }; C3DScenario* Scenario = NULL; Klassenentwürfe
Projektdateien und Klassenentwürfe • CStarfield Sterne werden gleichmäßig um den Spieler herum verteilt und haben allesamt den gleichen Abstand vom Spieler class CStarfield { … CStarfield() { … for(i = 0; i < AnzahlStars; i++) { pPointVertices[i].position = D3DXVECTOR3(frnd(-1.0f,1.0f), frnd(-1.0f,1.0f), frnd(-1.0f,1.0f)); NormalizeVector_If_Necessary(&pPointVertices[i].position, &pPointVertices[i].position); pPointVertices[i].position *= 20.0f; HelpColorValue = lrnd(50,200); pPointVertices[i].color = D3DCOLOR_XRGB(HelpColorValue, HelpColorValue, HelpColorValue); } … }; CStarfield* Starfield; Klassenentwürfe
Projektdateien und Klassenentwürfe • CCursor Renderfunktion abgewandelt Cursor mit Hilfe der Billboardfunktion Positioniere_ 2D_Object() im 3DRaum dargestellt class CCursor { … void Render_Cursor(void) { g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE); … tempVektor3 = 7.0f*CursorRichtungsVektor; tempFloat = 0.25f; // Scalefactor Positioniere_2D_Object(&tempVektor3, tempFloat ); g_pd3dDevice->SetTexture( 0, CursorTextur->pTexture ); … } }; CCursor* Cursor = NULL; Klassenentwürfe
Projektdateien und Klassenentwürfe • CNebula zusätzliche Methode Nebula_Initialisieren() void Nebula_Initialisieren(long TexturNummer, float HorizontalWinkel, float VertikalWinkel, float Abstand, float scale, long red, long green, long blue) { // Nebeltextur erstellen: if(TexturNummer == 1) sprintf( NebulaTextur->Speicherpfad , "Nebula1.bmp" ); else if(TexturNummer == 2) sprintf( NebulaTextur->Speicherpfad , "Nebula2.bmp" ); else if(TexturNummer == 3) sprintf( NebulaTextur->Speicherpfad , "Nebula3.bmp" ); NebulaTextur->CreateTextur(); ScaleFactor = scale; Entfernung = Abstand; // Ortsvektor des Billboards berechnen: Horizontalwinkel = HorizontalWinkel*D3DX_PI/180.0f; Vertikalwinkel = VertikalWinkel*D3DX_PI/180.0f; Abstandsvektor.x = Entfernung*cosf(Vertikalwinkel)*sinf(Horizontalwinkel ); Abstandsvektor.y = Entfernung*sinf(Vertikalwinkel); Abstandsvektor.z = Entfernung*cosf(Vertikalwinkel)*cosf(Horizontalwinkel ); // Zuweisung der Vertexfarbe: COLOREDVERTEX* pColVertices; NebulaVB->Lock( 0, 0, (VOID**)&pColVertices, 0 ); pColVertices[0].color = D3DCOLOR_XRGB(red,green,blue); pColVertices[1].color = D3DCOLOR_XRGB(red,green,blue); pColVertices[2].color = D3DCOLOR_XRGB(red,green,blue); pColVertices[3].color = D3DCOLOR_XRGB(red,green,blue); NebulaVB->Unlock(); } Auswahl der zu verwendenden Textur Festlegen der Polarkoordinaten Festlegen der Nebelfarbe Klassenentwürfe
Projektdateien und Klassenentwürfe • Spielsteuerung: Funktion ReadImmediateDataMouse() in GiveInput.h Entgegennahme aller Maus-Steuerbefehle • die eingegangenen MausSteuerbefehle werden innerhalb der Funktion Player_Game_Control() in Space3D.cpp in konkrete Aktionen umgesetzt. Ihr Aufruf erfolgt durch die Funktion GameMainRoutine() Klassenentwürfe