Ogre3D嵌入Qt框架

来源:互联网 发布:阿肆预谋邂逅 知乎 编辑:程序博客网 时间:2024/06/04 18:46

  按照经典的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;    }    



原创粉丝点击