PDA

View Full Version : Integrating Ogre in QMdiArea !



erqsor
28th June 2010, 16:45
Hello,

I have a problem integrating Ogre in QtMdiArea (not with QWidget, it's work fine!).
I'm pretty sure that the problem is Qt, because I have checked all the Ogre Code, and it's working with a simple QWidget.
You can see I have derived OgreWidget from QMdiSubWindow instead of QWidget because it's working better than QWidget with QMdiArea. I will post the Visual Solution tomorrow if you want.

Here is my source code :

OgreApplication.h :

#ifndef OGREAPPLICATION_H
#define OGREAPPLICATION_H

#include <QObject>
#include <Ogre.h>

class OgreWidget;

class OgreApplication : public QObject
{
Q_OBJECT

public:
OgreApplication(QObject *parent = 0);
~OgreApplication();
void setupNLoadResources();
void createScene();

public slots:
void initialise();
OgreWidget * createOgreWidget();

private:
Ogre::Root *ogreRoot;
Ogre::SceneManager *ogreSceneManager;
static int nbRenderWindows;
};

#endif // OGREAPPLICATION_H


OgreApplication.cpp :

#include "OgreApplication.h"

#include "OgreWidget.h"

int OgreApplication::nbRenderWindows = 0;

OgreApplication::OgreApplication(QObject *parent)
: QObject(parent),
ogreRoot(0),
ogreSceneManager(0)
{

}

OgreApplication::~OgreApplication()
{
if(ogreRoot)
{
if(ogreSceneManager)
{
ogreRoot->destroySceneManager(ogreSceneManager);
}
}

delete ogreRoot;
}

void OgreApplication::initialise()
{
if (ogreRoot == NULL)
{
ogreRoot = new Ogre::Root();
}

// initialised ?
if (!ogreRoot->isInitialised())
{
Ogre::RenderSystem *renderSystem = ogreRoot->getRenderSystemByName("OpenGL Rendering Subsystem");
ogreRoot->setRenderSystem(renderSystem);
ogreRoot->initialise(false);
// Verify initialisation after initialise root
if (!ogreRoot->isInitialised())
{
return;
}
}
else
{
return;
}

ogreSceneManager = ogreRoot->createSceneManager(Ogre::ST_GENERIC);
}

OgreWidget * OgreApplication::createOgreWidget()
{
nbRenderWindows++;
OgreWidget * og = new OgreWidget();
og->initialise(nbRenderWindows, ogreRoot, ogreSceneManager);

if (nbRenderWindows == 1)
{
setupNLoadResources();
createScene();
}

return og;
}

void OgreApplication::setupNLoadResources()
{
// Load resource paths from config file
Ogre::ConfigFile cf;
cf.load("resources.cfg");

// Go through all sections & settings in the file
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;
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
// OS X does not set the working directory relative to the app,
// In order to make things portable on OS X we need to provide
// the loading with it's own bundle path location
Ogre::ResourceGroupManager::getSingleton().addReso urceLocation(
Ogre::String(macBundlePath() + "/" + archName), typeName, secName);
#else
Ogre::ResourceGroupManager::getSingleton().addReso urceLocation(
archName, typeName, secName);
#endif
}
}

// Initialise, parse scripts etc
Ogre::ResourceGroupManager::getSingleton().initial iseAllResourceGroups();
}

void OgreApplication::createScene()
{
ogreSceneManager->setAmbientLight(Ogre::ColourValue(1,1,1));

Ogre::Entity *robotEntity = ogreSceneManager->createEntity("Robot", "robot.mesh");
Ogre::SceneNode *robotNode = ogreSceneManager->getRootSceneNode()->createChildSceneNode("RobotNode");
robotNode->attachObject(robotEntity);
robotNode->yaw(Ogre::Radian(Ogre::Degree(-90)));
}


OgreWidget.h :

#ifndef OGREWIDGET_H
#define OGREWIDGET_H

#include <QtGui>
#include <Ogre.h>

