I find an strange behavior of ogre scene that it always stay at left-bottom corner of current viewport .

if I resize my window, the secene size is not updated.

And this is a FHD (1920*1080) monitor, without HiDPI.
ogreWindow code:
.h
Code: Select all
#ifndef QTOGREWINDOW_H
#define QTOGREWINDOW_H
/*
Qt headers
*/
#include <QtWidgets/QApplication>
#include <QtGui/QKeyEvent>
#include <QtGui/QWindow>
#include <QtCore/QTimer>
/*
Ogre3D header
*/
#include <Ogre.h>
namespace Ogre {
class OverlaySystem;
}
/*
Changed SdkCameraMan implementation to work with QKeyEvent, QMouseEvent, QWheelEvent
*/
#include <OgreCameraMan.h>
/*
With the headers included we now need to inherit from QWindow.
*/
class QTOgreWindow : public QWindow, public Ogre::FrameListener
{
/*
A QWindow still inherits from QObject and can have signals/slots; we need to add the appropriate
Q_OBJECT keyword so that Qt's intermediate compiler can do the necessary wireup between our class
and the rest of Qt.
*/
Q_OBJECT
public:
explicit QTOgreWindow(QWindow *parent = NULL);
~QTOgreWindow();
/*
We declare these methods virtual to allow for further inheritance.
*/
virtual void render(QPainter *painter);
virtual void render();
virtual void initialize();
virtual void loadScene();
virtual void createCube();
#if OGRE_VERSION >= ((2 << 16) | (0 << 8) | 0)
virtual void createCompositor();
#endif
void setAnimating(bool animating);
public slots:
virtual void renderLater();
virtual void renderNow();
/*
We use an event filter to be able to capture keyboard/mouse events. More on this later.
*/
virtual bool eventFilter(QObject *target, QEvent *event);
void takeSnapshot(Ogre::String& fileName);
signals:
/*
Event for clicking on an entity.
*/
void entitySelected(Ogre::Entity* entity);
void getStepNumber(int stepNumber);
void getTotalStepNumber(int stepNumber);
protected:
/// Locad "resources.cfg"
void _loadResources();
/*
The below methods are what is actually fired when they keys on the keyboard are hit.
Similar events are fired when the mouse is pressed or other events occur.
*/
virtual void keyPressEvent(QKeyEvent * ev);
virtual void keyReleaseEvent(QKeyEvent * ev);
virtual void mouseMoveEvent(QMouseEvent* e);
virtual void wheelEvent(QWheelEvent* e);
virtual void mousePressEvent(QMouseEvent* e);
virtual void mouseReleaseEvent(QMouseEvent* e);
virtual void exposeEvent(QExposeEvent *event);
virtual bool event(QEvent *event);
/*
FrameListener method
*/
virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);
/*
Write log messages to Ogre log
*/
void log(Ogre::String msg);
void log(QString msg);
/*
* create Axis
*/
void createAxis();
protected:
/*
Ogre3D pointers added here. Useful to have the pointers here for use by the window later.
*/
Ogre::Root* m_ogreRoot;
Ogre::RenderWindow* m_ogreWindow;
Ogre::SceneManager* m_ogreSceneMgr;
Ogre::Camera* m_ogreCamera;
Ogre::ColourValue m_ogreBackground;
Ogre::OverlaySystem* mOverlaySystem;
OgreBites::CameraMan* m_cameraMan;
Ogre::SceneNode* m_cameraNode;
Ogre::SceneNode* m_Axis;
QMouseEvent _lastMouseEvent;
bool m_update_pending;
bool m_animating;
private:
QTimer _qtime;
};
}
#endif // QTOGREWINDOW_H
Code: Select all
#include "QTOgreWindow.h"
#include "OgreManualObject.h"
#include "OgreMaterial.h"
#include <OgreAxisAlignedBox.h>
#include <OgreSceneNode.h>
#include <OgreViewport.h>
#include <Overlay/OgreOverlaySystem.h>
#include <QDir>
/*
Note that we pass any supplied QWindow parent to the base QWindow class. This is necessary should we
need to use our class within a container.
*/
QTOgreWindow::QTOgreWindow(QWindow *parent)
: QWindow(parent)
, m_update_pending(false)
, m_animating(false)
, m_ogreRoot(nullptr)
, m_ogreWindow(nullptr)
, m_ogreCamera(nullptr)
, m_cameraMan(nullptr)
, m_Axis(nullptr)
, m_cameraNode(nullptr)
, _lastMouseEvent(QEvent::Type::MouseButtonPress, QPointF(), Qt::MouseButton::LeftButton, Qt::MouseButtons(), Qt::KeyboardModifiers())
{
setAnimating(true);
installEventFilter(this);
m_ogreBackground = Ogre::ColourValue(0.0f, 0.5f, 1.0f);
}
/*
Upon destruction of the QWindow object we destroy the Ogre3D scene.
*/
QTOgreWindow::~QTOgreWindow()
{
if (m_cameraMan) { delete m_cameraMan; m_cameraMan = nullptr; }
delete m_ogreRoot;
}
/*
In case any drawing surface backing stores (QRasterWindow or QOpenGLWindow) of Qt are supplied to this
class in any way we inform Qt that they will be unused.
*/
void QTOgreWindow::render(QPainter *painter)
{
Q_UNUSED(painter);
}
/*
Our initialization function. Called by our renderNow() function once when the window is first exposed.
*/
void QTOgreWindow::initialize()
{
/*
As shown Ogre3D is initialized normally; just like in other documentation.
*/
#ifdef _MSC_VER
std::string dir = QDir::currentPath().toStdString();
Ogre::String pluginFile = Ogre::String("plugins" OGRE_BUILD_SUFFIX ".cfg");
m_ogreRoot = new Ogre::Root(pluginFile);
#else
m_ogreRoot = new Ogre::Root(Ogre::String("plugins.cfg"));
#endif
const Ogre::RenderSystemList& rsList = m_ogreRoot->getAvailableRenderers();
Ogre::RenderSystem* rs = rsList[0];
/*
This list setup the search order for used render system.
*/
Ogre::StringVector renderOrder;
#if defined(Q_OS_WIN)
renderOrder.push_back("Direct3D9");
renderOrder.push_back("Direct3D11");
#endif
renderOrder.push_back("OpenGL");
renderOrder.push_back("OpenGL 3+");
for (Ogre::StringVector::iterator iter = renderOrder.begin(); iter != renderOrder.end(); iter++)
{
for (Ogre::RenderSystemList::const_iterator it = rsList.begin(); it != rsList.end(); it++)
{
if ((*it)->getName().find(*iter) != Ogre::String::npos)
{
rs = *it;
break;
}
}
if (rs != NULL) break;
}
if (rs == NULL)
{
if (!m_ogreRoot->restoreConfig())
{
if (!m_ogreRoot->showConfigDialog())
OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
"Abort render system configuration",
"QTOgreWindow::initialize");
}
}
/*
Setting size and VSync on windows will solve a lot of problems
*/
QString dimensions = QString("%1 x %2").arg(this->width()).arg(this->height());
rs->setConfigOption("Video Mode", dimensions.toStdString());
rs->setConfigOption("Full Screen", "No");
rs->setConfigOption("VSync", "Yes");
rs->setConfigOption("FSAA", "8");
m_ogreRoot->setRenderSystem(rs);
m_ogreRoot->initialise(false);
// m_ogreRoot->initialise(true);
Ogre::NameValuePairList parameters;
/*
Flag within the parameters set so that Ogre3D initializes an OpenGL context on it's own.
*/
if (rs->getName().find("GL") <= rs->getName().size())
parameters["currentGLContext"] = Ogre::String("false");
/*
We need to supply the low level OS window handle to this QWindow so that Ogre3D knows where to draw
the scene. Below is a cross-platform method on how to do this.
If you set both options (externalWindowHandle and parentWindowHandle) this code will work with OpenGL
and DirectX.
*/
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
parameters["externalWindowHandle"] = Ogre::StringConverter::toString((size_t)(this->winId()));
parameters["parentWindowHandle"] = Ogre::StringConverter::toString((size_t)(this->winId()));
#else
parameters["externalWindowHandle"] = Ogre::StringConverter::toString((unsigned long)(this->winId()));
parameters["parentWindowHandle"] = Ogre::StringConverter::toString((unsigned long)(this->winId()));
#endif
#if defined(Q_OS_MAC)
parameters["macAPI"] = "cocoa";
parameters["macAPICocoaUseNSView"] = "true";
#endif
// enable antialiasing
parameters["FSAA"] = "8";
/*
Note below that we supply the creation function for the Ogre3D window the width and height
from the current QWindow object using the "this" pointer.
*/
m_ogreWindow = m_ogreRoot->createRenderWindow("QT Window",
this->width(),
this->height(),
false,
¶meters);
m_ogreWindow->setVisible(true);
/*
The rest of the code in the initialization function is standard Ogre3D scene code. Consult other
tutorials for specifics.
*/
#if OGRE_VERSION >= ((2 << 16) | (0 << 8) | 0)
const size_t numThreads = std::max<int>(1, Ogre::PlatformInformation::getNumLogicalCores());
Ogre::InstancingTheadedCullingMethod threadedCullingMethod = Ogre::INSTANCING_CULLING_SINGLETHREAD;
if (numThreads > 1)threadedCullingMethod = Ogre::INSTANCING_CULLING_THREADED;
m_ogreSceneMgr = m_ogreRoot->createSceneManager(Ogre::ST_GENERIC, numThreads, threadedCullingMethod);
#else
m_ogreSceneMgr = m_ogreRoot->createSceneManager(Ogre::ST_GENERIC);
#endif
_loadResources();
/////////////////////////
/// Camera
/////////////////////////
m_ogreCamera = m_ogreSceneMgr->createCamera("MainCamera");
// m_ogreCamera->setPosition(Ogre::Vector3(0.0f, 0.0f, 10.0f));
// m_ogreCamera->lookAt(Ogre::Vector3(0.0f, 0.0f, -300.0f));
m_cameraNode = m_ogreSceneMgr->getRootSceneNode()->createChildSceneNode();
m_cameraNode->attachObject(m_ogreCamera);
m_ogreCamera->setNearClipDistance(0.1f);
m_ogreCamera->setFarClipDistance(2000.0f);
m_ogreCamera->setAspectRatio(180);
m_cameraMan = new OgreBites::CameraMan(m_cameraNode);
m_cameraMan->setStyle(OgreBites::CameraStyle::CS_ORBIT);
m_cameraMan->setYawPitchDist(Ogre::Degree(-10), Ogre::Degree(0), 20);
m_cameraMan->setTopSpeed(50);
Ogre::Viewport* pViewport = m_ogreWindow->addViewport(m_ogreCamera);
pViewport->setBackgroundColour(m_ogreBackground);
m_ogreCamera->setAspectRatio((Ogre::Real)pViewport->getActualWidth() / (Ogre::Real)pViewport->getActualHeight());
m_ogreCamera->setAutoAspectRatio(true);
Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
createCube();
createAxis();
m_cameraMan->setTarget(m_Axis);
}
void QTOgreWindow::createAxis()
{
const size_t nVertices = 8;
const size_t vbufCount = 3*2*nVertices;
float vertices[vbufCount] = {
0.0,0.0,0.0, //0 position
10.0,0.0,0.0, //1 position
0.0,0.0,0.0, //2 position
0.0,10.0,0.0, //3 position
0.0,0.0,0.0, //4 position
0.0,0.0,10.0, //5 position
};
float normals[6][3] = {
{ 1, 0, 0},
{ 1, 0, 0},
{ 0, 1, 0},
{ 0, 1, 0},
{ 0, 0, 1},
{ 0, 0, 1}
};
float colors[6][3] = {
{ 1, 0, 0},
{ 1, 0, 0},
{ 0, 1, 0},
{ 0, 1, 0},
{ 0, 0, 1},
{ 0, 0, 1}
};
const int size = 6;
const Ogre::String mb("Axis");
Ogre::ManualObject* mob = m_ogreSceneMgr->createManualObject(mb);
mob->begin("NormalColors/Vertex", Ogre::RenderOperation::OT_LINE_LIST);
for(int i=0; i<size; i++)
{
for(int j=0; j<3; j++)
{
mob->position(vertices[3*i+0], vertices[3*i+1],vertices[3*i+2]);
mob->normal(normals[i][0], normals[i][1], normals[i][2]);
mob->colour(colors[i][0], colors[i][1], colors[i][2]);
}
}
mob->end();
Ogre::AxisAlignedBox aaBox( 0, 0, 0, 5, 5, 5);
mob->setBoundingBox(aaBox);
const Ogre::String node("Axis");
m_Axis = m_ogreSceneMgr->getRootSceneNode()
->createChildSceneNode(node);
m_Axis->attachObject(mob);
m_Axis->_updateBounds();
}
void QTOgreWindow::createCube()
{
m_ogreSceneMgr->setAmbientLight(Ogre::ColourValue(1.0f, 1.0f, 1.0f));
Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(
"Test/ColourTest", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
material->getTechnique(0)->getPass(0)->setVertexColourTracking(Ogre::TVC_AMBIENT);
const size_t nVertices = 8;
const size_t vbufCount = 3*2*nVertices;
float vertices[vbufCount] = {
0.0,1.0,0.0, //0 position
1.0,1.0,0.0, //1 position
1.0,0.0,0.0, //2 position
0.0,0.0,0.0, //3 position
0.0,1.0,1.0, //4 position
1.0,1.0,1.0, //5 position
1.0,0.0,1.0, //6 position
0.0,0.0,1.0, //7 position
};
float normals[6][3] = {
{ 0, 0,-1},
{ 1, 0, 0},
{ 0, 0, 1},
{-1, 0, 0},
{ 0, 1, 0},
{ 0,-1, 0}
};
/// Define 12 triangles (two triangles per cube face)
/// The values in this table refer to vertices in the above table
const size_t ibufCount = 36;
unsigned short faces[ibufCount] = {
0,2,3,
0,1,2,
1,6,2,
1,5,6,
4,6,5,
4,7,6,
0,7,4,
0,3,7,
0,5,1,
0,4,5,
2,7,3,
2,6,7
};
int pIdx, fIdx;
const int size = 12;
const Ogre::String mb("Cube");
Ogre::ManualObject* mob = m_ogreSceneMgr->createManualObject(mb);
for(int i=0; i<size; i++)
{
mob->begin("Test/ColourTest", Ogre::RenderOperation::OT_TRIANGLE_LIST);
for(int j=0; j<3; j++)
{
pIdx = faces[3*i+j];
fIdx = i/2;
mob->position(vertices[3*pIdx+0], vertices[3*pIdx+1],vertices[3*pIdx+2]);
mob->normal(normals[fIdx][0], normals[fIdx][1], normals[fIdx][2]);
mob->colour(1,0,1);
}
mob->end();
}
Ogre::AxisAlignedBox aaBox( 0, 0, 0, 5, 5, 5);
mob->setBoundingBox(aaBox);
const Ogre::String node("Cube");
Ogre::SceneNode* thisSceneNode = m_ogreSceneMgr->getRootSceneNode()->createChildSceneNode(node);
thisSceneNode->attachObject(mob);
// thisSceneNode->showBoundingBox(true);
// thisSceneNode->setPosition(8,0,0);
// m_cameraMan->setTarget(thisSceneNode);
Ogre::Light* light = m_ogreSceneMgr->createLight("MainLight3");
light->setPosition(10.0f, 1.0f, 6.0f);
light->setDiffuseColour(0.8, 0.8, 0.8);
light->setSpecularColour(1.0, 1.0, 1.0);
}
void QTOgreWindow::loadScene()
{
/*
Example scene
Derive this class for your own purpose and overwite this function to have a working Ogre widget with
your own content.
*/
m_ogreSceneMgr->setAmbientLight(Ogre::ColourValue(1.0f, 1.0f, 1.0f));
Ogre::Light* light = m_ogreSceneMgr->createLight("MainLight");
light->setPosition(6.0f, 6.0f, 6.0f);
light->setDiffuseColour(1.0, 1.0, 1.0);
light->setSpecularColour(1.0, 1.0, 1.0);
m_ogreSceneMgr->getRootSceneNode()->attachObject(light);
light = m_ogreSceneMgr->createLight("MainLight2");
light->setPosition(6.0f, -6.0f, 6.0f);
light->setDiffuseColour(1.0, 1.0, 1.0);
light->setSpecularColour(1.0, 1.0, 1.0);
m_ogreSceneMgr->getRootSceneNode()->attachObject(light);
}
void QTOgreWindow::render()
{
Ogre::WindowEventUtilities::messagePump();
m_ogreRoot->renderOneFrame();
}
void QTOgreWindow::renderLater()
{
if (!m_update_pending)
{
m_update_pending = true;
QApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
}
bool QTOgreWindow::event(QEvent *event)
{
return QWindow::event(event);
}
/*
Called after the QWindow is reopened or when the QWindow is first opened.
*/
void QTOgreWindow::exposeEvent(QExposeEvent *event)
{
Q_UNUSED(event);
if (isExposed())
renderNow();
if(!_qtime.isActive()) {
QObject::connect(&_qtime, SIGNAL(timeout()), this, SLOT(renderNow()));
_qtime.start(40);
}
}
/*
The renderNow() function calls the initialize() function when needed and if the QWindow is already
initialized and prepped calls the render() method.
*/
void QTOgreWindow::renderNow()
{
if (!isExposed())
return;
if (m_ogreRoot == NULL)
{
initialize();
}
render();
if (m_animating)
renderLater();
}
/*
Our event filter; handles the resizing of the QWindow. When the size of the QWindow changes note the
call to the Ogre3D window and camera. This keeps the Ogre3D scene looking correct.
*/
bool QTOgreWindow::eventFilter(QObject *target, QEvent *event)
{
if (target == this)
{
if (event->type() == QEvent::Resize)
{
if (isExposed() && m_ogreWindow != NULL)
{
m_ogreWindow->resize(this->width(), this->height());
}
}
}
return false;
}
void QTOgreWindow::takeSnapshot(Ogre::String& fileName)
{
m_ogreWindow->writeContentsToFile(fileName);
}
void QTOgreWindow::_loadResources()
{
Ogre::ResourceGroupManager& mgr = Ogre::ResourceGroupManager::getSingleton();
Ogre::ConfigFile cf;
cf.load("resources.cfg");//load resources config file
Ogre::ConfigFile::SectionIterator sectionIter = cf.getSectionIterator();
Ogre::String sectionName,typeName,dataname;
while(sectionIter.hasMoreElements())
{
// get section name
sectionName = sectionIter.peekNextKey();
// get scetion settings and iterator
Ogre::ConfigFile::SettingsMultiMap *settings = sectionIter.getNext();
Ogre::ConfigFile::SettingsMultiMap::iterator i;
for(i = settings->begin(); i != settings->end(); ++i)
{
typeName = i->first;
dataname = 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
mgr.addResourceLocation(String(macBundlePath() + "/" + archName)
, typeName, secName);
#else
mgr.addResourceLocation(dataname,typeName,sectionName);
#endif
}
}
// init resources loaded, ONLY after this ".mesh" files can be loaded
mgr.initialiseAllResourceGroups();
}
/*
How we handle keyboard and mouse events.
*/
void QTOgreWindow::keyPressEvent(QKeyEvent * ev)
{
}
void QTOgreWindow::keyReleaseEvent(QKeyEvent * ev)
{
}
void mapMouseBtnEvent(QMouseEvent* curE, OgreBites::MouseButtonEvent& oe)
{
if(curE->button()==Qt::MouseButton::LeftButton)
oe.button = OgreBites::BUTTON_LEFT ;
else if (curE->button()==Qt::MouseButton::RightButton)
oe.button = OgreBites::BUTTON_RIGHT;
else
oe.button = OgreBites::BUTTON_MIDDLE;
oe.timestamp = curE->timestamp();
oe.clicks = 1;
oe.x = curE->x();
oe.y = curE->y();
}
void mapMouseMotionEvent(QMouseEvent* curE, QMouseEvent* preE, OgreBites::MouseMotionEvent& oe)
{
oe.type = SDL_MOUSEMOTION;
oe.timestamp = curE->timestamp();
oe.x = curE->x();
oe.y = curE->y();
oe.xrel = curE->x() - preE->x();
oe.yrel = curE->y() - preE->y();
}
void mapMouseWheelEvent(QWheelEvent* curE, QMouseEvent* preE, OgreBites::MouseWheelEvent& oe)
{
oe.type = SDL_MOUSEWHEEL;
oe.timestamp = curE->timestamp();
oe.x = curE->x() - preE->x();
oe.y = curE->y() - preE->y();
oe.direction = SDL_MOUSEWHEEL_NORMAL;
}
void QTOgreWindow::mouseMoveEvent( QMouseEvent* e )
{
OgreBites::MouseMotionEvent ogreE;
mapMouseMotionEvent(e, &_lastMouseEvent, ogreE);
if (m_cameraMan && (e->buttons() & Qt::LeftButton))
m_cameraMan->mouseMoved(ogreE);
_lastMouseEvent = *e;
}
void QTOgreWindow::wheelEvent(QWheelEvent *e)
{
OgreBites::MouseWheelEvent ogreE;
mapMouseWheelEvent(e, &_lastMouseEvent, ogreE);
if (m_cameraMan)
m_cameraMan->mouseWheelRolled(ogreE);
//_lastMouseEvent = *e;
}
void QTOgreWindow::mousePressEvent( QMouseEvent* e )
{
OgreBites::MouseButtonEvent ogreE;
mapMouseBtnEvent(e, ogreE);
ogreE.state = SDL_PRESSED;
m_cameraMan->mousePressed(ogreE);
_lastMouseEvent = *e;
}
void QTOgreWindow::mouseReleaseEvent( QMouseEvent* e )
{
OgreBites::MouseButtonEvent ogreE;
mapMouseBtnEvent(e, ogreE);
ogreE.state = SDL_RELEASED;
m_cameraMan->mousePressed(ogreE);
_lastMouseEvent = *e;
return;
}
/*
Function to keep track of when we should and shouldn't redraw the window; we wouldn't want to do
rendering when the QWindow is minimized. This takes care of those scenarios.
*/
void QTOgreWindow::setAnimating(bool animating)
{
m_animating = animating;
if (animating)
renderLater();
}
bool QTOgreWindow::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
//m_cameraMan->frameRenderingQueued(evt);
return true;
}
void QTOgreWindow::log(Ogre::String msg)
{
if(Ogre::LogManager::getSingletonPtr() != NULL) Ogre::LogManager::getSingletonPtr()->logMessage(msg);
}
void QTOgreWindow::log(QString msg)
{
}
void QTOgreWindow::setTargetSceneNode(Ogre::SceneNode *t)
{
m_cameraMan->setTarget(t);
}
Ogre::SceneNode* QTOgreWindow::getTargetSceneNode()
{
return m_cameraMan->getTarget();
}
const Ogre::SceneNode* QTOgreWindow::getTargetSceneNode()const
{
return m_cameraMan->getTarget();
}