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就可以了。
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;    
}    



发布了3 篇原创文章 · 获赞 1 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章