Saturday, July 4, 2009

Qt - Ogre - VS2008 Express

This post describes the steps necessary for getting Qt, Ogre and Visual Studio 2008 Express to work, as well as the code for a very basic OgreWidget.

Compile Qt with VS 2008 Express
  1. Download and install Visual Studio Visual C++ 2008 Express Edition

  2. Download the source code of the Qt libraries

  3. Extract the zip to a path without spaces: e.g. C:\Qt

  4. Open the Visual Studio prompt: programs->visual studio 2008-> vs 2008 tools-> vs 2008 command prompt


    • Go to the Qt dir

    • Type: configure

    • Type: nmake [this may take several hours]


  5. Setup path and VS 2008 directories


    • Add an environment variable: QTDIR=C:\Qt

    • Add to the path: %QTDIR%\bin

    • Check if the previous is done right by opening a command prompt and typing: qmake [if this shows the help of this command, it is ok]

    • Add $(QTDIR)\include to the VS 2008 VC++ include directories

    • Add $(QTDIR)\lib to the VS 2008 VC++ library directories




Set up Ogre

  1. Download and install Ogre SDK for Visual C++ 2008

  2. Add OGRE_HOME to the environment variables: e.g. OGRE_HOME=C:\OgreSDK



A Qt/Ogre project in VS 2008 Express

You will need a few .pro files setting up your Qt/Ogre project.
It can all be placed into one file, but it might be convenient to split it into several files for easier reuse.

Settings.pro : Change your ogre home directory

win32 {
# You may need to change this include directory
OGREHOME = C:\OgreSDK
Release:LIBS += -L$$OGREHOME\bin\release
Debug:LIBS += -L$$OGREHOME\bin\debug
LIBS += -L$$OGREHOME\lib
INCLUDEPATH += $$OGREHOME\include
}


For each project a separate project file.
MyProject.pro : the sources and headers need to be edited, obviously

exists(../settings.pro):include(../settings.pro)
else:message("I can't find settings file")

CONFIG(debug, debug|release) {
LIBS *= -lOgreMain_d
}

CONFIG(release, debug|release) {
LIBS *= -lOgreMain
}

TEMPLATE += app
CONFIG += qt warn_on
SOURCES += Main.cpp OgreWidget.cpp
HEADERS += Main.h MainUI.h OgreWidget.h
TARGET = Main

win32:debug:CONFIG += console


This is a basic config to configure a Qt/Ogre application.
This project file assumes the Settings.pro file is one directory up.

Read more about Qmake project files: here

Now we set up the actual Visual Studio project:
File->New Project->Visual C++ ->General->Makefile Project
Go to the project properties (for All Configurations):
Configuration Properties -> NMake -> General





Build Command Line:qmake && nmake $(ConfigurationName)
Rebuild Command Line:qmake && nmake $(ConfigurationName)-clean && nmake $(ConfigurationName)
Clean Command Line:nmake $(ConfigurationName)-clean
Output:$(ConfigurationName)/Main.exe


This will tell your Visual Studio to use qmake, which will convert the .pro files to a makefile for nmake, and to compile this file with nmake.

Qt/Ogre IntelliSense setup

Go to the project properties (for All Configurations):
Configuration Properties -> NMake -> IntelliSense



Common Language Runtime SupportCommon Language Runtime Support (/clr)
Include search path"$(QTDIR)\include";"$(OGRE_HOME)\include"


An OgreWidget implementation

I've tried to create a very basic OgreWidget which subclasses a QWidget. Most of the code was taken from a couple of the sources below, taking only the parts which are strictly necessary and leaving out all redundant code. The widget only renders the Ogre scene, it does not handle any user input.
OgreWidget.h
OgreWidget.cpp

Here is a code snippet on how to use this OgreWidget:
In a QMainWindow:

m_pWidget = new QtOgre::OgreWidget(this);
//Add the widget to the QMainWindow
setCentralWidget(m_pWidget);
//uncomment code below for fullscreen
//Hide all the GUI stuff you do not want to see fullscreen
/*menuBar()->hide();
statusBar()->hide();
showFullScreen();*/


