History: Integrating Ogre into QT5
Preview of version: 13
Work in Progress
Original forum link: http://www.ogre3d.org/forums/viewtopic.php?p=515314#p515314
The following document is an up-to-date method of integrating Ogre3D into the latest version of Qt (5.4 as of this writing).
Previous methods of integrating Ogre3D with Qt focused on using a QWidget and overriding the paint methods for drawing.
The method proposed in this document uses a QWindow as opposed to a QWidget. There are several reasons for using a QWindow over a QWidget:
- Smaller memory and processing footprint. Simply put, QWidgets use a lot of resources in comparison to QWindows and thus adds a lot of unnecessary overhead. Ogre3D doesn't require much from Qt besides a surface to draw upon and the input/window events from the underlying OS and windowing system that a QWindow provides. As a related sidenote, QWidget actually inherits from QWindow as shown in the below inheritance chain.
- Easier integration. Because of the simplicity of QWindow it is actually much easier to integrate Ogre3D into Qt using a QWindow versus using a QWidget. QWidget by default creates a surface to draw on which Ogre3D doesn't need to draw upon. Thus, as shown in earlier Qt-Ogre3D implementation documents you need to override Qt methods to prevent the default QWidget methods from "drawing over" Ogre3D. Using a QWindow this is unnecessary as with a QWindow no "surface" is automatically created; you can simply supply QWindow's native "Window ID" (whether it is a HWND on Windows or the equivalent representations on Linux/Mac OS) and Ogre3D takes care of the rest.
- All standard Qt functionality can still be implemented. If you still need to have a QWidget (for integration into a QMainWindow/QTabWidget/etc.) this can still be achieved. You can easily create a QWidget "container" for your QWindow and get all of the standard benefits of a QWidget. A standard use case for this would be needing to place an Ogre3D-integrated QWindow inside of a standard QMainWindow as a "central widget".
Note that the below implementation depends on you following the guides on setting up include/library/runtime binary directories. Since the setup for this is compiler and operating system dependent such details is beyond the scope of this document.
In summary, consult a guide like this for setting up directory paths, includes, etc. Note that you will need to do this for Qt as well so consult equivalent documentation for Qt Creator like this.
With the proper setup of the environment done, we need to create a header file to include the necessary Qt components as well as including Ogre3D:
#ifndef QTOGREWINDOW_H_ #define QTOGREWINDOW_H_ /* For the purposes of creating a bare-bones Qt implementation I found that I only need to include these three (3) Qt headers. */ #include <QtWidgets/QApplication> #include <QtGui/QKeyEvent> #include <QtGui/QWindow> /* As expected; the Ogre3D header. */ #include "OGRE/Ogre.h" /* With the headers included we now need to inherit from QWindow. */ class QTOgreWindow : public QWindow { /* 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(QObject *parent = NULL); ~QTOgreWindow(); virtual void render(QPainter *painter); virtual void render(); virtual void initialize(); void setAnimating(bool animating); public slots: virtual void renderLater(); virtual void renderNow(); virtual bool eventFilter(QObject *target, QEvent *event); protected: Ogre::Root* ogreRoot; Ogre::RenderWindow* ogreWindow; Ogre::SceneManager* ogreSceneMgr; Ogre::Camera* ogreCamera; Ogre::Viewport* ogreViewPort; bool m_update_pending; bool m_animating; virtual void keyPressEvent(QKeyEvent * ev); virtual void keyReleaseEvent(QKeyEvent * ev); virtual void exposeEvent(QExposeEvent *event); virtual bool event(QEvent *event); private: private slots: }; #endif