2009年4月6日 星期一

IrrLicht Example Learn: 02. Quake3Map

 

02. Quake3Map Learn

 

以下內容部分來自於此鏈結

http://www.cppblog.com/irrwowview/articles/55310.html

 

這個DEMO 說明了 顯示QUAKE3 BSP 文件的方法, 但目前irrlicht BSP 文件的解碼尚存在問題.

以及目前尚未找到可以正確顯示以及編輯 BSP 文件的軟件, 所以暫時在使用上還是有問題.

 

 

int main()

{

     /*

     Like in the HelloWorld example, we create an IrrlichtDevice with

     createDevice(). The difference now is that we ask the user to select

     which video driver to use. The Software device might 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;

 

     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) Burning's 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(640, 480));

 

     if (device == 0)

         return 1; // could not create selected driver.

 

     /*

     Get a pointer to the video driver and the SceneManager so that

     we do not always have to call irr::IrrlichtDevice::getVideoDriver() and

     irr::IrrlichtDevice::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 which are nothing else than .zip files.

     So we add the .pk3 file to our irr::io::IFileSystem. After it was added,

     we are able to read from the files in that archive as if they are

     directly stored on the disk.

     */

     /*

          Pk3 格式為Quake3 的文件, zip格式壓縮, pk3改成zip可以解壓縮看到內容.

           再此將pk3文件掛載到irr文件系統中, 等待以後讀取.

*/

     device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3");

 

     /*

     Now we can load the mesh by calling

     irr::scene::ISceneManager::getMesh(). We get a pointer returned to an

     irr::scene::IAnimatedMesh. As you might know, Quake 3 maps are not

     really animated, they are only a huge chunk of static geometry with

     some materials attached. Hence the IAnimatedMesh 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

     irr::scene::ISceneManager::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

     irr::scene::IMeshSceneNode, which would always draw the complete

     geometry of the mesh, without optimization. Try it: Use

     irr::scene::ISceneManager::addMeshSceneNode() instead of

     addOctTreeSceneNode() and compare the primitives drawn by the video

     driver. (There is a irr::video::IVideoDriver::getPrimitiveCountDrawn()

     method in the irr::video::IVideoDriver class). Note that this

     optimization with the OctTree is only useful when drawing huge meshes

     consisting of lots of geometry.

     */

     /*

         使用 smgr->GetMesh 讀取mesh文件, 剛剛文件系統中已登陸的map020kdm2.pk3 文件包中的 20kmd2.bsp 文件.

        Quake3地圖是不能活動的,它們只是一個附上材質的具大靜態幾何型。因此IAnimatedMesh只包含一幀,取得(first frame)根據它調用addOctTreeSceneNode()函數創建一個八叉數(OctTree)場景節點。

                   八叉數嘗試只繪製當前看到的幾何型來優化場景。另一種代替八叉樹(OctTree)的是活動網格場景節點(AnimatedMeshSceneNode),它會沒優化,只會把整個網格幾何型繪製出來。

試試這樣:addAnimatedMeshSceneNode()函數代替addAnimatedMeshSceneNode()函數並作一下比較(IVideoDriver類裏有一個getPrimitiveCountDrawed()函數)。

注意八叉樹(OctTree)優化只在大型網格地圖時有效。

     */

     scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");

     scene::ISceneNode* node = 0;

    

     if (mesh)

         node = smgr->addOctTreeSceneNode(mesh->getMesh(0), 0, -1, 1024);

//       node = smgr->addMeshSceneNode(mesh->getMesh(0));

 

     /*

     Because the level was not modelled around the origin (0,0,0), we

     translate the whole level a little bit. This is done on

     irr::scene::ISceneNode level using the methods

     irr::scene::ISceneNode::setPosition() (in this case),

     irr::scene::ISceneNode::setRotation(), and

     irr::scene::ISceneNode::setScale().

     */

     /*

              在此關卡中 原點(000)周圍無模型,改變了一下座標。

     */

     if (node)

         node->setPosition(core::vector3df(-1300,-144,-1249));

 

     /*

     Now we only need a camera to look at the Quake 3 map.

     We want to create a user controlled camera. There are some

     cameras available in the Irrlicht engine. For example the

     MayaCamera which can be controlled like 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

     irr::scene::ISceneManager::addCameraSceneNodeMaya(). But for this

     example, we want to create a camera which behaves like the ones in

     first person shooter games (FPS) and hence use

     irr::scene::ISceneManager::addCameraSceneNodeFPS().

     */

     /*

現在我們只需要一個攝像機就可以觀察Quake3的地圖。

IrrLicht引擎中有兩種攝像機 FPS, MAYA)。

這裡設定使用第一人稱射擊(first person shooter (FPS))遊戲的攝像機:

 

     */

     smgr->addCameraSceneNodeFPS();

 

     /*

     The mouse cursor needs not be visible, so we hide it via the

     irr::IrrlichtDevice::ICursorControl.

     */

     /*

         設定Mouse 游標隱藏

     */

     device->getCursorControl()->setVisible(false);

 

     /*

     We have done everything, so lets draw it. We also write the current

     frames per second and the primitives drawn into the caption of the

     window. The test for irr::IrrlichtDevice::isWindowActive() is optional,

     but prevents the engine to grab the mouse cursor after task switching

     when other programs are active. The call to

     irr::IrrlichtDevice::yield() will avoid the busy loop to eat up all CPU

     cycles when the window is not active.

     */

     int lastFPS = -1;

 

     while(device->run())

     {

         if (device->isWindowActive())

         {

              driver->beginScene(true, true, video::SColor(255,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;

              }

         }

         else

              device->yield();

     }

 

     /*

     In the end, delete the Irrlicht device.

     */

     device->drop();

     return 0;

}

 

/*

That's it. Compile and play around with the program.

**/

沒有留言: