按照经典的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就可以了。
class OgreView : public QWidget
{
 Q_OBJECT

public:
 OgreView(QWidget* parent );
 ~OgreView();
 //QSize minimumSizeHint() const;
 //QSize sizeHint() const;
protected:
  void setupView()//创建Ogre使用的内容,场景内容;
 void update();//通过它,手动更新场景内容
 void setupResources();//
 void createScene();
 void createLight();
 void resizeEvent(QResizeEvent* evt);//窗口可能缩放
 void timerEvent(QTimerEvent* evt);//可以设一时钟来更新窗口
 void paintEvent(QPaintEvent* evt);//呵,当然得处理了
        //消息响应
 void keyPressEvent(QKeyEvent* evt);
 void keyReleaseEvent(QKeyEvent* evt);
 void mousePressEvent(QMouseEvent* evt);
 void mouseReleaseEvent(QMouseEvent* evt);
 void mouseMoveEvent(QMouseEvent* evt);
 void wheelEvent(QWheelEvent* evt);

 //有关Ogre
 Ogre::RenderWindow* mRenderWindow;
 Ogre::SceneManager* mSceneMgr;
 Ogre::Camera* mCamera;
 Ogre::Viewport* mVp;
 Ogre::Root* mRoot;
 Ogre::Light* mainLight;
  Ogre::Entity* mainEnt;
 Ogre::SceneNode* mainNode;
 //一些控制变量,没有完全列出
 Ogre::Vector3 mDirection;
 Ogre::Real mRotate;
 
};
//cpp文件中的内容(部分)
OgreView::OgreView(QWidget* parent) : QWidget(parent,Qt::WFlags(Qt::MSWindowsOwnDC))
{
 mRenderWindow = NULL;
 mSceneMgr = NULL;
 mVp = NULL;
 mainEnt = NULL;
 mainNode = NULL;
 //....还有一些控制变量的初始化
 setupResources();
}

OgreView::~OgreView()
{
 // destroy Viewport and RenderWindow
 if( mVp )
 {
  mRenderWindow->removeViewport(mVp->getZOrder());
  mVp = 0;
 }
 
 Ogre::Root::getSingleton().detachRenderTarget(mRenderWindow);
 mRenderWindow = 0;
 
 if(mRoot != NULL){
  delete mRoot;
  mRoot = 0;
 }
}


void OgreView::setupResources()
{
 mRoot = new Ogre::Root();
 Ogre::ConfigFile cf;
 cf.load("resources.cfg");

 Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
 Ogre::String secName, typeName, archName;
 while(seci.hasMoreElements())
 {
  secName = seci.peekNextKey();
  Ogre::ConfigFile::SettingsMultiMap* settings = seci.getNext();
  Ogre::ConfigFile::SettingsMultiMap::iterator i;
  for(i=settings->begin(); i!=settings->end(); ++i){
   typeName = i->first;
   archName = i->second;
   Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
  }
 }

 if(!mRoot->restoreConfig())
  {
   mRoot->showConfigDialog();
  }
 mRoot->initialise(false);
      //以上都是从Ogre普通程序照搬
}
//没啥说的,代码比注释更明白
void OgreView::createScene()
{
  mainEnt = mSceneMgr->createEntity("Head", "ogrehead.mesh");
  mainNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
  mainNode->attachObject(mainEnt);
}

void OgreView::createLight()
{
 
    mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
    mainLight = mSceneMgr->createLight("MainLight");
    mainLight->setPosition(20,80,50);
}

void OgreView::setupView()
{
    if(mRenderWindow)
        return;
  //createRenderWindow,当然必须得自己手工建窗口了,把窗口句柄扒出来....
 
 Ogre::NameValuePairList params;
 params["externalWindowHandle"] = Ogre::StringConverter::toString((size_t)(HWND)winId());
 mRenderWindow = mRoot->createRenderWindow("View", width(), height(), false, &params);
 //SceneManager
  mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC);
  //setup camera & viewport 
  mCamera = mSceneMgr->createCamera("PlayerCam");
  mCamera->setPosition(Ogre::Vector3(0,0,80));
  mCamera->lookAt(Ogre::Vector3(0,0,-300));
  mCamera->setNearClipDistance(5);
  mVp = mRenderWindow->addViewport(mCamera);
  mVp->setBackgroundColour(Ogre::ColourValue(0, 0.0, 0.0, 1));
 mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth()) / Ogre::Real(mVp->getActualHeight()));
  //resource
 Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
   createScene();
   createLight();
   startTimer(2);
}

void OgreView::paintEvent(QPaintEvent *evt)
{
 Q_UNUSED(evt);
    if(mRenderWindow == NULL)
        setupView();
  update();
}

void OgreView::timerEvent(QTimerEvent* evt)
{
 Q_UNUSED(evt);
 update();
 
}

void OgreView::update()
{
 //手工更新场景内容,而不是进入到连续的循环中
        if(mRenderWindow != NULL){
  mRoot->_fireFrameStarted();
  mRenderWindow->update();

  mCamera->moveRelative(mDirection);
  mCamera->yaw(Ogre::Radian(angleX));
  mCamera->pitch(Ogre::Radian(angleY));

  mRoot->_fireFrameEnded();
 }
}


void OgreView::resizeEvent(QResizeEvent *evt)
{
 Q_UNUSED(evt);
 if (mRenderWindow != NULL){
  mRenderWindow->windowMovedOrResized();
  mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth()) / Ogre::Real(mVp->getActualHeight()));
 }
}

