將 Ogre3D 嵌入 Qt 框架 解決方案
將 Ogre3D 嵌入 Qt 框架 解決方案是本文要講述的內(nèi)容,可能不會有太多的內(nèi)容去講解,大都是大媽實現(xiàn)的,請看內(nèi)容。
OGRE3D 是一個被廣泛使用的開源三維圖形渲染庫,成功地被應(yīng)用于諸多三維仿真領(lǐng)域,其中包括網(wǎng)絡(luò)游戲和一些商業(yè)的三維仿真項目。
按照經(jīng)典的Qt程序結(jié)構(gòu),應(yīng)該有一個從QMainWindow繼承而來的MainWindow,讓它做為主窗口,然后子類化一個QWidget,它做為主窗口的"中心掛件",能過封裝Ogre的部分功能,實現(xiàn)用Ogre對該窗體的繪制。首先,如何把Ogre這個引擎發(fā)動,不斷驅(qū)動其進(jìn)行工作。
Qt也需要告訴Ogre如何把渲染的內(nèi)容畫到指定的窗口中去,以及用哪種方式更新窗口中的內(nèi)容。當(dāng)鍵盤或鼠標(biāo)消息來的時候,如何通知Ogre進(jìn)行響應(yīng)。從Ogre這邊來看,就是如何把Ogre的功能,分布到Qt的各個部分。而且與一般的ogre程序不同,不是進(jìn)入到連續(xù)的循環(huán)中(一般的ogre程序中,通過執(zhí)行mRoot->startRendering();語句進(jìn)入一個不停渲染循環(huán),通過預(yù)先安插好的幀偵聽器來對消息進(jìn)行響應(yīng),對程序邏輯進(jìn)行處理)而可以是“必要時”對窗口進(jìn)行更新。而且與一般ogre程序不同,由于Qt自身可以檢測輸入設(shè)備消息,因此,OIS不再需要。
把Ogre中的內(nèi)容嵌入到Qt,從形式來看可以許多種,也就是說可以把相關(guān)Ogre的部分拆成不同部分,按照作者的需要封裝在Qt中的不同部分。比如,Ogre中描述抽象的“引擎”概念的部分(Root等),因為我們想一但應(yīng)用程序啟動,就應(yīng)該讓Ogre引擎啟動了,那么這些部分可以用QApplication封裝,而且RenderWindow,與Qt中的QWidget概念上是關(guān)聯(lián)的,所以就用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()//創(chuàng)建Ogre使用的內(nèi)容,場景內(nèi)容;
- void update();//通過它,手動更新場景內(nèi)容
- void setupResources();//
- void createScene();
- void createLight();
- void resizeEvent(QResizeEvent* evt);//窗口可能縮放
- void timerEvent(QTimerEvent* evt);//可以設(shè)一時鐘來更新窗口
- void paintEvent(QPaintEvent* evt);//呵,當(dāng)然得處理了
- //消息響應(yīng)
- void keyPressEvent(QKeyEvent* evt);
- void keyReleaseEvent(QKeyEvent* evt);
- void mousePressEvent(QMouseEvent* evt);
- void mouseReleaseEvent(QMouseEvent* evt);
- void mouseMoveEvent(QMouseEvent* evt);
- void wheelEvent(QWheelEvent* evt);
- //有關(guān)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文件中的內(nèi)容(部分)
- 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,當(dāng)然必須得自己手工建窗口了,把窗口句柄扒出來....
- 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()
- {
- //手工更新場景內(nèi)容,而不是進(jìn)入到連續(xù)的循環(huán)中
- 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;
- }
小結(jié):將 Ogre3D 嵌入 Qt 框架 解決方案內(nèi)容介紹完了,我感覺這個實例真的很好。那希望本篇對你再學(xué)習(xí)中有所幫助。