class OgreWidget : public QMdiSubWindow, public Ogre::FrameListener
{
Q_OBJECT

public:
OgreWidget(QWidget *parent = 0);
~OgreWidget();
void initialise(int renderWindowId, Ogre::Root * root, Ogre::SceneManager * sceneManager);
virtual bool frameStarted(const Ogre::FrameEvent &evt);
virtual bool frameEnded(const Ogre::FrameEvent &evt);
void setCameraPosition(const Ogre::Vector3 &pos);

virtual void showEvent(QShowEvent *e);
virtual void paintEvent(QPaintEvent *e);
virtual void moveEvent(QMoveEvent *e);
virtual void resizeEvent(QResizeEvent *e);

virtual void keyPressEvent(QKeyEvent *e);
virtual void keyReleaseEvent(QKeyEvent *e);
QPaintEngine * paintEngine() const;

public slots:
void setBackgroundColor(QColor c);

signals:
void cameraPositionChanged(const Ogre::Vector3 &pos);

protected:

private:
bool mContinue;
Ogre::RenderWindow *ogreRenderWindow;
Ogre::Viewport *ogreViewport;
Ogre::Camera *ogreCamera;
Ogre::Root *ogreRoot;
Ogre::SceneManager *ogreSceneManager;

Ogre::Vector3 mDirection;
};

#endif OGREWIDGET_H


OgreWidget.cpp :

#include "OgreWidget.h"

OgreWidget::OgreWidget(QWidget *parent) :
QMdiSubWindow(parent),
ogreRenderWindow(0),
ogreViewport(0),
ogreCamera(0),
mContinue(true),
mDirection(Ogre::Vector3::ZERO)
{
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_NoBackground);
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_OpaquePaintEvent);
setMinimumSize(160,120);
setFocusPolicy(Qt::ClickFocus);
}

OgreWidget::~OgreWidget()
{
if (ogreRoot)
{
ogreRoot->detachRenderTarget(ogreRenderWindow);
}

if(ogreRenderWindow)
{
ogreRenderWindow->removeAllViewports();
}
}

void OgreWidget::initialise(int renderWindowId, Ogre::Root * root, Ogre::SceneManager * sceneManager)
{
ogreRoot = root;
ogreSceneManager = sceneManager;

Ogre::NameValuePairList viewConfig;
Ogre::String widgetHandle;
#ifdef Q_WS_WIN
widgetHandle = Ogre::StringConverter::toString((size_t)((HWND)win Id()));
#else
QWidget *q_parent = dynamic_cast <QWidget *> (parent());
QX11Info xInfo = x11Info();

widgetHandle = Ogre::StringConverter::toString ((unsigned long)xInfo.display()) +
":" + Ogre::StringConverter::toString ((unsigned int)xInfo.screen()) +
":" + Ogre::StringConverter::toString ((unsigned long)q_parent->winId());
#endif
Ogre::String renderWindowIdStr = Ogre::StringConverter::toString(renderWindowId);

viewConfig["externalWindowHandle"] = widgetHandle;
ogreRenderWindow = ogreRoot->createRenderWindow("Ogre rendering window"+renderWindowIdStr,
width(), height(), false, &viewConfig);

ogreCamera = ogreSceneManager->createCamera("myCamera"+renderWindowIdStr);
ogreCamera->setPosition(0, 50,150);
ogreCamera->lookAt(0,50,0);

ogreViewport = ogreRenderWindow->addViewport(ogreCamera);
ogreViewport->setBackgroundColour(Ogre::ColourValue(1,0,0));
ogreCamera->setAspectRatio(Ogre::Real(width()) / Ogre::Real(height()));

ogreRoot->addFrameListener(this);
}

bool OgreWidget::frameStarted(const Ogre::FrameEvent& evt)
{
return mContinue;
}

bool OgreWidget::frameEnded(const Ogre::FrameEvent& evt)
{
return mContinue;
}

void OgreWidget::setBackgroundColor(QColor c)
{
if(ogreViewport)
{
Ogre::ColourValue ogreColour;
ogreColour.setAsARGB(c.rgba());
ogreViewport->setBackgroundColour(ogreColour);
}
update();
}