void OgreView::keyPressEvent(QKeyEvent* evt)
{
 if(mainEnt != NULL && mainNode != NULL){
  switch(evt->key()){
   case Qt::Key_W:
   case Qt::Key_Up:
    rotX = -0.1;
    mainNode->pitch(Ogre::Radian(rotX));
    break;
   case Qt::Key_S:
   case Qt::Key_Down:
    rotX = 0.1;
    mainNode->pitch(Ogre::Radian(rotX));
    break;
   case Qt::Key_A:
   case Qt::Key_Left:
    rotY = -0.1;
    mainNode->yaw(Ogre::Radian(rotY));
    break;
   case Qt::Key_D:
   case Qt::Key_Right:
    rotY = 0.1;
    mainNode->yaw(Ogre::Radian(rotY));
    break;
  }
 }
}


void OgreView::mousePressEvent(QMouseEvent* evt)
{
 if(evt->button() == Qt::LeftButton)
  mouseLeftPressed = true;
 if(evt->button() == Qt::RightButton){
  mouseRightPressed = true;
  mousePos = Ogre::Vector2(evt->x(), evt->y());
 }
 if(evt->button() == Qt::MidButton)
  mouseMiddleBtn = true;
}


void OgreView::wheelEvent(QWheelEvent* evt)
{
 mDirection.z = -evt->delta()/12;
 update();
 mDirection.z = 0;
}

posted on 2007-05-21 11:57 清源游民 阅读(7735) 评论(18)  编辑 收藏 引用 所属分类: OGREQt

FeedBack:
# re: Ogre3D嵌入Qt框架 之 小结
2007-08-06 10:41 | 阿来
来我们公司搞地图编辑器怎样?  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2007-08-06 10:41 | 阿来
有兴趣没?  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结[未登录]
2007-08-06 11:13 | 清源游民
@阿来
什么公司呀?用什么开发呢?  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2007-08-07 21:59 | 阿来
征途,做网络游戏的  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2007-08-07 21:59 | 阿来
c++
windows + vc  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2007-08-07 22:01 | 阿来
工具我想用qt来做,包括自动更新程序
现在的工具有用bcb做的,有的mfc,有的managed c++,有的c#  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2007-08-08 00:16 | 清源游民
呵呵,征途。两年前,还没毕业,想实习,面试过的,做了份题,面谈了一下,便over了。当时很菜,所以正常,当然现在也很菜。原来想过进游戏行的,不过各种原因没有进去。刚工作一年,觉得自己经验,能力还是有差距。所以还是想先练练内功,多打打怪,有点积累再跳吧。现在工作环境较松,有时间可以多学点东西,据说游戏公司都很忙吧.是不是啊?
qt,bcb,mfc,managed c++,c#,你的武器还挺多,佩服!  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2007-08-08 01:04 | 阿来
你来征途学得更快,忙是肯定的。想来的话把简历发我一份。
现在<巨人>终极封测了,你进来参与这个项目  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2007-08-08 09:55 | 清源游民
给个联系方式,有空的话可以先聊聊。MSN,QQ都可以。  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2007-08-08 13:22 | 阿来
lai3d#163 dot com

这个是msn  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2008-11-21 00:50 | codespy
我在用Ogre与Qt结合的时候,出现了名字冲突的错误。
qt-win-opensource-src-4.4.0\src\corelib\global\qglobal.h中
#ifndef QT_NAMESPACE /* user namespace */ // 这句该怎么用?
不知道你能否发给我一个简单的例子程序?我的email是info_resource¥sina.com
使用时,¥换成@。  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2009-03-12 11:49 | Wickedangel
能发一份完整的源代码给我吗?我的邮件是flydragon_hy@163.com.谢谢!  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2009-04-08 15:21 | hzyy
可以发一份原代码给我嘛?我也在试验如何把OGRE嵌入到Qt框架,做了一周都没有成功,楼主可以帮我一下嘛?

我的邮箱是:402142793@qq.com
  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2009-04-08 15:23 | hzyy
我正在试验把OGRE嵌入到QT,可惜做了一周时间,还没有成功,希望你能帮我一下,给我一个源代码。我的邮箱是:402142793·qq.com  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结[未登录]
2009-04-10 15:50 | DD
没有 keyReleaseEvent ()的实现咧?
我的是QT4.4.3
实现了KeyReleaseEvent()与keyPressEvent()
可是KeyReleaseEvent()不能触发。。楼主遇到这种问题么?  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2010-01-24 17:29 |
哥们。谢谢你提供的资料。。正在 学习中 万分感激啊  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2010-05-14 10:45 | xiya
可以发一份原代码给我嘛?我也在试验如何把OGRE嵌入到Qt框架,做了一周都没有成功,楼主可以帮我一下嘛? 我的邮箱是: bluelf77#163.com.感激不尽啊!  回复  更多评论
  
# re: Ogre3D嵌入Qt框架 之 小结
2014-01-15 20:01 | 耿肖
您好,最近在学习ogre,看到您这篇文章感觉写的很好很强大,想学习学习。能把完整的源码发一份吗1124670369@qq.com。谢谢了  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2014年1月>
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

留言簿(35)

随笔分类(78)

随笔档案(74)

文章档案(5)

搜索

  •  

最新评论

阅读排行榜

评论排行榜