IrrLicht入門基礎

一、Irrlicht引擎簡介

Irrlicht引擎是一個用C++編寫的高性能實時3D引擎。該引擎支持底層圖形接口Direct3DOpenGL,並且自帶了軟件渲染的實現。Irrlicht引擎還提供了諸如動態陰影,粒子系統,角色動畫,室內和室外技術以及碰撞檢測等功能特性。

Irrlicht是一個德國神話故事中的一種動物的名字,它能夠發光和飛翔,可以在大部分的沼澤地附近發現它。單詞"Irrlicht"是兩個德國單詞("irr"意思是瘋狂的;而"Licht"意思是光)的組合。在英語中,它被譯爲"鬼火"。 

二、Irrlicht引擎的組成結構

Irrlicht引擎共分爲五部分:

1)Core

該部分由一些容器類及數學庫組成,如stringvector等。

對應的名字空間爲:namespace irr::core

2)Scene

該部分主要負責三維場景的繪製及管理,包括場景節點,攝像機,粒子系統、mesh 資源,公告板,燈光,動畫器,天空體,地形等。

Irrlicht的場景中的所有的東西都是場景節點,統一由場景管理器來管理。

對應的名字空間爲:namespace irr::scene

3)Video

該部分主要負責圖片紋理的載入及管理,包括紋理,材質,燈光,圖片,頂點等渲 染屬性的控制。

對應的名字空間爲:namespace irr::video

4)GUI

該部分包括了一些二維GUI控件

對應的名字空間爲:namespace irr::gui

5)FileSystem

該部分負責文件系統的讀寫。

對應的名字空間爲:namespace irr::io

三、Irrlicht編程步驟

1、獲取設備指針

在編寫任何一個Irrlicht程序時,首選需要做的就是獲取設備指針 

IrrlichtDevice  *device :

 video::E_DRIVER_TYPE driver_type = irr::video::EDT_OPENGL;   

 core::dimension2d<s32> screen_resolution = core::dimension2d<s32>(1280, 800);   

 u32 color_depth = 32;   

 bool is_full_screen = true;   

   

 IrrlichtDevice* device = irr::createDevice(driver_type, screen_resolution, color_depth, is_full_screen); 

driver_type爲驅動類型,可以選擇OPENGLDX8 或 DX9。其餘幾個參數分別爲分辨率,顏色 深度,是否全屏。

獲得 device 指針以後,就可以得到屬於該 device 的四大塊功能:

video::IVideoDriver* driver = device->getVideoDriver();   

scene::ISceneManager* scene_mgr = device->getSceneManager();   

gui::IGUIEnvironment* gui_env = device->getGUIEnvironment();   

io::IFileSystem* file_system = device->getFileSystem();  

2、創建3D場景

創建3D場景有三個步驟:

(1) 通過場景管理器scene_mgr添加3D物體

 // 爲場景添加一個立方體,邊長100  

 scene::ISceneNode* cube = scene_mgr->addCubeSceneNode(100.0f);   

(2) 爲3D物體貼上紋理:

 // 載入紋理  

 video::ITexture* tex = driver->getTexture("box.jpg");   

   

 // 將紋理附加到立方體上  

 cube->setMaterialTexture(0, tex);   

   

 // 將紋理EMF_LIGHTING屬性設爲false  

 // 表示該紋理現實與光源無關,即爲圖片自身顏色  

 cube->setMaterialFlag(video::EMF_LIGHTING, false);   

   

 // 使紋理支持半透明,半透明效果與圖片相同  

 cube->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL);   

(3) 添加Camera,使物體可見

 // 添加一個相機,在(700,700,-700)位置,往(0,0,0)位置拍攝。  

 scene::ICameraSceneNode* camera = scene_mgr->addCameraSceneNode(0,    

     core::vector3df(700,700,-700), core::vector3df(0,0,0));  

3、進入主循環

通過 driver 載入圖片和 texture,通過 scene_mgr 3d場景添加 irrlicht 內置支持的3D對象等工作後,即可進入主循環,主循環結束時,釋放 device,程序結束。其中 beginScene 的參數 SColor(alpha, r, g, b) 爲背景色

1 while (device->run())   

2 {   

3     if (device->isWindowActive())   

4     {   

5         driver->beginScene(true, true, video::SColor(0, 0, 0, 0));   

6         scene_mgr->drawAll();   

7         gui_env->drawAll();   

8         driver->endScene();   

9     }   

10 }   

11 device->drop();  

值得一提的是 drop() 函數。Irrlicht中大部分類都繼承自一個 IReferenceCounted 的接口,類似智能指針。Irrlicht 中的慣例是不使用 delete 刪除對象,而調用該接口的 drop() 函數。在添加對象的引用時,調用 grap() 函數。