void OgreWidget::showEvent(QShowEvent *e)
{
QMdiSubWindow::showEvent(e);
}

void OgreWidget::paintEvent(QPaintEvent *e)
{
QMdiSubWindow::paintEvent(e);

ogreRoot->_fireFrameStarted();
ogreRenderWindow->update();
ogreRoot->_fireFrameEnded();

e->accept();
}

void OgreWidget::moveEvent(QMoveEvent *e)
{
QMdiSubWindow::moveEvent(e);

if(e->isAccepted() && ogreRenderWindow)
{
ogreRenderWindow->windowMovedOrResized();
}
update();
}

void OgreWidget::resizeEvent(QResizeEvent *e)
{
QMdiSubWindow::resizeEvent(e);

if(e->isAccepted())
{
const QSize &newSize = e->size();
if(ogreRenderWindow)
{
ogreRenderWindow->resize(newSize.width(), newSize.height());
ogreRenderWindow->windowMovedOrResized();
}
if(ogreCamera)
{
Ogre::Real aspectRatio = Ogre::Real(newSize.width()) / Ogre::Real(newSize.height());
ogreCamera->setAspectRatio(aspectRatio);
}
}
update();
}

void OgreWidget::setCameraPosition(const Ogre::Vector3 &pos)
{
ogreCamera->setPosition(pos);
ogreCamera->lookAt(0,50,0);
update();
emit cameraPositionChanged(pos);
}

void OgreWidget::keyPressEvent(QKeyEvent *e)
{
switch(e->key())
{
case Qt::Key_Escape:
mContinue = false;
break;
case Qt::Key_Z:
mDirection.z = -1;
break;
case Qt::Key_S:
mDirection.z = 1;
break;
case Qt::Key_Q:
mDirection.x = -1;
break;
case Qt::Key_D:
mDirection.x = 1;
break;
case Qt::Key_PageUp:
mDirection.y = 1;
break;
case Qt::Key_PageDown:
mDirection.y = -1;
break;
}

const Ogre::Vector3 &actualCamPos = ogreCamera->getPosition();
setCameraPosition(actualCamPos + mDirection);

e->accept();
}

void OgreWidget::keyReleaseEvent(QKeyEvent *e)
{
switch(e->key())
{
case Qt::Key_Z:
mDirection.z = 0;
break;
case Qt::Key_S:
mDirection.z = 0;
break;
case Qt::Key_Q:
mDirection.x = 0;
break;
case Qt::Key_D:
mDirection.x = 0;
break;
case Qt::Key_PageUp:
mDirection.y = 0;
break;
case Qt::Key_PageDown:
mDirection.y = 0;
break;
}

e->accept();
}

QPaintEngine * OgreWidget::paintEngine() const
{
return 0;
}

Ginsengelf
29th June 2010, 07:00
Hi, if it works with a QWidget, why not use this and set it as the internal widget of the MdiSubWindow?

Ginsengelf

PS: if you post code, please use CODE tags to improve readability.

erqsor
29th June 2010, 10:56
That's what I did but it did not work. That's why I did derive OgreWidget from QMdiSubWidget.

main.cpp :


#include "OgreMainWindow.h"

#include <QtGui>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

OgreMainWindow w;
w.show();

return a.exec();
}


OgreMainWindow.h :


#ifndef OgreMainWindow_H
#define OgreMainWindow_H

#include <QtGui>

#include "OgreApplication.h"

class OgreMainWindow : public QMainWindow
{
Q_OBJECT

public:
OgreMainWindow(QWidget *parent = 0, Qt::WFlags flags = 0);
~OgreMainWindow();

public slots:
void createOgreWidget();

private:
QMdiArea * mdiArea;

OgreApplication * ogreApp;
};

#endif // OgreMainWindow_H


OgreMainWindow.cpp :


#include "OgreMainWindow.h"

