Tutorial:Scenegraph2

aus ZFXCE, der freien Wissensdatenbank

Inhaltsverzeichnis

Basisidee der ZFXCE-Resourcen-Verwaltung

Daten wie zum Beispiel Leveldaten werden in der ZFX-Community-Engine durch einen Resourcenmanager angesprochen. Dieser verwaltet zum einen die Resourcen, kann sie von der Festplatte laden, bei Bedarf entladen und nicht benötigte Resourcen wieder freigeben. Liegt z.B. ein Quake3-Level in einem Quake3-Archiv, kann der Resourcemanager die Daten direkt aus dem Archiv laden (Quake3-Archive sind im eigentlichen Sinne nur Zip-Archive, die die ZFX-Community-Engine auslesen kann). Der Resourcemanager gibt dem Anwender nach dem Laden und Bearbeiten die Daten in einer speziellen Resource-Klasse wie zum Beispiel einem ceMesh zurück. Mittels dieser Resource kann man nun weiter mit den Daten arbeiten.

Vorbereitungen

 
//Erzeugen eines Szenegraphen
ceSceneGraph *pSG = ceMainApp::CreateSceneGraph();
		
// Erzeugen eines Rendermodules
pSG->SetRenderSystem((Render::ceRenderSystem*) CreateSystemFromDynLib(DynLib::CE_RENDER_OGL));
		
// Erzeugen einer Rendersurface
pSG->CreateRenderSurface(ce_string("Apptest"), 0,0, SceneGraph::CE_1024_768, false, 4,
			24, 24, 0, ceColorRGBA(1.0f, 1.0f, 1.0f, 0.0f));
 

Um sich in dem Quake3-Level bewegen zu können, braucht man noch eine First-Person-Kamera. Auch diese erhält man durch den Szenegraphen:

 
m_pCamera = pSG->CreateCamera("default", ceVec3f(0.0f, 0.0f, 0.0f), 
		ceVec3f(1.0f, 1.0f, 0.0f), NULL);

Nun ist man soweit und kann den Scenegraphen zum Einsatz fertig machen, in dem man ihn initialisiert:

 
pSG->InitSystem();

Laden einer Resource

Wie im Erste-Schritte-Beispiel zu sehen war, kann man aus der Mainapplikation den Resourcenmanager anfordern. In diesem Fall weisen wir den Resourcemanager an, ein Mesh aus einem Q3-Archiv zu laden.

 
vector<ce_string> vParam;
ceMesh *pMesh = (ceMesh*) ceMainApp::GetResourceServer()->CreateResource("test1.mesh", "maps/cht3.bsp", vParam);

Der Resourcemanager sieht durch die Extention:

*.mesh

dass er eine Resource vom Typ ceMesh generieren soll. Der Name ist in diesem Fall test1. Spezielle Parameter wollen wir nicht übergeben, so dass wir den Parameterarray leer lassen können. Konnte die Datei nicht in den vorhandenen Archiven gefunden werden, wird NULL zurückgegeben. Das Eingabefile wird durch die Extention:

*.bsp 

erkannt. Alle im Arbeitsverzeichnis vorliegenden Files werden nun durchsucht. Handelt es sich um ein gezipptes Archiv, durchsucht das VFS der ZFXCE dieses ebenfalls nach dem angegebenen File (Hinweis: Q3-Level werden als komplettes Zip-Archiv angelegt, in dem man die Levelgeometrie unter maps ablegt).

Erstellen eines Scenenodes

Das geladene Mesh kann nun mittels eines Scenenodes in den Scenegraphen eingehängt werden:

 
ceSceneNode *pNode = pSG->CreateSceneNode(std::string("testnode1"), pMesh, ceVec3f(1.0f, 1.0f, 1.0f), NULL);

Der neu kreierte Scenenode wird nun direkt ins Wurzelverzeichnis des Szenegraphen eingehängt:

 
Root
 +->pNode1

