zoukankan      html  css  js  c++  java
  • 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函数做了些什么。
    用法示例:
    IrrlichtDevice *device =
      createDevice(driverType, core::dimension2d<u32>(640, 480),
      16, false, shadows);

    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);
    #endif
    #ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_
      if (params.DeviceType == EIDT_WINCE || (!dev && params.DeviceType == EIDT_BEST))
       dev = new CIrrDeviceWinCE(params);
    #endif
    #ifdef _IRR_COMPILE_WITH_X11_DEVICE_
      if (params.DeviceType == EIDT_X11 || (!dev && params.DeviceType == EIDT_BEST))
       dev = new CIrrDeviceLinux(params);
    #endif
    #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
      if (params.DeviceType == EIDT_SDL || (!dev && params.DeviceType == EIDT_BEST))
      dev = new CIrrDeviceSDL(params);
    #endif
    #ifdef _IRR_COMPILE_WITH_CONSOLE_DEVICE_
      if (params.DeviceType == EIDT_CONSOLE || (!dev && params.DeviceType == EIDT_BEST))
      dev = new CIrrDeviceConsole(params);
    #endif
    根据宏定义决定了平台相关系,从而创建出相应的平台。。。。。
    请大家注意上面代码中的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
      break;
    case video::EDT_OPENGL:
      #ifdef _IRR_COMPILE_WITH_OPENGL_
      VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this);
      break;
    case video::EDT_SOFTWARE:
      #ifdef _IRR_COMPILE_WITH_SOFTWARE_
      VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize,
      break;
    case video::EDT_BURNINGSVIDEO:
      #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
      VideoDriver = video::createSoftwareDriver2
      break;
    case video::EDT_NULL:
      // create null driver
      VideoDriver = video::createNullDriver
      break;
    }
    }
    一切都明了了……

    这里并没有作详细的研究,只是一个简单的介绍,算是一个导读吧。大家根据这个思路去读源码,相信很快就能研究明白了~~~

  • 相关阅读:
    C#带日期型默认值参数的函数
    mvc调用webapi上传图片或文件
    mysql增删改查存储过程
    sql 分页存储过程
    sql 出库存储过程
    Ternura
    留言板
    友链
    .net 死锁
    C#微信小程序搜索框
  • 原文地址:https://www.cnblogs.com/qilinzi/p/1940509.html
Copyright © 2011-2022 走看看