天天看点

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

继续阅读