Beim Aktualisieren wird dieser Node nun vom Scenegraph mit abtraversiert und gerendert. Scenenodes stellen die einfachste Form eines Scenegraph-Nodes dar. Die Grafik-Informationen werden direkt gerendert. Es finden keine Cullingstrategien der Renderdaten im Scenenode Anwendung. Nun kann man das Quake3-Level rendern lassen.

Bewegen im Level

Man braucht nun noch einige Eventlistener, die das Steuern der First-Person-Kamera übernehmen: Als erstes binden wir im Init-Teil die Eventlistener an das Eventdevice

 
// Füge Eventlistener für Taste gedrückt, Taste losgelassen und Maus bewegt hinzu
GetInputDevice()->AddEventListener(Input::ceKeyboardButtonDownEvent,
			ceEventFunctor::Make(this, &MeshLoader::OnKeyPressed));
GetInputDevice()->AddEventListener(Input::ceKeyboardButtonUpEvent,
			ceEventFunctor::Make(this, &MeshLoader::OnKeyUp));
GetInputDevice()->AddEventListener(Input::ceMouseMoveEvent,
			ceEventFunctor::Make(this, &MeshLoader::OnMouseMove));

Diese müssen nun noch implementiert werden. Die ZFXCE-First-Person-Kamera verwaltert Bewegungsstates. Durch Setzen dieser Flags kann man die Kamera entsprechend per Tastatur bewegen. Der Einfachheit halber zeige ich hier einen Weg, um die aus Egoshootern allseits bekannte Tastaturkonfiguration zu kopieren. Zunächst müssen wir bei den Tastendrücken die entsprechenden States setzen:

 
void MeshLoader::OnKeyPressed(const ceEvent& ev, const ceEventData* data)
{
	// Extrahiere Keyboardinfo aus dem Event
	const Input::ceKeyboardButtonEventData* key = 
		(Input::ceKeyboardButtonEventData*)data;
	switch(key->m_Key) {
	// Beende Programm
	case Input::CE_KEY_ESCAPE:
		exit(0);
		break;
 
	// Rückwärts
	case Input::CE_KEY_s:
		m_pCamera->MoveBackward(true);
		break;
 
	// Vorwärts
	case Input::CE_KEY_w:
		m_pCamera->MoveForward(true); 
		break;
 
	// Seitlich links
	case Input::CE_KEY_a:
		m_pCamera->StrafeLeft(true);
		break;
 
	// Seitlich rechts
	case Input::CE_KEY_d: 
		m_pCamera->StrafeRight(true); 
		break;
	}
}

Nun müssen wir noch die Beweguns-Flags nach den Loslassen der Tasten wieder zurücksetzten:

 
void MeshLoader::OnKeyUp(const ceEvent& ev, const ceEventData* data)
{	
	// Get keybord event data
		Input::ceKeyboardButtonEventData* key = 
			(Input::ceKeyboardButtonEventData*)data;
	switch(key->m_Key) {
	// Vorwärts gehen
	case Input::CE_KEY_w:
		m_pCamera->MoveForward(false);
		break;
 
	// Rückwarts gehen
	case Input::CE_KEY_s:
		m_pCamera->MoveBackward(false);
		break;
 
	// Seitlich links fertig
	case Input::CE_KEY_a:
		m_pCamera->StrafeLeft(false);
		break;
 
	// Seitlich rechts fertig
	case Input::CE_KEY_d:
		m_pCamera->StrafeRight(false);
		break;
	}
}

Abschliessend setzen wir nun noch die Richtung der Kamera:

 
void MeshLoader::OnMouseMove(const ceEvent& ev, const ceEventData* data)
{
	// Get mouse event data
	const Input::ceMouseMoveEventData* mouse = 
		(Input::ceMouseMoveEventData*)data;
		
	// Set new view by mouse
	m_pCamera->SetViewByMouse(mouse->m_RelX, mouse->m_RelY);
}

Abschliessende Worte

Den kompletten Code kann man sich in der ZFXCE unter:

 
ZFXC-Engine/demos/MeshLoader

ansehen

Andere Sprachen

'Persönliche Werkzeuge
ZFXC-Engine