OgreMainWindow::OgreMainWindow(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
mdiArea = new QMdiArea;
setCentralWidget(mdiArea);

ogreApp = new OgreApplication;

QMenu * menuOgre = this->menuBar()->addMenu("Ogre");

QAction * ogreInitAction = menuOgre->addAction("Initialise");
QObject::connect( ogreInitAction, SIGNAL(triggered()), ogreApp, SLOT(initialise()) );

QAction * ogreWidgetAction = menuOgre->addAction("Create Ogre Widget");
QObject::connect( ogreWidgetAction, SIGNAL(triggered()), this, SLOT(createOgreWidget()) );
}

OgreMainWindow::~OgreMainWindow()
{

}

void OgreMainWindow::createOgreWidget()
{
OgreWidget * og = ogreApp->createOgreWidget();
mdiArea->addSubWindow( (QMdiSubWindow*)og );
//og->show();
}


OgreApplication.h :


#ifndef OGREAPPLICATION_H
#define OGREAPPLICATION_H

#include <QObject>
#include <Ogre.h>

class CNahGui;
class OgreWidget;

class OgreApplication : public QObject
{
Q_OBJECT

public:
OgreApplication(QObject *parent = 0);
~OgreApplication();
void setupNLoadResources();
void createScene();

public slots:
void initialise();
OgreWidget * createOgreWidget();

private:
Ogre::Root *ogreRoot;
Ogre::SceneManager *ogreSceneManager;
static int nbRenderWindows;
};

#endif // OGREAPPLICATION_H


OgreApplication.cpp :


#include "OgreApplication.h"

#include "OgreWidget.h"

int OgreApplication::nbRenderWindows = 0;

OgreApplication::OgreApplication(QObject *parent)
: QObject(parent),
ogreRoot(0),
ogreSceneManager(0)
{
}

OgreApplication::~OgreApplication()
{
if(ogreRoot)
{
if(ogreSceneManager)
{
ogreRoot->destroySceneManager(ogreSceneManager);
}
}

delete ogreRoot;
}

void OgreApplication::initialise()
{
if (ogreRoot == 0)
{
ogreRoot = new Ogre::Root();
}

// initialised ?
if (!ogreRoot->isInitialised())
{
Ogre::RenderSystem *renderSystem = ogreRoot->getRenderSystemByName("OpenGL Rendering Subsystem");
ogreRoot->setRenderSystem(renderSystem);
ogreRoot->initialise(false);
// Verify initialisation after initialise root
if (!ogreRoot->isInitialised())
{
return;
}
}
else
{
return;
}

ogreSceneManager = ogreRoot->createSceneManager(Ogre::ST_GENERIC);

QMessageBox::information(0, "INFO", "OgreApplication initialised.");
}

OgreWidget * OgreApplication::createOgreWidget()
{
nbRenderWindows++;
OgreWidget * og = new OgreWidget();
og->initialise(nbRenderWindows, ogreRoot, ogreSceneManager);

if (nbRenderWindows == 1)
{
setupNLoadResources();
createScene();
}

QMessageBox::information(0, "INFO", "OgreWidget initialised.");

return og;
}

void OgreApplication::setupNLoadResources()
{
// Load resource paths from config file
Ogre::ConfigFile cf;
cf.load("resources.cfg");

// Go through all sections & settings in the file
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;
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
// OS X does not set the working directory relative to the app,
// In order to make things portable on OS X we need to provide
// the loading with it's own bundle path location
Ogre::ResourceGroupManager::getSingleton().addReso urceLocation(
Ogre::String(macBundlePath() + "/" + archName), typeName, secName);
#else
Ogre::ResourceGroupManager::getSingleton().addReso urceLocation(
archName, typeName, secName);
#endif
}
}

// Initialise, parse scripts etc
Ogre::ResourceGroupManager::getSingleton().initial iseAllResourceGroups();

QMessageBox::information(0, "INFO", "Ressources initialised.");
}

