Ogre3D嵌入Qt框架

摘要:
首先,如何把Ogre这个引擎发动,不断驱动其进行工作。当键盘或鼠标消息来的时候,如何通知Ogre进行响应。而且与一般ogre程序不同,由于Qt自身可以检测输入设备消息,因此,OIS不再需要。把Ogre中的内容嵌入到Qt,从形式来看可以许多种,也就是说可以把相关Ogre的部分拆成不同部分,按照作者的需要封装在Qt中的不同部分。出于简单的原因,我把Ogre都封装从QWidget继承而来的OgreView中了。很显然,主要考虑OgreView就可以了。
按照经典的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. classOgreView:publicQWidget
  2. {
  3. Q_OBJECT
  4. public:
  5. OgreView(QWidget*parent);
  6. ~OgreView();
  7. //QSizeminimumSizeHint()const;
  8. //QSizesizeHint()const;
  9. protected:
  10. voidsetupView()//创建Ogre使用的内容,场景内容;
  11. voidupdate();//通过它,手动更新场景内容
  12. voidsetupResources();//
  13. voidcreateScene();
  14. voidcreateLight();
  15. voidresizeEvent(QResizeEvent*evt);//窗口可能缩放
  16. voidtimerEvent(QTimerEvent*evt);//可以设一时钟来更新窗口
  17. voidpaintEvent(QPaintEvent*evt);//呵,当然得处理了
  18. //消息响应
  19. voidkeyPressEvent(QKeyEvent*evt);
  20. voidkeyReleaseEvent(QKeyEvent*evt);
  21. voidmousePressEvent(QMouseEvent*evt);
  22. voidmouseReleaseEvent(QMouseEvent*evt);
  23. voidmouseMoveEvent(QMouseEvent*evt);
  24. voidwheelEvent(QWheelEvent*evt);
  25. //有关Ogre
  26. Ogre::RenderWindow*mRenderWindow;
  27. Ogre::SceneManager*mSceneMgr;
  28. Ogre::Camera*mCamera;
  29. Ogre::Viewport*mVp;
  30. Ogre::Root*mRoot;
  31. Ogre::Light*mainLight;
  32. Ogre::Entity*mainEnt;
  33. Ogre::SceneNode*mainNode;
  34. //一些控制变量,没有完全列出
  35. Ogre::Vector3mDirection;
  36. Ogre::RealmRotate;
  37. };
  38. //cpp文件中的内容(部分)
  39. OgreView::OgreView(QWidget*parent) : QWidget(parent,Qt::WFlags(Qt::MSWindowsOwnDC))
  40. {
  41. mRenderWindow=NULL;
  42. mSceneMgr=NULL;
  43. mVp=NULL;
  44. mainEnt=NULL;
  45. mainNode=NULL;
  46. //....还有一些控制变量的初始化
  47. setupResources();
  48. }

  49. OgreView::~OgreView()
  50. {
  51. //destroyViewportandRenderWindow
  52. if(mVp)
  53. {
  54. mRenderWindow->removeViewport(mVp->getZOrder());
  55. mVp=0;
  56. }
  57. Ogre::Root::getSingleton().detachRenderTarget(mRenderWindow);
  58. mRenderWindow=0;
  59. if(mRoot!=NULL){
  60. deletemRoot;
  61. mRoot=0;
  62. }
  63. }


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

  97. voidOgreView::createLight()
  98. {
  99. mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5,0.5,0.5));
  100. mainLight=mSceneMgr->createLight("MainLight");
  101. mainLight->setPosition(20,80,50);
  102. }

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

  128. voidOgreView::paintEvent(QPaintEvent*evt)
  129. {
  130. Q_UNUSED(evt);
  131. if(mRenderWindow==NULL)
  132. setupView();
  133. update();
  134. }

  135. voidOgreView::timerEvent(QTimerEvent*evt)
  136. {
  137. Q_UNUSED(evt);
  138. update();
  139. }

  140. voidOgreView::update()
  141. {
  142. //手工更新场景内容,而不是进入到连续的循环中
  143. if(mRenderWindow!=NULL){
  144. mRoot->_fireFrameStarted();
  145. mRenderWindow->update();
  146. mCamera->moveRelative(mDirection);
  147. mCamera->yaw(Ogre::Radian(angleX));
  148. mCamera->pitch(Ogre::Radian(angleY));
  149. mRoot->_fireFrameEnded();
  150. }
  151. }


  152. voidOgreView::resizeEvent(QResizeEvent*evt)
  153. {
  154. Q_UNUSED(evt);
  155. if(mRenderWindow!=NULL){
  156. mRenderWindow->windowMovedOrResized();
  157. mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth())/Ogre::Real(mVp->getActualHeight()));
  158. }
  159. }

  160. voidOgreView::keyPressEvent(QKeyEvent*evt)
  161. {
  162. if(mainEnt!=NULL&&mainNode!=NULL){
  163. switch(evt->key()){
  164. caseQt::Key_W:
  165. caseQt::Key_Up:
  166. rotX=-0.1;
  167. mainNode->pitch(Ogre::Radian(rotX));
  168. break;
  169. caseQt::Key_S:
  170. caseQt::Key_Down:
  171. rotX=0.1;
  172. mainNode->pitch(Ogre::Radian(rotX));
  173. break;
  174. caseQt::Key_A:
  175. caseQt::Key_Left:
  176. rotY=-0.1;
  177. mainNode->yaw(Ogre::Radian(rotY));
  178. break;
  179. caseQt::Key_D:
  180. caseQt::Key_Right:
  181. rotY=0.1;
  182. mainNode->yaw(Ogre::Radian(rotY));
  183. break;
  184. }
  185. }
  186. }


  187. voidOgreView::mousePressEvent(QMouseEvent*evt)
  188. {
  189. if(evt->button()==Qt::LeftButton)
  190. mouseLeftPressed=true;
  191. if(evt->button()==Qt::RightButton){
  192. mouseRightPressed=true;
  193. mousePos=Ogre::Vector2(evt->x(),evt->y());
  194. }
  195. if(evt->button()==Qt::MidButton)
  196. mouseMiddleBtn=true;
  197. }


  198. voidOgreView::wheelEvent(QWheelEvent*evt)
  199. {
  200. mDirection.z=-evt->delta()/12;
  201. update();
  202. mDirection.z=0;
  203. }

