将 Ogre3D 嵌入 Qt 框架 解决方案是本文要讲述的内容,可能不会有太多的内容去讲解,大都是大妈实现的,请看内容。
OGRE3D 是一个被广泛使用的开源三维图形渲染库,成功地被应用于诸多三维仿真领域,其中包括网络游戏和一些商业的三维仿真项目。
按照经典的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);
- }
#p#
- 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, ¶ms);
- //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;
- }
小结:将 Ogre3D 嵌入 Qt 框架 解决方案内容介绍完了,我感觉这个实例真的很好。那希望本篇对你再学习中有所帮助。