.Introduction
Many people discussed about how to integrate with Ogre3D engine and Qt libraries. Here are some implements,including 3rd add-on named QtOgreFramework at Ogre3D official site, a framework named QtOgre on Ogre Forums, and some articles.
- http://www.ogre3d.org/developers/addons
- http://www.ogre3d.org/forums/viewtopic.php?f=11&t=45709&hilit=qtogre
- http://www.ogre3d.org/tikiwiki/QtOgre
- http://lakin.weckers.net/code/ogre3d/
According these articles and add-on souce, I try to integrate Ogre3D in Qt application by rendering Ogre3D content on Qt QWidge.
.Environment
I use Ogre3D version 1.7.4 , Qt libraries version 4.8.1 ,and building source code on Visual studio C++ 2010.
- Ogre3D v1.7.4
- Qt Libraries v4.8.1
- Visual studio c++ 2010
.Implement
There are four steps to integrate Ogre3D in Qt.
- Create a Qt widget for Ogre3D, called OgreWidget
- Initialize Ogre3D
- Using Ogre3D to update OgreWidget
- Using OgreWidget
1.Create a Qt widget for Ogre3D, called OgreWidget
First of all, we should implement the qt widget for rendering content by Ogre3D. In this widget we should overwrite some event handler function like resizeEvent, paintEvent, The widget(OgreWidget) will be like this.
class OgreWidget : public QWidget
{
Q_OBJECT
public:
OgreWidget (QWidget* parent = 0);
~ OgreWidget ();
virtual void resizeEvent(QResizeEvent* evt);
virtual void timerEvent(QTimerEvent* evt);
virtual void paintEvent(QPaintEvent* evt);
protected:
Ogre::Root *mOgreRoot;
Ogre::RenderWindow *mOgreWindow;
Ogre::Camera *mCamera;
Ogre::Viewport *mViewport;
Ogre::SceneManager *mSceneMgr;
Ogre::Light* mMainLight;
Ogre::SceneNode* mHeadNode;
Ogre::RenderSystem *mRenderSystem;
}
2. Initialize OgreWidget
The step initializing OgreWidget is almost the same with Ogre3D's demonstration , what we need is just to create root, setup render system, and load resources. However, there are something need to be concerned, we have to pass Qt widget handle to Ogre3D when creating Ogre3D render window.
.All of steps to Initialize OgreWidget
OgreWidget::OgreWidget(QWidget *parent)
:QWidget(parent){
createOgreRoot();
assert(setupOgreRenderSystem() == SUCCESS);
createOgreRenderWindow();
initOgreScene();
}
OgreWidget::~ OgreWidget (){
release();
}
.create ogre root object
void OgreWidget::createOgreRoot(){
mOgreRoot = new Ogre::Root("plugins.cfg", "ogre.cfg", "ogre.log");
}
.setup Ogre3D Render System
int OgreWidget::setupOgreRenderSystem(){
Ogre::RenderSystemList::const_iterator renderers;
renderers = mOgreRoot->getAvailableRenderers().begin();
while(renderers != mOgreRoot->getAvailableRenderers().end()){
Ogre::String rName = (*renderers)->getName();
if (rName == "Direct3D9 Rendering Subsystem"){
mOgreRoot->setRenderSystem(*renderers);
return SUCCESS;
}
renderers++;
}
return FAILED;
}
.create Ogre3D Render Window
There are three points in this step.
- Initialize Ogre3D without creating window
- Set OgreWiget WId to Ogre3D parameter externalWindowHandle for creating render window
- Set OgreWidget size to Ogre3D render window
void OgreWidget:: createOgreRenderWindow(){
Ogre::String winHandle;
Ogre::NameValuePairList params;
// 1. initialize without creating window
mOgreRoot->initialise(false);
//2. pass OgreWidget WId to parameter "externalWindowHandle" for creating renderwindow
winHandle = Ogre::StringConverter::toString((size_t)(HWND) winId());
params["externalWindowHandle"] = winHandle;
//3. set OgreWidget size to create render window
mOgreWindow = mOgreRoot->createRenderWindow( "QtOgreWidget_RenderWindow",
width(),
height(),
true,
¶ms );
}
.Initializng Ogre3D Scene
void OgreWidget::initOgreScene(){
Ogre::SceneType scene_manager_type = Ogre::ST_GENERIC;
mSceneMgr = mOgreRoot->createSceneManager( scene_manager_type );
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
mMainLight = mSceneMgr->createLight("MainLight");
mMainLight->setPosition(20,80,50);
mCamera = mSceneMgr->createCamera( "OgreWidgetCam" );
mCamera->setPosition(Ogre::Vector3(0,0,200));
mCamera->lookAt(Ogre::Vector3(0,0,-300));
mCamera->setNearClipDistance(1);
mViewport = mOgreWindow->addViewport( mCamera );
mViewport->setBackgroundColour(Ogre::ColourValue::Black);
mCamera->setAspectRatio(Ogre::Real(mViewport->getActualWidth()) / Ogre::Real(mViewport->getActualHeight()));
}
.Load Scene
Load an ogre head for this demo.
void OgreCoreRenderer::loadScene(){
Ogre::Entity* ogreHead = mSceneMgr->createEntity("head", "ogrehead.mesh");
mHeadNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
mHeadNode->attachObject(ogreHead);
mCamera->setAutoTracking(true, mHeadNode);
}
.Release memory
void OgreWidget::release(){
mOgreWindow->removeAllViewports();
mOgreRoot->detachRenderTarget(mOgreWindow);
mSceneMgr->clearScene();
mOgreRoot->destroySceneManager(mSceneMgr);
mOgreRoot->shutdown();
delete mOgreRoot;
}
3.Using Ogre3D to update OgreWidget
.Make OgreWidget better performances
Because we use Ogre3D to update(draw) window instead of Qt draw engine,we can do someting to make OgreWidget better performances.
.Disable auto fill background
We can control auto fill background by setAutoFillBackground function, but notice this..
Windows are always filled with QPalette::Window, unless the WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
.Set Attributes in OgreWidget
enum Qt::WidgetAttribute
- WA_PaintOnScreen
- WA_NoSystemBackground
- WA_OpaquePaintEvent
.Overwrite event handle function
- resizeEvent,
void OgreWidget::resizeEvent(QResizeEvent* evt){
if(!mOgreWindow||!mCamera){
return;
}
mOgreWindow->windowMovedOrResized();
mCamera->setAspectRatio(static_cast(width) / static_cast(height));
}
- timerEvent
- paintEvent
void OgreWidget::render(){
if(!mOgreRoot || !mOgreWindow){
return;
}
mOgreRoot->_fireFrameStarted();
mOgreWindow->update();
mOgreRoot->_fireFrameRenderingQueued();
mOgreRoot->_fireFrameEnded();
}
void OgreWidget::timerEvent(QTimerEvent* evt){
render();
}
void OgreWidget::paintEvent(QPaintEvent* evt){
render();
}
And don't forget to start timer.
OgreWidget::OgreWidget(QWidget *parent)
: QWidget(parent){
……
startTimer(10);
}
4. Using OgreWidget
int main(int argc, char *argv[]){
QApplication app(argc, argv);
int appResult;
OgreWidget *ogreSceneWidget=NULL;
ogreSceneWidget = new OgreWidget();
assert(ogreSceneWidget);
ogreSceneWidget->loadScene();
ogreSceneWidget->resize(800, 600);
ogreSceneWidget->setWindowTitle("Integrating Ogre3D 1.7.4 with Qt 4.8.1...");
ogreSceneWidget->show();
appResult = app.exec();
delete ogreSceneWidget;
return appResult;
}
.Result

Referecnes:
(1).Ogre3D is a popular rendering engine for multiple platforms.
http://www.ogre3d.org/
(2).Qt is a cross-platform application framework for developing graphical user interface(GUI). Beside the framework for GUI, QT also has extensive module for usual development such like network、multimedia、database…
http://qt.nokia.com/

沒有留言:
張貼留言