免责声明:文章转载自《Ogre3D嵌入Qt框架》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇js 实现数组数字奇偶归类LOG EXPLORER FOR SQL SERVER 使用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

MOGRE学习笔记(1)

       由于工作需要,花费了一段时间研究OGRE,但是研究的目的是要在vs2010平台下用c#进行MOGRE的开发,不得已才转到MGRE,步骤是首选熟悉MOGRE的一些基础知识,做到在winform下能用MOGRE单独开发项目,最终的目的不仅限于此,而是构建一个MOGRE和physx结合的一个开发平台,以便在此基础上能够运用vs和.net快速的开发项...

Ogre内部渲染流程分析系列

come from:http://blog.csdn.net/weiqubo/article/details/6956005 要理解OGRE引擎,就要理解其中占很重要位置的 Renderable接口,今天先将一部分我分析的内容贴出来。 以下是 Ogre 的代码中的详细说明: Renderable是OGRE中所有可渲染对象的抽象接口 这个接口抽象出了在渲染...

Ogre 渲染队列(二)

转自:http://www.cnblogs.com/cppguru/archive/2009/11/25/1610626.html 简要说Ogre渲染主流程分三步使用渲染队列:清空、构造和访问,这个过程在每一帧的绘制过程中重复执行。 渲染队列的清空 Ogre在每一帧渲染前都会先清空渲染队列。熟悉Ogre渲染流程的很容易看到在SceneManager::_r...

OGRE GLRenderSystem

视口 glViewport(x, y, w, h); 清理 glClearColor(colour.r, colour.g, colour.b, colour.a); glClearDepth(depth); glEnable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glClear(flags); glD...

Ogre2.0 全新功能打造新3D引擎

不知当初是在那看到,说是Ogre2.0浪费了一个版本号,当时也没多想,以为没多大更新,一直到现在想做一个编辑器时,忽然想到要看下最新版本的更新,不看不知道,一看吓一跳,所以说,网络上的话少信,你不认识别人,别人张嘴就来,对别人也没损失,还可以装B下,靠. 从现在Ogre2.1的代码来看,大约总结下,更新包含去掉过多的设计模式,SoA的数据结构(用于SIMD...

Ogre骨骼动画

转自:http://blog.csdn.net/yanonsoftware/article/details/1281516 OGRE的基本动画控制是很简单的,设置一个动画的操作是这样: // Set idle animation mAnimationState = ent->getAnimationState( "Idle" ); mAnimatio...