void OgreApplication::createScene()
{
ogreSceneManager->setAmbientLight(Ogre::ColourValue(1,1,1));

Ogre::Entity *robotEntity = ogreSceneManager->createEntity("Robot", "robot.mesh");
Ogre::SceneNode *robotNode = ogreSceneManager->getRootSceneNode()->createChildSceneNode("RobotNode");
robotNode->attachObject(robotEntity);
robotNode->yaw(Ogre::Radian(Ogre::Degree(-90)));

QMessageBox::information(0, "INFO", "Scene created.");
}

erqsor
29th June 2010, 10:57
and here the OgreWidget class (because the last message was too long) :

OgreWidget.h :


#ifndef OGREWIDGET_H
#define OGREWIDGET_H

#include <QtGui>
#include <Ogre.h>

class OgreWidget : public QMdiSubWindow, public Ogre::FrameListener
{
Q_OBJECT

public:
OgreWidget(QWidget *parent = 0);
~OgreWidget();
void initialise(int renderWindowId, Ogre::Root * root, Ogre::SceneManager * sceneManager);
virtual bool frameStarted(const Ogre::FrameEvent &evt);
virtual bool frameEnded(const Ogre::FrameEvent &evt);
void setCameraPosition(const Ogre::Vector3 &pos);

virtual void showEvent(QShowEvent *e);
virtual void paintEvent(QPaintEvent *e);
virtual void moveEvent(QMoveEvent *e);
virtual void resizeEvent(QResizeEvent *e);

virtual void keyPressEvent(QKeyEvent *e);
virtual void keyReleaseEvent(QKeyEvent *e);
QPaintEngine * paintEngine() const;

public slots:
void setBackgroundColor(QColor c);

signals:
void cameraPositionChanged(const Ogre::Vector3 &pos);

protected:

private:
bool mContinue;
Ogre::RenderWindow *ogreRenderWindow;
Ogre::Viewport *ogreViewport;
Ogre::Camera *ogreCamera;
Ogre::Root *ogreRoot;
Ogre::SceneManager *ogreSceneManager;

Ogre::Vector3 mDirection;
};

#endif OGREWIDGET_H


OgreWidget.cpp :


#include "OgreWidget.h"

OgreWidget::OgreWidget(QWidget *parent) :
QMdiSubWindow(parent),
ogreRenderWindow(0),
ogreViewport(0),
ogreCamera(0),
mContinue(true),
mDirection(Ogre::Vector3::ZERO)
{
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_NoBackground);
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_OpaquePaintEvent);
setMinimumSize(160,120);
setFocusPolicy(Qt::ClickFocus);
}

OgreWidget::~OgreWidget()
{
if (ogreRoot)
{
ogreRoot->detachRenderTarget(ogreRenderWindow);
}

if(ogreRenderWindow)
{
ogreRenderWindow->removeAllViewports();
}
}

void OgreWidget::initialise(int renderWindowId, Ogre::Root * root, Ogre::SceneManager * sceneManager)
{
ogreRoot = root;
ogreSceneManager = sceneManager;

Ogre::NameValuePairList viewConfig;
Ogre::String widgetHandle;
#ifdef Q_WS_WIN
widgetHandle = Ogre::StringConverter::toString((size_t)((HWND)win Id()));
#else
QWidget *q_parent = dynamic_cast <QWidget *> (parent());
QX11Info xInfo = x11Info();

widgetHandle = Ogre::StringConverter::toString ((unsigned long)xInfo.display()) +
":" + Ogre::StringConverter::toString ((unsigned int)xInfo.screen()) +
":" + Ogre::StringConverter::toString ((unsigned long)q_parent->winId());
#endif
Ogre::String renderWindowIdStr = Ogre::StringConverter::toString(renderWindowId);

viewConfig["externalWindowHandle"] = widgetHandle;
ogreRenderWindow = ogreRoot->createRenderWindow("Ogre rendering window"+renderWindowIdStr,
width(), height(), false, &viewConfig);

ogreCamera = ogreSceneManager->createCamera("myCamera"+renderWindowIdStr);
ogreCamera->setPosition(0, 50,150);
ogreCamera->lookAt(0,50,0);

ogreViewport = ogreRenderWindow->addViewport(ogreCamera);
ogreViewport->setBackgroundColour(Ogre::ColourValue(1,0,0));
ogreCamera->setAspectRatio(Ogre::Real(width()) / Ogre::Real(height()));

ogreRoot->addFrameListener(this);
}

