Upload
georg-schneiders
View
107
Download
0
Embed Size (px)
Citation preview
Balance V01
Der Windows-Rahmen
S. 207 - 210
Vortrag von Lisa Rau
- Elementares Windows-Framework schon vorhanden- Rahmen ist mit dem Ultris-Rahmen fast identisch
Erforderliche Includes:
# include <stdio.h># include <stdarg.h># include <windows.h># include <commctrl.h># include <d3dx9.h># include <dinput.h># include "d3dfont.h"
# include "resource.h„
HINSTANCE balance_instance; // Instanz-HandlerHWND balance_window; // Handler für Hauptfenster der Applikation
- Neuer Name des Eventhandlers- WM_GETMINMAXINFO Message wird nicht behandelt, da Fenstergröße frei
veränderbar sein soll
LRESULT CALLBACK balance_windowhandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{switch( msg)
{case WM_COMMAND:
switch( LOWORD(wParam)) {
case IDM_EXIT:PostMessage( hWnd, WM_CLOSE, 0, 0);return 0;}
break;case WM_DESTROY:
PostQuitMessage( 0);return 0;}
return DefWindowProc(hWnd, msg, wParam, lParam);}
Hauptprogramm
- nur Unterschiede in Benennung der Handles, Ressourcensymbole und des Windows-Handlers
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
...//Anlegen des Fenstersbalance_window = CreateWindowEx(0, TEXT( "Balance"),
TEXT( "Balance"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0,
CW_USEDEFAULT, // System-Defaults in der Fenstergröße
0, NULL, NULL, hInst, NULL);...}
- Keine Stelle, um aus der Hauptverarbeitungsschleife heraus das Spiel regelmäßig zu aktualisieren
Spiel starten / testen:
- Leeres Fenster, das in der Größe veränderbar ist
- Warnungen beim Start können ignoriert werden
- stammen von inkludierten Libraries, die momentan noch nicht verwendet werden
Balance V02
Initialisieren und Darstellen des Spielfeldes
S. 211 - 222
Die Klasse directX
class directx{public:
LPDIRECT3D9 d3d;LPDIRECT3DDEVICE9 device;D3DPRESENT_PARAMETERS d3dpp;
int init(); //wird als nächstes genauer betrachtetvoid adjust(int breite, int hoehe);
};
int directx::init(){
D3DDISPLAYMODE d3ddm;D3DDEVTYPE devtype;D3DCAPS9 caps;
d3d = Direct3DCreate9( D3D_SDK_VERSION); // Zeiger d3d erlaubt Zugriff auf grundlegende DirectX – Funktionen// Initialisierung des Zeigers mit der Funktion Direct3DCreate9
- Schnittstelle, die durch d3d zur Verfügung steht
- Überwiegend technische Details des Grafik-Adapters
- Für Balance werden nur Standard-möglichkeiten genutzt, um das Spiel möglichst schnell zum Laufen zu bringen
Weiter in init-Funktion ...if( !d3d) return 0;
if( d3d->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm) < 0)// Display-Modus wird in Variable d3ddm ausgelesen return 0;
ZeroMemory( &d3dpp, sizeof(d3dpp)); //Präsentationsparameter d3dpp wird gesetzt//ZeroMemory: Parameter, die nicht im Folgenden explizit erwähnt werden, erhalten den
Wert 0
d3dpp.Windowed = TRUE; //Umstellung auf Windowed-Mode (Darstellung des Spiels in einem Fenster)
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.BackBufferFormat = d3ddm.Format; //bestehendes Display-Format für den Backbuffer übernehmen
Graphic Device Interface (GDI):
-Von klassischen Windows-Anwendungen (z.B. Word, Explorer) verwendet
-erlaubt Darstellung von Text und Zeichnungen auf dem Bildschirm
Direct3D-API (Application Programming Interface):
- Von 3D Spielen verwendet
- Erlaubt Rendern dreidimensionaler Objekte
-> benutzt HAL
Hintergrundinformationen:
HAL (Hardware Abstraction Layer)
-versucht alle Operationen möglichst direkt auf der Hardware auszuführen
-nur wenn Grafikkarte eine Operation nicht unterstütz, wird sie in der HAL-Software nachgebildet (langsamer)
- alternativ Reference Device: Emulation der Direct3D Funktionen in Software
Weiter in init-Funktion:
//Prüfung, ob HAL verfügbar ist
if( d3d->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps) < 0)
{MessageBox( balance_window, "Kein HAL-Device - das wird langsam!",
"Balance-Meldung", MB_OK | MB_ICONWARNING | MB_SETFOREGROUND);devtype = D3DDEVTYPE_REF; //Speicherung in devtype: kein HAL}
elsedevtype = D3DDEVTYPE_HAL; //Speicherung in devtype: HAL verfügbar
// Anlegen des Devices, das im Folgenden benutzt wird
if( d3d->CreateDevice( D3DADAPTER_DEFAULT, devtype, balance_window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device) < 0)
return 0; // Initialisierung gescheitert return 1; // Initialisierung hat vollständig funktioniert
}
adjust-Funktion
- Wird aufgerufen, wenn sich die Größe des Fensters ändert- DirectX-Einstellungen müssen dann an neue Fenstergröße (breite, höhe) angepasst
werden
void directx::adjust( int breite, int hoehe){
D3DXMATRIX proj;
d3dpp.BackBufferWidth = breite; // Anpassen des Backbuffers d3dpp.BackBufferHeight = hoehe;
device->Reset( &d3dpp); // Reset des Devices
- Ganz am Anfang setzt System in der Funktion CreateDevice bei gewähltem Windowed-Mode die Koordinaten des aktiven Fensters zu Bestimmung der Backbuffergröße heran
- Änderung des Render-State des Devices:device->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE); // z-Buffering
aktivierendevice->SetRenderState( D3DRS_AMBIENT, 0xffffff); //Umgebungsbeleuchtung
einschalten
Z-Buffering:
- Wichtig für Tiefe (z-Achse)- Vorne liegende Objekte verdecken andere,
die weiter hinten liegen- Kostet Rechenzeit
-> lässt sich abstellen, wenn es nicht benötigt wird (wenn man jederzeit weiß, was vorne und hinten ist)
Beleuchtung:
- Farbe Weiß: 0xffffff
- Auch andere Farbwerte möglich, z.B.: 0xff0000, 0x00ff00, 0x0000ff
- Umgebungslicht ist ungerichtetes, gleichmäßiges Licht ohne Schatten
Fehler bei ausgeschaltetem z-Buffer
Weiter in adjust Funktion:- Projektionsmatrix proj wird erzeugt und mit SetTransform festgelegt
D3DXMatrixPerspectiveFovLH( &proj, D3DX_PI/4,
((float)breite)/hoehe, 1.0f, 500.0f);
device->SetTransform( D3DTS_PROJECTION, &proj); //Projektion zur Darstellung der Szene festlegen
}
Parameter:
Blickfeldwinkel:
Kleiner Winkel (z.B. Teleobjektiv)
-> entfernte Dinge rücken nah heran
-> alles rückt in der Tiefe nah zusammen
Großer Winkel (z.B. Weitwinkelobjektiv)-> Dinge rücken auseinander-> Landschaft wirkt flacher/ niedriger
Der menschlichen Sehweise entspricht etwa ein Winkel von 45° im Bogenmaß, also etwa π/4.
Begrenzungsebenen:
- Beschränken Blickfeld in der Tiefe
- Bereich davor/dahinter wird abgeschnitten
-Sichtbarer Teil mit Pyramidenstumpf vergleichbar
-aber: normalerweise werden nahe liegende Dinge perspektivisch vergrößert
-> Blickfeld wird am Blickpunkt auseinander gezogen, um dies zu erreichen
-> perspektivische Transformation durch Projektionsmatrix
Ansichtsverhältnis- Quotient aus Breite und Höhe des Blickfeldes- Parameter sorgt dafür, dass bei der perspektivischen Transformation keine
Verzerrungen auftreten
-> Alle Parameter-Funktionen anschaulich im Demoprogramm Projektion.
Schließlich Instanziierung eines Objekts der Klasse directx:
directx mein_directx;
Die Klasse objekt- Dient zur Aufnahme der Drahtmodelle- Kapselung der Daten eines Drahtmodells:
class objekt
{
private:
LPD3DXMESH mesh; // Mesh mit Vertices und Faces
D3DMATERIAL9 *materialien;
DWORD anz_mat; // gewisse Anzahl der Materialien
LPDIRECT3DTEXTURE9 *texturen; //zu jedem Material eine Textur
public:
objekt(); // Konstruktor
void load( char *xfile); // Objekt aus x-Datei laden
void draw(); // auf dem Bildschirm darstellen
~objekt(); // Destruktor
};
Konstruktor
- Vorbesetzung der Member-Variablen mit 0:
objekt::objekt()
{
mesh = NULL;
materialien = NULL;
anz_mat = 0;
texturen = NULL;
}
Funktion load
void objekt::load( char *xfile){
LPD3DXBUFFER buf;D3DXMATERIAL* mat; DWORD i;
// Mesh wird aus der Datei geladen D3DXLoadMeshFromX( xfile, D3DXMESH_SYSTEMMEM, mein_directx.device, NULL,
&buf, // Buffer mit Material- und Texturinformationen
NULL, &anz_mat, // Information über Anzahl der
Materialien&mesh); // Mesh wird in eine interne Struktur
geladen
mat = (D3DXMATERIAL*)buf->GetBufferPointer(); // Zeiger mat wird initialisiert, um auf Materialdaten im Buffer zugreifen zu
können //Arrays für Material- und Texturdaten, werden angelegt: materialien = new D3DMATERIAL9[anz_mat]; texturen = new LPDIRECT3DTEXTURE9[anz_mat];
for( i=0; i<anz_mat; i++) // Schleife durch die Materialien Texturen aus den Textur{
materialien[i] = mat[i].MatD3D; // Materialdaten werden in Array übertragen
// Materialen werden auf volle Reflexion (1.0) gesetzt, damit Licht reflektiert wirdmaterialien[i].Ambient.r = 1.0f;materialien[i].Ambient.g = 1.0f;materialien[i].Ambient.b = 1.0f;
// Texturen aus Dateien laden:if( D3DXCreateTextureFromFile( mein_directx.device,
mat[i].pTextureFilename, &texturen[i]) < 0)
texturen[i] = NULL;}
buf->Release(); // Buffer wird wieder frei gegeben }
Destruktor- Ressourcen zur Speicherung des Objekts sind dynamisch allokiert-> müssen beim Abbau des Objekts wieder freigegeben werden
objekt::~objekt(){unsigned int i;
if( materialien) delete[] materialien;
if( texturen){
for( i = 0; i < anz_mat; i++ ){
if( texturen[i]) texturen[i]->Release();
} delete[] texturen;
} if( mesh) mesh->Release();
}
Methode draw
void objekt::draw(){unsigned int i;
for( i=0; i < anz_mat; i++ ) // Schleife durch alle Materialien{
// Material und zugehörige Textur in das Device laden:mein_directx.device->SetMaterial( &materialien[i]);
mein_directx.device->SetTexture( 0, texturen[i]);
mesh->DrawSubset( i); // Teilgitternetz zeichnen, das mit Material und Textur belegt wurde
}}
Zu beachten:- Device kann zu einem Zeitpunkt immer nur ein Material + Textur aufnehmen- kann aber ein ganzesTeilgitternetz, das damit belegt ist, rendern