zoukankan      html  css  js  c++  java
  • Ogre3D嵌入Qt框架

     按照经典的Qt程序结构,应该有一个从QMainWindow继承而来的MainWindow,让它做为主窗口,然后子类化一个QWidget,它做为主窗口的"中心挂件",能过封装Ogre的部分功能,实现用Ogre对该窗体的绘制。首先,如何把Ogre这个引擎发动,不断驱动其进行工作。Qt也需要告诉Ogre如何把渲染的内容画到指定的窗口中去,以及用哪种方式更新窗口中的内容。
             当键盘或鼠标消息来的时候,如何通知Ogre进行响应。从Ogre这边来看,就是如何把Ogre的功能,分布到Qt的各个部分。而且与一般的ogre程序不同,不是进入到连续的循环中(一般的ogre程序中,通过执行mRoot->startRendering();语句进入一个不停渲染循环,通过预先安插好的帧侦听器来对消息进行响应,对程序逻辑进行处理)而可以是“必要时”对窗口进行更新。而且与一般ogre程序不同,由于Qt自身可以检测输入设备消息,因此,OIS不再需要。
             把Ogre中的内容嵌入到Qt,从形式来看可以许多种,也就是说可以把相关Ogre的部分拆成不同部分,按照作者的需要封装在Qt中的不同部分。比如,Ogre中描述抽象的“引擎”概念的部分(Root等),因为我们想一但应用程序启动,就应该让Ogre引擎启动了,那么这些部分可以用QApplication封装,而且RenderWindow,与Qt中的QWidget概念上是关联的,所以就用QWidget来封装。出于简单的原因,我把Ogre都封装从QWidget继承而来的OgreView中了。很显然,主要考虑OgreView就可以了。

    1. class  OgreView  :  public  QWidget    
    2. {    
    3.     Q_OBJECT    
    4.         
    5. public:    
    6.     OgreView(QWidget*  parent  );    
    7.     ~OgreView();    
    8.     //QSize  minimumSizeHint()  const;    
    9.     //QSize  sizeHint()  const;    
    10. protected:    
    11.     void  setupView()//创建Ogre使用的内容,场景内容;    
    12.         void  update();//通过它,手动更新场景内容    
    13.     void  setupResources();//    
    14.     void  createScene();    
    15.     void  createLight();    
    16.     void  resizeEvent(QResizeEvent*  evt);//窗口可能缩放    
    17.     void  timerEvent(QTimerEvent*  evt);//可以设一时钟来更新窗口    
    18.     void  paintEvent(QPaintEvent*  evt);//呵,当然得处理了    
    19.     //消息响应    
    20.     void  keyPressEvent(QKeyEvent*  evt);    
    21.     void  keyReleaseEvent(QKeyEvent*  evt);    
    22.     void  mousePressEvent(QMouseEvent*  evt);    
    23.     void  mouseReleaseEvent(QMouseEvent*  evt);    
    24.     void  mouseMoveEvent(QMouseEvent*  evt);    
    25.     void  wheelEvent(QWheelEvent*  evt);    
    26.     
    27.     //有关Ogre    
    28.     Ogre::RenderWindow*  mRenderWindow;    
    29.     Ogre::SceneManager*  mSceneMgr;    
    30.     Ogre::Camera*  mCamera;    
    31.     Ogre::Viewport*  mVp;    
    32.     Ogre::Root*  mRoot;    
    33.     Ogre::Light*  mainLight;    
    34.     Ogre::Entity*  mainEnt;    
    35.     Ogre::SceneNode*  mainNode;    
    36.     //一些控制变量,没有完全列出    
    37.     Ogre::Vector3  mDirection;    
    38.     Ogre::Real  mRotate;    
    39.     
    40. };    
    41. //cpp文件中的内容(部分)    
    42. OgreView::OgreView(QWidget*  parent) : QWidget(parent,Qt::WFlags(Qt::MSWindowsOwnDC))    
    43. {    
    44.     mRenderWindow  =  NULL;    
    45.     mSceneMgr  =  NULL;    
    46.     mVp  =  NULL;    
    47.     mainEnt  =  NULL;    
    48.     mainNode  =  NULL;    
    49.     //....还有一些控制变量的初始化    
    50.     setupResources();    
    51. }    

    52. OgreView::~OgreView()    
    53. {    
    54.     //  destroy  Viewport  and  RenderWindow    
    55.     if(  mVp  )    
    56.     {    
    57.         mRenderWindow->removeViewport(mVp->getZOrder());    
    58.         mVp  =  0;    
    59.     }    
    60.     
    61.     Ogre::Root::getSingleton().detachRenderTarget(mRenderWindow);    
    62.     mRenderWindow  =  0;    
    63.     
    64.     if(mRoot  !=  NULL){    
    65.         delete  mRoot;    
    66.         mRoot  =  0;    
    67.     }    
    68. }    


    69. void  OgreView::setupResources()    
    70. {    
    71.     mRoot  =  new  Ogre::Root();    
    72.     Ogre::ConfigFile  cf;    
    73.     cf.load("resources.cfg");    
    74.     
    75.     Ogre::ConfigFile::SectionIterator  seci  =  cf.getSectionIterator();    
    76.     Ogre::String  secName,  typeName,  archName;    
    77.     while(seci.hasMoreElements())    
    78.     {    
    79.         secName  =  seci.peekNextKey();    
    80.         Ogre::ConfigFile::SettingsMultiMap*  settings  =  seci.getNext();    
    81.         Ogre::ConfigFile::SettingsMultiMap::iterator  i;    
    82.         for(i=settings->begin();  i!=settings->end();  ++i){    
    83.             typeName  =  i->first;    
    84.             archName  =  i->second;    
    85.             Ogre::ResourceGroupManager::getSingleton().
    86.   addResourceLocation(archName,  typeName,  secName);    
    87.         }    
    88.     }    
    89.     
    90.     if(!mRoot->restoreConfig())    
    91.     {    
    92.         mRoot->showConfigDialog();    
    93.     }    
    94.     mRoot->initialise(false);    
    95.     //以上都是从Ogre普通程序照搬    
    96. }    
    97. //没啥说的,代码比注释更明白    
    98. void  OgreView::createScene()    
    99. {    
    100.     mainEnt  =  mSceneMgr->createEntity("Head",  "ogrehead.mesh");    
    101.     mainNode  =  mSceneMgr->getRootSceneNode()->createChildSceneNode();    
    102.     mainNode->attachObject(mainEnt);    
    103. }    

    104. void  OgreView::createLight()    
    105. {    
    106.     
    107.         mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5,  0.5,  0.5));    
    108.         mainLight  =  mSceneMgr->createLight("MainLight");    
    109.         mainLight->setPosition(20,80,50);    
    110. }    

    111. void  OgreView::setupView()    
    112. {    
    113.         if(mRenderWindow)    
    114.                 return;    
    115.     //createRenderWindow,当然必须得自己手工建窗口了,把窗口句柄扒出来....    
    116.     
    117.     Ogre::NameValuePairList  params;    
    118.     params["externalWindowHandle"]  =  Ogre::StringConverter::toString((size_t)(HWND)winId());    
    119.     mRenderWindow  =  mRoot->createRenderWindow("View",  width(), height(),  false,  params);    
    120.     //SceneManager    
    121.     mSceneMgr  =  mRoot->createSceneManager(Ogre::ST_GENERIC);    
    122.     //setup  camera  &  viewport      
    123.     mCamera  =  mSceneMgr->createCamera("PlayerCam");    
    124.     mCamera->setPosition(Ogre::Vector3(0,0,80));    
    125.     mCamera->lookAt(Ogre::Vector3(0,0,-300));    
    126.     mCamera->setNearClipDistance(5);    
    127.     mVp  =  mRenderWindow->addViewport(mCamera);    
    128.     mVp->setBackgroundColour(Ogre::ColourValue(0,  0.0,  0.0,  1));    
    129.     mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth())  /  
    130.     Ogre::Real(mVp->getActualHeight()));    
    131.     //resource    
    132.     Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();    
    133.     createScene();    
    134.     createLight();    
    135.     startTimer(2);    
    136. }    

    137. void  OgreView::paintEvent(QPaintEvent  *evt)    
    138. {    
    139.     Q_UNUSED(evt);    
    140.         if(mRenderWindow  ==  NULL)    
    141.                 setupView();    
    142.     update();    
    143. }    

    144. void  OgreView::timerEvent(QTimerEvent*  evt)    
    145. {    
    146.     Q_UNUSED(evt);    
    147.     update();    
    148.     
    149. }    

    150. void  OgreView::update()    
    151. {    
    152.     //手工更新场景内容,而不是进入到连续的循环中    
    153.     if(mRenderWindow  !=  NULL){    
    154.         mRoot->_fireFrameStarted();    
    155.         mRenderWindow->update();    
    156.         
    157.         mCamera->moveRelative(mDirection);    
    158.         mCamera->yaw(Ogre::Radian(angleX));    
    159.         mCamera->pitch(Ogre::Radian(angleY));    
    160.         
    161.         mRoot->_fireFrameEnded();    
    162.     }    
    163. }    


    164. void  OgreView::resizeEvent(QResizeEvent  *evt)    
    165. {    
    166.     Q_UNUSED(evt);    
    167.     if  (mRenderWindow  !=  NULL){    
    168.         mRenderWindow->windowMovedOrResized();    
    169.         mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth())  /  Ogre::Real(mVp->getActualHeight()));    
    170.     }    
    171. }    

    172. void  OgreView::keyPressEvent(QKeyEvent*  evt)    
    173. {    
    174.     if(mainEnt  !=  NULL  &&  mainNode  !=  NULL){    
    175.         switch(evt->key()){    
    176.         case  Qt::Key_W:    
    177.         case  Qt::Key_Up:    
    178.             rotX  =  -0.1;    
    179.             mainNode->pitch(Ogre::Radian(rotX));    
    180.             break;    
    181.         case  Qt::Key_S:    
    182.         case  Qt::Key_Down:    
    183.             rotX  =  0.1;    
    184.             mainNode->pitch(Ogre::Radian(rotX));    
    185.             break;    
    186.         case  Qt::Key_A:    
    187.         case  Qt::Key_Left:    
    188.             rotY  =  -0.1;    
    189.             mainNode->yaw(Ogre::Radian(rotY));    
    190.             break;    
    191.         case  Qt::Key_D:    
    192.         case  Qt::Key_Right:    
    193.             rotY  =  0.1;    
    194.             mainNode->yaw(Ogre::Radian(rotY));    
    195.             break;    
    196.         }    
    197.     }    
    198. }    


    199. void  OgreView::mousePressEvent(QMouseEvent*  evt)    
    200. {    
    201.     if(evt->button()  ==  Qt::LeftButton)    
    202.         mouseLeftPressed  =  true;    
    203.     if(evt->button()  ==  Qt::RightButton){    
    204.         mouseRightPressed  =  true;    
    205.         mousePos  =  Ogre::Vector2(evt->x(),  evt->y());    
    206.     }    
    207.     if(evt->button()  ==  Qt::MidButton)    
    208.         mouseMiddleBtn  =  true;    
    209. }    


    210. void  OgreView::wheelEvent(QWheelEvent*  evt)    
    211. {    
    212.     mDirection.z  =  -evt->delta()/12;    
    213.     update();    
    214.     mDirection.z  =  0;    
    215. }    

  • 相关阅读:
    邮票面值设计(codevs 1047) 题解
    练习 : 生成器和模块
    练习 : 数据类型之字符串
    练习 : 函数基础
    练习 : 高阶函数
    练习 : 数据类型之列表
    练习 : 数据类型之元组
    练习 : 数据类型之字典
    练习 : 分支结构和循环结构
    练习 : 变量和运算符
  • 原文地址:https://www.cnblogs.com/ainima/p/6331164.html
Copyright © 2011-2022 走看看