bool OgreWidget::frameStarted(const Ogre::FrameEvent& evt)
{
//mCamera->translate(evt.timeSinceLastFrame);
return mContinue;
}

bool OgreWidget::frameEnded(const Ogre::FrameEvent& evt)
{
return mContinue;
}

void OgreWidget::setBackgroundColor(QColor c)
{
if(ogreViewport)
{
Ogre::ColourValue ogreColour;
ogreColour.setAsARGB(c.rgba());
ogreViewport->setBackgroundColour(ogreColour);
}
update();
}

void OgreWidget::showEvent(QShowEvent *e)
{
QMdiSubWindow::showEvent(e);
}

void OgreWidget::paintEvent(QPaintEvent *e)
{
QMdiSubWindow::paintEvent(e);

ogreRoot->_fireFrameStarted();
ogreRenderWindow->update();
ogreRoot->_fireFrameEnded();

e->accept();
}

void OgreWidget::moveEvent(QMoveEvent *e)
{
QMdiSubWindow::moveEvent(e);

if(e->isAccepted() && ogreRenderWindow)
{
ogreRenderWindow->windowMovedOrResized();
}
update();
}

void OgreWidget::resizeEvent(QResizeEvent *e)
{
QMdiSubWindow::resizeEvent(e);

if(e->isAccepted())
{
const QSize &newSize = e->size();
if(ogreRenderWindow)
{
ogreRenderWindow->resize(newSize.width(), newSize.height());
ogreRenderWindow->windowMovedOrResized();
}
if(ogreCamera)
{
Ogre::Real aspectRatio = Ogre::Real(newSize.width()) / Ogre::Real(newSize.height());
ogreCamera->setAspectRatio(aspectRatio);
}
}
update();
}

void OgreWidget::setCameraPosition(const Ogre::Vector3 &pos)
{
ogreCamera->setPosition(pos);
ogreCamera->lookAt(0,50,0);
update();
emit cameraPositionChanged(pos);
}

void OgreWidget::keyPressEvent(QKeyEvent *e)
{
switch(e->key())
{
case Qt::Key_Escape:
mContinue = false;
break;
case Qt::Key_Z:
mDirection.z = -1;
break;
case Qt::Key_S:
mDirection.z = 1;
break;
case Qt::Key_Q:
mDirection.x = -1;
break;
case Qt::Key_D:
mDirection.x = 1;
break;
case Qt::Key_PageUp:
mDirection.y = 1;
break;
case Qt::Key_PageDown:
mDirection.y = -1;
break;
}

const Ogre::Vector3 &actualCamPos = ogreCamera->getPosition();
setCameraPosition(actualCamPos + mDirection);

e->accept();
}

void OgreWidget::keyReleaseEvent(QKeyEvent *e)
{
switch(e->key())
{
case Qt::Key_Z:
mDirection.z = 0;
break;
case Qt::Key_S:
mDirection.z = 0;
break;
case Qt::Key_Q:
mDirection.x = 0;
break;
case Qt::Key_D:
mDirection.x = 0;
break;
case Qt::Key_PageUp:
mDirection.y = 0;
break;
case Qt::Key_PageDown:
mDirection.y = 0;
break;
}

e->accept();
}

QPaintEngine * OgreWidget::paintEngine() const
{
return 0;
//return QWidget::paintEngine();
}

erqsor
30th June 2010, 09:56
nobody wants to test?

I've given the entire source code, it's easy.

If you want see the difference between the integration in the QMdiArea or not, take this change :
- go to the fonction OgreMainWindow::createOgreWidget
- remove the line mdiArea->addSubWindow( (QMdiSubWindow*)og );
- add the line og->show();

Without integration, you should see the ogre robot on a red background.

erqsor
30th June 2010, 16:14
OK I made some tests and the problem is not Qt. But in the architecture of my ogre Application. I will continue to search that on a Ogre Forum.