四、Irrlicht引擎之場景中的對象結構

3D對象在場景中被組織成一個樹形結構,在該樹中,僅有一個根節點。當在程序的主循環中調用scene_mgr->drawAll()時,系統會從場景的樹形結構的根節點開始遞歸繪製所有的節點對象。

每一個節點對象都維護了一個“動畫效果”ISceneNodeAnimator列表:

core::list<ISceneNodeAnimator*> Animators;

在繪製每一個節點對象之前,都會將其所維護的所有動畫效果應用到該節點上。

“動畫效果”的原理是,當節點每次被繪製之前,均先根據其維護的動畫對象Animators來計算出該節點的位置、大小、紋理。這樣,當一個節點不斷被繪製時,就產生了動畫效果。

五、Irrlicht引擎之3D對象運動原理

所謂運動,實際上是計算機在不停地繪製場景,每繪製一次稱之爲一幀。 當各幀中物體的位置或外觀有所變化,那麼它就動起來了。 在irrlicht中,繪製一幀是在run循環中完成的:

1 while (device->run())   

2 {   

3     if (device->isWindowActive())   

4     {   

5         driver->beginScene(true, true, video::SColor(0, 0, 0, 0));   

6         scene_mgr->drawAll();  // 繪製一幀  

7         driver->endScene();   

8     }   

9 }   

10 device->drop();  

我們所要做的,就是在 drawAll() 函數中,更新物體的位置及大小等屬性,那麼場景就動起來了。

在Irrlicht中,所有與運動相關的一切,都與 scene::ISecenNodeAnimator 這個接口相關。凡是實現這個接口的類實例,都可以通過 addAnimator() 函數加入到 ISceneNode 所維護的animators列表中。 

SceneManager drawAll() 函數在渲染(render)場景前,會調用其OnAnimate() 函數。這個函數是遞歸的,以保證加入場景中的每個 SceneNode 會被調用。 在OnAnimate() 函數中, SceneNode 的每一個 ISecenNodeAnimator 的 animateNode() 函數都會被調用,以更新 SceneNode 的位置、大小或紋理等屬性。 

其具體的調用順序如下: 

1. SceneManager           --> drawAll()                 繪製一幀畫面

2. ISceneNode             --> OnAnimate()              SceneNode運動  

3. ISceneNodeAnimator --> animateNode(ISceneNode)      實現運動的具體函數

4. SceneManager           --> render()                  渲染

 

可見,只要實現 ISecenNodeAnimator 接口,並加入到 SceneNode 中,就能夠讓該SceneNode 運動起來。而至於具體如何運動,完全可由自己來定義。

六、Irrlicht引擎之消息傳遞原理

Irrlicht引擎中消息的傳遞是從device->run()開始的,首先由具體平臺的操作系統接口將接收到的用戶消息打包成IrrlichtSEvent結構(這一步打包過程是在device->run()中完成的),再由postEventFromUser()該消息依次傳遞給UserReceiver, GUI 和 3D Scene

Irrlicht 中所有處理消息的類都必須實現 IEventReciever 接口。UserReceiver 就是在CreateDevice函數中指定的一個 IEventReceiver。 也就是說,消息處理的優先級爲 UserReceiver > GUI > 3D Scene

如果在程序中,沒有指定UserReceiver和GUI,消息就會直接交給SceneManager

SceneManager 的消息,也由 ISceneManager 的 postEventFromUser() 傳遞。 這個函數的實現如下:

1 bool CSceneManager::postEventFromUser(const SEvent& event)   

2 {   

3     bool ret = false;   

4     ICameraSceneNode* cam = getActiveCamera();   

5     if (cam)   

6         ret = cam->OnEvent(event);   

7   

8     _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;   

9     return ret;   

10 }  

也就是說,只有當前Active(有效)的 ICameraSceneNode 纔會接收到消息。ICameraSceneNode 會檢測ISceneNodeAnimator isEventReceiverEnabled(), 如果爲真則調用其OnEvent 函數。 

整理消息傳遞的機制如下:

 

1. IrrlichtDevice           --> run()                      蒐集消息並打包

2. IrrlichtDevice           --> postEventFromUser()    傳遞消息到userReceiver     GUI 和 Scene

3. ISceneManager         --> postEventFromUser()       傳遞消息到CameraNode

4. ICameraSceneNode     --> onEvent()                  調用 Animator onEvent

5. ISceneNodeAnimator    --> onEvent()  // if enabled      響應消息。

 

可見,實現 ISceneNodeAnimator 雖然可以 SceneNode 動起來,但只有在 ICameraSceneNode 上,才能夠接收和處理消息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章