Easy, isn't it?

Now you set up the Ogre scene:

//Create the scene manager
mSceneManager = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC, "GenericSceneManager");
//Create the camera
mCamera = mSceneManager->createCamera("Cam");
//Add a viewport to the render window from the OgreWidget
m_pWidget->renderWindow()->addViewport(mCamera);


Of course your Ogre code will become much more ellaborate, but this is the minimum you need to render an Ogre scene inside a Qt Window.

I hope this is useful to someone :)

JR


Sources

Qt and VS 1
Qt and VS 2
Qt and VS 3
Qt and Ogre 1
Qt and Ogre 2
Qt and Ogre 3
IntelliSense

18 comments:

  1. I've used the above code and it works fine, however, I can't override the mouse or keyboard events (that is I can't get the application to jump into those functions).

    Any ideas?

    Ta

    JP

    ReplyDelete
  2. I suggest checking out the links in the "sources" section. You will have to adjust the OgreWidget class.

    ReplyDelete
  3. Thanks,
    I've been trying that for a fair few days now and I just can't get it to work. A lot of the projects I've looked at (like the Ogre Qt Framework) are far too complex.

    Would you be able to have a look at doing this also please?

    Thanks

    JP

    ReplyDelete
  4. Have a look at: https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/QtOgreFramework/QtOgre/include/EventHandlingOgreWidget.h

    and

    https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/QtOgreFramework/QtOgre/source/EventHandlingOgreWidget.cpp

    It extends an ogre widget (probably not exactly the same as the one here, but not much different either) with event handling functionality.

    ReplyDelete
  5. Thanks for youre help so far.

    If I use their OgreEntity and EventHandlingOgreEntity then I can capture the mouse pressed event. Albeit on a blank Ogre widget.

    However, if I try to insert my code that does things like sets up the camera, adds the ogrehead.mesh etc (which is in the constructor of the QMainWindow after I've made the central widget to be the EventHandlingOgreEntity), I get a crash.

    So where is the best place for me to put this code in? It's the code in a non Qt application that you'd put in createScene.

    Cheers

    JP

    ReplyDelete
  6. Debug the code to see where the crash comes from and solve it, I suppose.

    You should put the code where you like it to be, but after everything it depends on is initialised.

    ReplyDelete
  7. I can stop the crash by shifting the code at the end of the initialisation part of OgreWidget, but now I'm just getting an empty Ogre widget in my application.

    Ahhhhhhhh

    ReplyDelete
  8. Analyse the code and the solution will come to you :)

    ReplyDelete
  9. That's what I'm trying to do

    ReplyDelete
  10. Do you have any ideas to help? I've been looking into this for over a week now and still have no luck.

    It's not like I want someone to do it for me.

    ReplyDelete
  11. I suggest getting help on the Ogre forums.

    ReplyDelete
  12. That's where I've been trying (JonnyJP is my username), nobody seems to know anything even the people who have done exactly what I want.

    ReplyDelete
  13. Right, if I change the line of your code to:
    ogreWindowParams["externalWindowHandle"] = Ogre::StringConverter::toString((unsigned long)q_parent->winId());

    I can get it to jump into the mousePressed event simply by adding it to the OgreWidget.

    However, it's flickering like mental!

    ReplyDelete
  14. What did you do with the parentWindowHandle?
    Remove it ?

    ReplyDelete
  15. I took that bit out.

    ReplyDelete
  16. I think you should try to use the Ogre event handling code, not the QT event handling. I think that should work :)

    ReplyDelete
  17. In your_ogre_dir\samples\include take a look at ExampleFrameListener

    ReplyDelete
  18. Thanks for your help.
    I basically stripped down the framework at: http://www.ogre3d.org/forums/viewtopic.php?f=11&t=45709 by removing anything I didn't need. I also had to add the paintEngine function (page 9) to remove flicker.

    I guess that function contained a lot of Qt drawing related stuff that was interfering with the Ogre Widget, but since that function now does nothing and returns 0, there is no unnecessary rendering going on.

    Cheers

    JP

    ReplyDelete