1. 程式人生 > >開源3D遊戲引擎Irrlicht簡介

開源3D遊戲引擎Irrlicht簡介

Irrlicht簡介

Irrlicht在國內也被叫做“鬼火”引擎,是一款用C++編寫的開放原始碼的高效能遊戲引擎。而且是跨平臺的,具有很好的移植性,Irrlicht支援OpenGl、Direcx3D渲染,引擎本身也實現了一套自己的渲染系統。在商業引擎中能夠找到的藝術特性,Irrlicht基本都支援。目前有很多專案中都使用到它,Irrlicht社群也比較活躍,可以在網際網路上找到不少Irrlicht增強工具,例如irrEdit、irrKlang等。在眾多開源遊戲引擎中,Irrlicht也是比較受筆者青睞的一款。

Irrlicht下載與使用

Irrlicht目前最新穩定版本為1.8.1,專案釋出在sourceforge平臺上,使用者可以通過sourceforge網站首頁面搜尋功能找到Irrlicht專案下載地址,或者從Irrlicht官網獲取下載連結。

1.目錄結構

解壓後目錄結構如下:

Irrlicht引擎目錄結構

bin:不同平臺編譯Irrlicht生成的可執行檔案和動態庫檔案放在該目錄中。
doc : 該目錄中為Irrlicht API文件。
examples : Irrlicht官方提供的案例程式存放在該目錄中。
include : 存放引擎所有標頭檔案。
lib : 該目錄存放Irrlicht引擎編譯過後生成的靜態庫。
media : 官方案例所需資原始檔存放在此目錄中。
source : 存放引擎原始碼。
tools : 該目錄下為Irrlicht引擎相關工具。如irrEdit、GUIEditor等。

2.官方案例

Irrlicht使用起來是非常方便的,這也是筆者比較喜歡它的原因之一。為了方便使用者學習和使用引擎,Irrlicht官方提供了大量的例子程式,而且都比較具有代表性。

開啟examples目錄,Irrlicht已經為目前主流開發工具Windows平臺下Visual Studio、MacOS下的Xcode以及Linux平臺下的GNU MAKE做好了專案配置。

這裡寫圖片描述

筆者是在Windows作業系統下使用VS2012進行演示,雙擊BuildAllExamples_vc11.sln開啟解決方案,無需做任何配置即可編譯執行程式。

這裡寫圖片描述

編譯執行Collision案例程式:

這裡寫圖片描述

看起來效果是不是很炫呢?Irrlicht為我們做了大量的封裝,即便看似如此複雜的程式,實際程式碼不超過200行。

#include <irrlicht.h>
#include "driverChoice.h"
using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif enum { ID_IsNotPickable = 0, IDFlag_IsPickable = 1 << 0, IDFlag_IsHighlightable = 1 << 1 }; int main() { video::E_DRIVER_TYPE driverType=video::EDT_OPENGL;//driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; IrrlichtDevice *device = createDevice(driverType, core::dimension2d<u32>(1024, 768), 16, false); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3"); scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp"); scene::IMeshSceneNode* q3node = 0; if (q3levelmesh) q3node = smgr->addOctreeSceneNode(q3levelmesh->getMesh(0), 0, IDFlag_IsPickable); scene::ITriangleSelector* selector = 0; if (q3node) { q3node->setPosition(core::vector3df(-1350,-130,-1400)); selector = smgr->createOctreeTriangleSelector( q3node->getMesh(), q3node, 128); q3node->setTriangleSelector(selector); } scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 100.0f, .3f, ID_IsNotPickable, 0, 0, true, 3.f); camera->setPosition(core::vector3df(50,50,-60)); camera->setTarget(core::vector3df(-70,30,-60)); if (selector) { scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(30,50,30), core::vector3df(0,-10,0), core::vector3df(0,30,0)); selector->drop(); // As soon as we're done with the selector, drop it. camera->addAnimator(anim); anim->drop(); } device->getCursorControl()->setVisible(false); scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode(); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); bill->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZBUFFER, false); bill->setSize(core::dimension2d<f32>(20.0f, 20.0f)); bill->setID(ID_IsNotPickable); // This ensures that we don't accidentally ray-pick it scene::IAnimatedMeshSceneNode* node = 0; video::SMaterial material; node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/faerie.md2"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-90,-15,-140)); // Put its feet on the floor. node->setScale(core::vector3df(1.6f)); // Make it appear realistically scaled node->setMD2Animation(scene::EMAT_POINT); node->setAnimationSpeed(20.f); material.setTexture(0, driver->getTexture("../../media/faerie2.bmp")); material.Lighting = true; material.NormalizeNormals = true; node->getMaterial(0) = material; selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); // We're done with this selector, so drop it now. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/ninja.b3d"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setScale(core::vector3df(10)); node->setPosition(core::vector3df(-75,-66,-80)); node->setRotation(core::vector3df(0,90,0)); node->setAnimationSpeed(8.f); node->getMaterial(0).NormalizeNormals = true; node->getMaterial(0).Lighting = true; selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/dwarf.x"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-70,-66,-30)); // Put its feet on the floor. node->setRotation(core::vector3df(0,-90,0)); // And turn it towards the camera. node->setAnimationSpeed(20.f); node->getMaterial(0).Lighting = true; selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/yodan.mdl"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-90,-25,20)); node->setScale(core::vector3df(0.8f)); node->getMaterial(0).Lighting = true; node->setAnimationSpeed(20.f); // Just do the same as we did above. selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); material.setTexture(0, 0); material.Lighting = false; scene::ILightSceneNode * light = smgr->addLightSceneNode(0, core::vector3df(-60,100,400), video::SColorf(1.0f,1.0f,1.0f,1.0f), 600.0f); light->setID(ID_IsNotPickable); // Make it an invalid target for selection. scene::ISceneNode* highlightedSceneNode = 0; scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager(); int lastFPS = -1; material.Wireframe=true; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0); smgr->drawAll(); if (highlightedSceneNode) { highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, true); highlightedSceneNode = 0; } core::line3d<f32> ray; ray.start = camera->getPosition(); ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 1000.0f; core::vector3df intersection; core::triangle3df hitTriangle; scene::ISceneNode * selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay( ray, intersection, hitTriangle, IDFlag_IsPickable, 0); if(selectedSceneNode) { bill->setPosition(intersection); driver->setTransform(video::ETS_WORLD, core::matrix4()); driver->setMaterial(material); driver->draw3DTriangle(hitTriangle, video::SColor(0,255,0,0)); if((selectedSceneNode->getID() & IDFlag_IsHighlightable) == IDFlag_IsHighlightable) { highlightedSceneNode = selectedSceneNode; highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, false); } } driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Collision detection example - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; }