En:Tutorial:Scenegraph2
aus ZFXCE, der freien Wissensdatenbank
Inhaltsverzeichnis |
Basic idea of the ZFXCE resource management
Data, like e.g. leveldata, can be accessed through a resource manager in the ZFXCE. It manages the resources, is able to load them from hard disk, if necessary unload them an free resources. For example if a Quake3 level is in a Quake3 archive, the resource manager can load the data directly from the archive (actually Quake3 archives are only zip archives, that the ZFXCE can read). After loading and editing, the resource manager returns the data in a special resource class, e.g. a ceMesh. Now the data can be further processed using the loaded resource.
Preparations
// Create a scenegraph ceSceneGraph *pSG = ceMainApp::CreateSceneGraph(); // Create a render module pSG->SetRenderSystem((Render::ceRenderSystem*) CreateSystemFromDynLib(DynLib::CE_RENDER_OGL)); // Create a render surface 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));
To be able to move around in the Quake3 level, wen need a first-person-camera. It can also be retrieved from the scenegraph:
m_pCamera = pSG->CreateCamera("default", ceVec3f(0.0f, 0.0f, 0.0f), ceVec3f(1.0f, 1.0f, 0.0f), NULL);
Now the time has come to get complete the scenegraph by initializing it:
pSG->InitSystem();
Loading a resource
As shown in the fist-steps-example, you can request the resource manager from the main app. In this case we instruct the resorce manager to load a mesh from a Quake3 archive.
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); }
By the extension
*.mesh
the resource manager realizes the it should generate a resource of the ceMesh type. The name is here test1. We do not want to give special parameters, so the vParam-array is left empty. If the files could not be found in the available archives, NULL is returned.
Creating a scenenode
The loaded mesh can now be mounted into the scenegraph by a scnenenode:
ceSceneNode *pNode = pSG->CreateSceneNode(std::string("testnode1"), pMesh, ceVec3f(1.0f, 1.0f, 1.0f), NULL);
The newly created scenenode is put directly in the root of the scenegraph:
Root +->pNode1
When refreshing the screen, this node is now traversed and rendered by the scenegraph. Scenenodes are the most simple form of a scenegraph node. The graphical information is rendered directly. There are no culling strategies applied to the rendering data in the scenenode. Now the Quake3 level can be rendered.
Movement in the level
We still need a bunch of event listeners, that take care of movement of the first-person-camera. In the init-part we bind the event listeners to the event device:
// Add event listener for key pressed, key released and mouse moved 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));
Now the event listeners have to be implemented. The ZFXCE first-person-camera manages movement states. By setting these flags we can move the camera according to the keys pressed. For convenience I present a way to clone the key configuration that is well known from several ego shooters. First we have to set the states corresponding to the keys pressed:
void MeshLoader::OnKeyPressed(const ceEvent& ev, const ceEventData* data) { // extract keyboard info from the event const Input::ceKeyboardButtonEventData* key = (Input::ceKeyboardButtonEventData*)data; switch(key->m_Key) { // quit program case Input::CE_KEY_ESCAPE: exit(0); break; // backward case Input::CE_KEY_s: m_pCamera->MoveBackward(true); break; // forward case Input::CE_KEY_w: m_pCamera->MoveForward(true); break; // left case Input::CE_KEY_a: m_pCamera->StrafeLeft(true); break; // right case Input::CE_KEY_d: m_pCamera->StrafeRight(true); break; } }
Now we have to reset the movement flags after the release of the key:
void MeshLoader::OnKeyUp(const ceEvent& ev, const ceEventData* data) { // Get keybord event data Input::ceKeyboardButtonEventData* key = (Input::ceKeyboardButtonEventData*)data; switch(key->m_Key) { // forward done case Input::CE_KEY_w: m_pCamera->MoveForward(false); break; // backward done case Input::CE_KEY_s: m_pCamera->MoveBackward(false); break; // left done case Input::CE_KEY_a: m_pCamera->StrafeLeft(false); break; // right done case Input::CE_KEY_d: m_pCamera->StrafeRight(false); break; } }
Now we set the direction of the camera:
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); }
Closing words
The complete sourcecode can be found in the ZFXCE in:
ZFXC-Engine/demos/MeshLoader
ZFXC-Engine
