+
+ Lets start like the HelloWorld example: We include the irrlicht header
+ files and an additional file to be able
+ to ask the user for a driver type using the console.
+
+
+ #include <irrlicht.h> #include <iostream>
|
+
+
+ As already written in the HelloWorld example, in the Irrlicht Engine,
+ everything can be found in the namespace 'irr'. To get rid of the irr::
+ in front of the name of every class, we tell the compiler that we use
+ that namespace from now on, and we will not have to write that 'irr::'.
+ There are 5 other sub namespaces 'core', 'scene', 'video', 'io' and
+ 'gui'. Unlike in the HelloWorld example, we do not a 'using namespace'
+ for these 5 other namespaces because in this way you will see what can
+ be found in which namespace. But if you like, you can also include the
+ namespaces like in the previous example. Code just like you want to.
+
+
+ using namespace irr; |
+
+
+ Again, to be able to use the Irrlicht.DLL file, we need to link with
+ the Irrlicht.lib. We could set this option in the project settings,
+ but to make it easy, we use a pragma comment lib:
+
+
+ #pragma comment(lib, "Irrlicht.lib") |
+
+
+
+
+ Ok, lets start. Again, we use the main() method as start, not the WinMain(),
+ because its shorter to write.
+
+ Like in the HelloWorld example, we create an IrrlichtDevice with createDevice().
+ The difference now is that we ask the user to select which hardware accelerated
+ driver to use. The Software device would be too slow to draw a huge Quake
+ 3 map, but just for the fun of it, we make this decision possible too.
+
+
+ // ask user for driver
video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;
printf("Please select the driver you want for this example:\n"\ " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\ " (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\ " (f) NullDevice\n (otherKey) exit\n\n");
+char i; std::cin >> i;
switch(i) { case 'a': driverType = video::EDT_DIRECT3D9;break; case 'b': driverType = video::EDT_DIRECT3D8;break; case 'c': driverType = video::EDT_OPENGL; break; case 'd': driverType = video::EDT_SOFTWARE; break; case 'e': driverType = video::EDT_BURNINGSVIDEO;break; case 'f': driverType = video::EDT_NULL; break; default: return 1; }
// create device and exit if creation failed
IrrlichtDevice *device = createDevice(driverType, core::dimension2d<s32>(640, 480));
if (device == 0) return 1; |
+
+
+ Get a pointer to the video driver and the SceneManager so that we do
+ not always have to write device->getVideoDriver() and device->getSceneManager().
+
+
+ video::IVideoDriver* driver = device->getVideoDriver();
+scene::ISceneManager* smgr = device->getSceneManager(); |
+
+
+ To display the Quake 3 map, we first need to load it. Quake 3 maps are
+ packed into .pk3 files wich are nothing other than .zip files. So we add
+ the .pk3 file to our FileSystem. After it was added, we are able to read
+ from the files in that archive as they would directly be stored on disk.
+
+
+ device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3"); |
+
+
+ Now we can load the mesh by calling getMesh(). We get a pointer returned
+ to a IAnimatedMesh. As you know, Quake 3 maps are not really animated,
+ they are only a huge chunk of static geometry with some materials attached.
+ Hence the IAnimated mesh consists of only one frame,
+ so we get the "first frame" of the "animation", which
+ is our quake level and create an OctTree scene node with it, using addOctTreeSceneNode().
+ The OctTree optimizes the scene a little bit, trying to draw only geometry
+ which is currently visible. An alternative to the OctTree would be a AnimatedMeshSceneNode,
+ which would draw always the complete geometry of the mesh, without optimization.
+ Try it out: Write addAnimatedMeshSceneNode instead of addOctTreeSceneNode
+ and compare the primitives drawed by the video driver. (There is a getPrimitiveCountDrawed()
+ method in the IVideoDriver class). Note that this optimization with the
+ Octree is only useful when drawing huge meshes consiting of lots of geometry.
+
+
+ scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp"); scene::ISceneNode* node = 0;
+
+if (mesh) node = smgr->addOctTreeSceneNode(mesh->getMesh(0)); |
+
+
+ Because the level was modelled not around the origin (0,0,0), we translate
+ the whole level a little bit.
+
+
+ if (node) node->setPosition(core::vector3df(-1300,-144,-1249)); |
+
+
+ Now we only need a Camera to look at the Quake 3 map. And we want to
+ create a user controlled camera. There are some different cameras available
+ in the Irrlicht engine. For example the Maya Camera which can be controlled
+ compareable to the camera in Maya: Rotate with left mouse button pressed,
+ Zoom with both buttons pressed,
+ translate with right mouse button pressed. This could be created with
+ addCameraSceneNodeMaya(). But for this example, we want to create a camera
+ which behaves like the ones in first person shooter games (FPS):
+
+
+ smgr->addCameraSceneNodeFPS(); |
+
+
+ The mouse cursor needs not to be visible, so we make it invisible.
+
+
+ device->getCursorControl()->setVisible(false); |
+
+
+ We have done everything, so lets draw it. We also write the current frames
+ per second and the drawn primitives to the caption of the window. The
+ 'if (device->isWindowActive())' line is optional, but prevents the
+ engine render to set the position of the mouse cursor after task switching
+ when other program are active.
+
+
+ int lastFPS = -1;
+ while(device->run())
+{
+ driver->beginScene(true, true, video::SColor(0,200,200,200));
+ smgr->drawAll();
+ driver->endScene();
+ int fps = driver->getFPS();
+ if (lastFPS != fps)
+ {
+ core::stringw str = L"Irrlicht Engine - Quake 3 Map example ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps;
+ }
+} |
+
+
+ In the end, delete the Irrlicht device.
+
+
+ device->drop(); return 0; } |
+
+
+ That's it. Compile and play around with the program. |
+
+