I'm experimenting the integration of Ogre within a QWidget.
A fairly simple task in view of the many threads one can find here and in other forums.
However, I have tried many of the advices I have found and still my QOgreWidget shows, after 2 days of digging in the forums, nothing else than a black background.
Technically, I'm trying to integrate Ogre 1.7.4 with Qt 4.8.0 compiling with Visual C++ 2010 Express on a Windows 7 64 bits.
I have no issue with compilation. At execution, the QWidget remains black.
As shown in the attached code extract, the viewport's got a red background which I can see subtly perceive when I rapidely resize back and forth the window.
It acts as if, immediately after Ogre::Root::update() had the chance to draw, Qt was redrawing the widget in black (or was wrongly swapping the buffers).
And of course the simple basic cube is not displayed

I have also added in the code extracts comments describing different behaviours occuring when some lines of code are uncommented.
Unless someone finds something wrong or missing in the code, I suspect an issue due to the version of Qt (4.8.0).
Anybody's got an idea ? Thx

QOWidget.h
Code: Select all
#ifndef QOWIDGET_H
#define QOWIDGET_H
#include <QtGui/QWidget>
#include <QtGui/QShowEvent>
#include <QtGui/QMoveEvent>
#include <QtGui/QResizeEvent>
#include <QtGui/QPaintEvent>
#include <Ogre.h>
class QOWidget : public QWidget
{
// --- Constructors & Destructor ---
public:
QOWidget(QWidget* parent = 0);
~QOWidget();
// --- Getters & Setters ---
public:
Ogre::RenderWindow* GetOgreRenderWindow() { return m_pOgreRenderWindow; }
Ogre::Viewport* GetOgreViewport() { return m_pOgreViewport; }
Ogre::Camera* GetOgreCamera() { return m_pOgreCamera; }
// --- Virtual Methods Implementation ---
protected:
virtual void showEvent(QShowEvent* event);
virtual void moveEvent(QMoveEvent* event);
virtual void resizeEvent(QResizeEvent* event);
virtual void paintEvent(QPaintEvent* event);
virtual QPaintEngine* paintEngine();
// --- Private Operators ---
private:
void initOgreSystem();
void createRenderWindow();
void createViewport();
void createCamera();
void createDefaultLight();
void loadMeshFile();
void loadResources();
private:
Ogre::Root* m_pOgreRoot;
Ogre::SceneManager* m_pOgreSceneManager;
Ogre::RenderWindow* m_pOgreRenderWindow;
Ogre::Viewport* m_pOgreViewport;
Ogre::Camera* m_pOgreCamera;
};
#endif QOWIDGET_H
Code: Select all
#include <QtCore/QDebug>
#include "QOWidget.h"
QOWidget::QOWidget(QWidget *parent)
: QWidget(parent)
{
m_pOgreRoot = 0;
m_pOgreSceneManager = 0;
m_pOgreRenderWindow = 0;
m_pOgreViewport = 0;
m_pOgreCamera = 0;
// Here I have tried many combination of attribute settings
setAttribute(Qt::WA_OpaquePaintEvent);
setAttribute(Qt::WA_PaintOnScreen);
//setAttribute(Qt::WA_NoSystemBackground);
//setAutoFillBackground(false);
}
QOWidget::~QOWidget()
{
}
void QOWidget::initOgreSystem()
{
if (m_pOgreRoot)
return;
// Create and store the root node
m_pOgreRoot = new Ogre::Root();
// Initialize the render system
//Ogre::RenderSystem* pRenderer = m_pOgreRoot->getRenderSystemByName("Direct3D9 Rendering Subsystem");
Ogre::RenderSystem* pRenderer = m_pOgreRoot->getRenderSystemByName("OpenGL Rendering Subsystem");
m_pOgreRoot->setRenderSystem(pRenderer);
// Initialize the Ogre system without creating a window
// which is delegated to Qt
m_pOgreRoot->initialise(false);
// Create the Scene Manager object
m_pOgreSceneManager = m_pOgreRoot->createSceneManager(Ogre::ST_GENERIC);
// Load resources based on config files
loadResources();
createRenderWindow();
createCamera();
createViewport();
createDefaultLight();
// Trying to push the init of Root later in the process
// but it does not solve the issue
//m_pOgreRoot->initialise(false);
loadMeshFile();
}
void QOWidget::loadResources()
{
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;
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
archName, typeName, secName);
}
}
}
void QOWidget::loadMeshFile()
{
Ogre::Entity* pEntity = m_pOgreSceneManager->createEntity("Mesh", "cube.mesh");
Ogre::SceneNode* pNode = m_pOgreSceneManager->getRootSceneNode()->createChildSceneNode();
pNode->attachObject(pEntity);
}
/*
* Virtual implementation
*/
void QOWidget::showEvent(QShowEvent* event)
{
if (!m_pOgreRenderWindow)
{
initOgreSystem();
}
QWidget::showEvent(event);
}
void QOWidget::moveEvent(QMoveEvent* event)
{
QWidget::moveEvent(event);
if (event->isAccepted() && m_pOgreRenderWindow)
{
m_pOgreRenderWindow->windowMovedOrResized();
update();
}
}
void QOWidget::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
if (event->isAccepted())
{
const QSize& newSize = event->size();
if (m_pOgreCamera)
{
Ogre::Real aspectRatio = Ogre::Real(newSize.width()) / Ogre::Real(newSize.height());
m_pOgreCamera->setAspectRatio(aspectRatio);
}
if (m_pOgreRenderWindow)
{
m_pOgreRenderWindow->resize(newSize.width(), newSize.height());
m_pOgreRenderWindow->windowMovedOrResized();
}
}
}
void QOWidget::paintEvent(QPaintEvent* event)
{
m_pOgreRoot->_fireFrameStarted();
m_pOgreRenderWindow->update();
m_pOgreRoot->_fireFrameEnded();
event->accept();
}
QPaintEngine* QOWidget::paintEngine()
{
return 0;
//return QWidget::paintEngine();
}
/*
* Private Operators
*/
void QOWidget::createRenderWindow()
{
if (!m_pOgreRenderWindow)
{
Ogre::NameValuePairList windowParameters;
size_t widgetHandle;
widgetHandle = (size_t)((HWND)winId());
windowParameters["externalWindowHandle"] = Ogre::StringConverter::toString(widgetHandle);
// When the window handle is assigned to the parent parameter instead of the external one,
// a quite big RED square is drawn on the widget area but starting at position (800,410) and
// still no scene object (cube)
//windowParameters["parentWindowHandle"] = Ogre::StringConverter::toString(widgetHandle);
m_pOgreRenderWindow = m_pOgreRoot->createRenderWindow("Viewer",
width(), height(), false, &windowParameters);
// Have tried to NOT pass the window handle : a separate window is well created,
// shows the red background of the viewport, resizes in sync when I resize the
// QOWidget window but the scene (the cube) is not drawn.
//m_pOgreRenderWindow = QOgreApplication::GetOgreRoot()->createRenderWindow("Viewer",
// width(), height(), false);
}
}
void QOWidget::createViewport()
{
if (!m_pOgreViewport)
{
// Create the viewport and set the background color to RED
// so that it is clearly visible (in vain ... :-/
m_pOgreViewport = m_pOgreRenderWindow->addViewport(m_pOgreCamera);
m_pOgreViewport->setBackgroundColour(Ogre::ColourValue(1.0f, 0.0f, 0.0f));
// Have tried this as well
//m_pOgreViewport->setAutoUpdated(true);
}
}
void QOWidget::createCamera()
{
if (!m_pOgreCamera)
{
// Create and adapt the aspect ratio
m_pOgreCamera = m_pOgreSceneManager->createCamera("myCamera");
m_pOgreCamera->setAspectRatio(Ogre::Real(width()) / Ogre::Real(height()));
// Set the default location and orientation
m_pOgreCamera->setPosition(Ogre::Vector3(0.0f, 10.0f, 50.0f));
m_pOgreCamera->lookAt(Ogre::Vector3(0.0f, 0.0f, 0.0f));
}
}
void QOWidget::createDefaultLight()
{
m_pOgreSceneManager->setAmbientLight(Ogre::ColourValue(1.0f, 1.0f, 1.0f));
}
Code: Select all
#include <QtGui/QApplication>
#include "QOWidget.h"
/*
* MAIN ENTRY POINT
*/
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QOWidget window;
window.setWindowTitle(QObject::tr("Ogre within Qt"));
window.resize(300, 300);
window.show();
return app.exec();
}