天天看點

Irrlicht(鬼火引擎)中多裝置的支援

理清一個引擎,不得不先理清它的層次結構,進而理清渲染流程。 本文給出了鬼火引擎中的裝置抽象層,有助于對鬼火引擎源碼的快速閱讀。

irrlichtdevice *device =

  createdevice(drivertype, core::dimension2d<u32>(640, 480),

  16, false, shadows);

這個函數大家都很熟悉,那閑話不多說,我們就從這裡開始。。。

irrlichtdevice 裝置的頂層接口

cirrdevicestub  實作裝置頂層接口類,所有裝置都從此派生,這裡的裝置是指和平台相關的裝置

類成員:

video::ivideodriver* videodriver;//   圖形接口

gui::iguienvironment* guienvironment;// gui接口

scene::iscenemanager* scenemanager;//場景節點接口

itimer* timer; //定時器,保證了一個裝置持有一個定時器

gui::icursorcontrol* cursorcontrol; //滑鼠控制器

ieventreceiver* userreceiver;//事件處理器

clogger* logger;//日志

iosoperator* operator; //系統操作相關

io::ifilesystem* filesystem; //檔案系統

scene::iscenemanager* inputreceivingscenemanager;   //

video::cvideomodelist videomodelist;   //圖形模式清單

sirrlichtcreationparameters creationparams;//建立圖形裝置時的參數

smousemulticlicks mousemulticlicks;   //滑鼠多擊(比輕按兩下還多)

從以上類成員就可以看出裝置裡面包含些什麼

下面是針對各種不同平台的實作類

cirrdeviceconsole

cirrdevicelinux

cirrdevicesdl

cirrdevicewin32

從類名可以看出是針對哪個平台的。cirrdeviceconsole是控制台

上面幾個平台的實作還除了派生于cirrdevicestub外,還派生于iimagepresenter

iimagepresenter隻有一個函數

//! presents a surface in the client area

virtual bool present(video::iimage* surface, void* windowid=0, core::rect<s32>* src=0 ) = 0;

輸出到目标客戶區。。。

對于平台相關的裝置的實作,拿win32的來說

下面是類成員:

core::position2d<s32> cursorpos;

core::dimension2d<u32> windowsize;

core::dimension2d<f32> invwindowsize;

bool isvisible;

hwnd hwnd;

s32 borderx, bordery;

bool usereferencerect;

core::rect<s32> referencerect;

可以看出,即是持有與平台相關的資料。平台無關的都被cirrdevicestub搞定啦

下面我們來仔細看看createdevice函數做了些什麼。

用法示例:

createdevice函數的參數意思就不多說了,會用api的人都知道。

實作如下:

irrlicht_api irrlichtdevice* irrcallconv createdevice(video::e_driver_type drivertype,

   const core::dimension2d<u32>& windowsize,

   u32 bits, bool fullscreen,

   bool stencilbuffer, bool vsync, ieventreceiver* res)

{

sirrlichtcreationparameters p;

p.drivertype = drivertype;

p.windowsize = windowsize;

p.bits = (u8)bits;

p.fullscreen = fullscreen;

p.stencilbuffer = stencilbuffer;

p.vsync = vsync;

p.eventreceiver = res;

return createdeviceex(p);

}

可以看出,它将參數指派給sirrlichtcreationparameters結構,然後調用createdeviceex

關鍵就是這個createdeviceex,實作了對應平台的建立

主要代碼如下

irrlichtdevice* dev = 0;

#ifdef _irr_compile_with_windows_device_

  if (params.devicetype == eidt_win32 || (!dev && params.devicetype == eidt_best))

   dev = new cirrdevicewin32(params);

#endif

#ifdef _irr_compile_with_osx_device_

  if (params.devicetype == eidt_osx || (!dev && params.devicetype == eidt_best))

   dev = new cirrdevicemacosx(params);

#ifdef _irr_compile_with_windows_ce_device_

  if (params.devicetype == eidt_wince || (!dev && params.devicetype == eidt_best))

   dev = new cirrdevicewince(params);

#ifdef _irr_compile_with_x11_device_

  if (params.devicetype == eidt_x11 || (!dev && params.devicetype == eidt_best))

   dev = new cirrdevicelinux(params);

#ifdef _irr_compile_with_sdl_device_

  if (params.devicetype == eidt_sdl || (!dev && params.devicetype == eidt_best))

  dev = new cirrdevicesdl(params);

#ifdef _irr_compile_with_console_device_

  if (params.devicetype == eidt_console || (!dev && params.devicetype == eidt_best))

  dev = new cirrdeviceconsole(params);

根據宏定義決定了平台相關系,進而建立出相應的平台。。。。。

請大家注意上面代碼中的params參數,他就是一個sirrlichtcreationparameters結構體,這個參數決定了建立圖形裝置的資訊。我們以win32為例,來繼續探究irr是如何實作平台、圖形api無關的。

cirrdevicewin32(const sirrlichtcreationparameters& params);

這是cirrdevicewin32它的構造函數,進而可知,params決定了一切,而params除了包含使用者指定的api資訊以外,并未有平台相關的資訊,是以,平台建立是無關的,而params決定了圖形api的選擇,當然,圖形api的選擇也可以通過類似的方案來實作,比如:在使用者建立裝置(調用createdevice)前,可以先測試是否支援d3d,如果不是再選擇opegnl。。。。

扯遠了,繼續說一下是怎麼建立的。。

下面我們進入他的構造函數的實作

構造函數将params傳給了他的父類。。。。,而它自已實作了windows相關的建立工作,如視窗類注冊,建立等。。。

params在父類中由creationparams;//儲存(如果忘了,請看貼子開頭的地方)。。。

構造函數還調用了另一個函數(當然不止一個,我隻是說,這是一個與creationparams相關的函數)

好了,就是它:createdriver();這個函數實作的代碼大緻如下

void cirrdevicewin32::createdriver()

switch(creationparams.drivertype)

case video::edt_direct3d8:

  #ifdef _irr_compile_with_direct3d_8_

  videodriver = video::createdirectx8driver

  break;

case video::edt_direct3d9:

  #ifdef _irr_compile_with_direct3d_9_

  videodriver = video::createdirectx9driver

case video::edt_opengl:

  #ifdef _irr_compile_with_opengl_

  videodriver = video::createopengldriver(creationparams, filesystem, this);

case video::edt_software:

  #ifdef _irr_compile_with_software_

  videodriver = video::createsoftwaredriver(creationparams.windowsize, 

case video::edt_burningsvideo:

  #ifdef _irr_compile_with_burningsvideo_

  videodriver = video::createsoftwaredriver2

case video::edt_null:

  // create null driver

  videodriver = video::createnulldriver

一切都明了了……

這裡并沒有作詳細的研究,隻是一個簡單的介紹,算是一個導讀吧。大家根據這個思路去讀源碼,相信很快就能研究明白了~~~

簡介:09年入行,喜歡遊戲和程式設計,對3d遊戲和引擎尤其感興趣。 

版權聲明:本文版權歸作者和部落格園共有,歡迎轉載。轉載必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

轉載:http://www.cnblogs.com/geniusalex/archive/2010/04/26/1940509.html

繼續閱讀