├── .gitignore ├── LICENSE ├── README.md ├── example ├── cameranodeobject.cpp ├── cameranodeobject.h ├── config │ ├── plugins.cfg │ └── resources.cfg ├── example.pro ├── exampleapp.cpp ├── exampleapp.h ├── main.cpp └── resources │ ├── GrassandSky.png │ ├── arrow.png │ ├── circle.png │ ├── data.zip │ ├── example.qml │ ├── minus.png │ ├── move.gif │ ├── plus.png │ ├── qt-logo.png │ └── resources.qrc ├── lib ├── lib.pro ├── ogrecamerawrapper.cpp ├── ogrecamerawrapper.h ├── ogreengine.cpp ├── ogreengine.h ├── ogreitem.cpp ├── ogreitem.h ├── ogrenode.cpp └── ogrenode.h └── qmlogre.pro /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | .obj/ 3 | .moc/ 4 | .ui/ 5 | Makefile 6 | *~ 7 | *.app 8 | .directory 9 | *.log 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | ** 3 | ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) 4 | ** Copyright (c) 2013 Markus Weiland 5 | ** 6 | ** All rights reserved. 7 | ** 8 | ** You may use this file under the terms of the BSD license as follows: 9 | ** 10 | ** "Redistribution and use in source and binary forms, with or without 11 | ** modification, are permitted provided that the following conditions are met: 12 | ** 13 | ** * Redistributions of source code must retain the above copyright notice, 14 | ** this list of conditions and the following disclaimer. 15 | ** * Redistributions in binary form must reproduce the above copyright notice, 16 | ** this list of conditions and the following disclaimer in the documentation 17 | ** and/or other materials provided with ** the distribution. 18 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the 19 | ** names of its contributors may be used to endorse or promote products 20 | ** derived from this software without specific ** prior written permission. 21 | ** 22 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 | ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 32 | ** 33 | **************************************************************************/ 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | QmlOgre 2 | ======= 3 | QmlOgre is a library that allows integrating Ogre3D into Qt QML scenes. 4 | 5 | Features 6 | -------- 7 | 8 | * Renders Ogre viewports to FBO (Frame Buffer Objects) which are then applied to QML items as textures 9 | * Window states, the application event loop and user input are managed by Qt 10 | * Creates an OpenGL context for Ogre which is shared with Qt's QML OpenGL context 11 | * Allows using the full range of QML features 12 | * Places no restriction on the depth sorting of Ogre items versus other QML elements 13 | * Allows multiple independent cameras, each assigned to an Ogre QML item, viewing the same scene 14 | 15 | Requirements 16 | ------------ 17 | 18 | * Ogre 1.8 19 | * Qt 5 20 | 21 | Documentation 22 | ------------- 23 | 24 | The code is split into the ```lib``` library code and ```example``` application code. 25 | 26 | License 27 | ------- 28 | QmlOgre is licensed under the BSD license. See ```LICENSE``` for details. 29 | -------------------------------------------------------------------------------- /example/cameranodeobject.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #include "cameranodeobject.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | static const Ogre::Vector3 initialPosition(0, 0, 300); 19 | 20 | CameraNodeObject::CameraNodeObject(QObject *parent) : 21 | QObject(parent), 22 | OgreCameraWrapper(), 23 | m_camera(0), 24 | m_yaw(0), 25 | m_pitch(0), 26 | m_zoom(1) 27 | { 28 | Ogre::SceneManager *sceneManager = Ogre::Root::getSingleton().getSceneManager("mySceneManager"); 29 | 30 | // let's use the current memory address to create a unique name 31 | QString instanceName; 32 | instanceName.sprintf("camera_%08p", this); 33 | 34 | Ogre::Camera *camera = sceneManager->createCamera(instanceName.toLatin1().data()); 35 | camera->setNearClipDistance(1); 36 | camera->setFarClipDistance(99999); 37 | camera->setAspectRatio(1); 38 | camera->setAutoTracking(true, sceneManager->getRootSceneNode()); 39 | 40 | m_camera = camera; 41 | m_node = sceneManager->getRootSceneNode()->createChildSceneNode(); 42 | m_node->attachObject(camera); 43 | camera->move(initialPosition); 44 | } 45 | 46 | void CameraNodeObject::updateRotation() 47 | { 48 | m_node->resetOrientation(); 49 | m_node->yaw(Ogre::Radian(Ogre::Degree(m_yaw))); 50 | m_node->pitch(Ogre::Radian(Ogre::Degree(m_pitch))); 51 | } 52 | 53 | void CameraNodeObject::setZoom(qreal z) 54 | { 55 | m_zoom = z; 56 | m_node->resetOrientation(); 57 | m_camera->setPosition(initialPosition * (1 / m_zoom)); 58 | updateRotation(); 59 | } 60 | -------------------------------------------------------------------------------- /example/cameranodeobject.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #ifndef CAMERANODEOBJECT_H 11 | #define CAMERANODEOBJECT_H 12 | 13 | #include 14 | 15 | #include "../lib/ogrecamerawrapper.h" 16 | 17 | namespace Ogre { 18 | class SceneNode; 19 | class Camera; 20 | } 21 | 22 | class CameraNodeObject : public QObject, public OgreCameraWrapper 23 | { 24 | Q_OBJECT 25 | Q_PROPERTY(qreal yaw READ yaw WRITE setYaw) 26 | Q_PROPERTY(qreal pitch READ pitch WRITE setPitch) 27 | Q_PROPERTY(qreal zoom READ zoom WRITE setZoom) 28 | public: 29 | explicit CameraNodeObject(QObject *parent = 0); 30 | 31 | Ogre::SceneNode *sceneNode() const 32 | { return m_node; } 33 | Ogre::Camera* camera() const { return m_camera; } 34 | 35 | qreal yaw() const 36 | { return m_yaw; } 37 | qreal pitch() const 38 | { return m_pitch; } 39 | qreal zoom() const 40 | { return m_zoom; } 41 | void setYaw(qreal y) 42 | { m_yaw = y; updateRotation(); } 43 | void setPitch(qreal p) 44 | { m_pitch = p; updateRotation(); } 45 | void setZoom(qreal z); 46 | 47 | private: 48 | void updateRotation(); 49 | 50 | Ogre::SceneNode *m_node; 51 | Ogre::Camera *m_camera; 52 | 53 | qreal m_yaw; 54 | qreal m_pitch; 55 | qreal m_zoom; 56 | }; 57 | 58 | #endif // CAMERANODEOBJECT_H 59 | -------------------------------------------------------------------------------- /example/config/plugins.cfg: -------------------------------------------------------------------------------- 1 | # Defines plugins to load 2 | 3 | # Define plugin folder 4 | PluginFolder=/usr/lib/x86_64-linux-gnu/OGRE-1.8.0 5 | 6 | # Define plugins 7 | # Plugin=RenderSystem_Direct3D9 8 | # Plugin=RenderSystem_Direct3D10 9 | # Plugin=RenderSystem_Direct3D11 10 | Plugin=RenderSystem_GL 11 | # Plugin=RenderSystem_GLES 12 | Plugin=Plugin_ParticleFX 13 | Plugin=Plugin_BSPSceneManager 14 | # Plugin=Plugin_CgProgramManager 15 | Plugin=Plugin_PCZSceneManager 16 | Plugin=Plugin_OctreeZone 17 | Plugin=Plugin_OctreeSceneManager 18 | -------------------------------------------------------------------------------- /example/config/resources.cfg: -------------------------------------------------------------------------------- 1 | # Resources required by the sample browser and most samples. 2 | [Essential] 3 | Zip=resources/data.zip 4 | 5 | # Common sample resources needed by many of the samples. 6 | # Rarely used resources should be separately loaded by the 7 | # samples which require them. 8 | [Popular] 9 | #FileSystem=Data/materials/scripts 10 | #FileSystem=Data/materials/textures 11 | #FileSystem=Data/models 12 | #FileSystem=Data/RTShaderLib 13 | #Zip=Data/packs/Sinbad.zip 14 | 15 | # Resource locations to be added to the default path 16 | [General] 17 | #FileSystem=Data 18 | -------------------------------------------------------------------------------- /example/example.pro: -------------------------------------------------------------------------------- 1 | CONFIG += qt 2 | QT += qml quick 3 | TEMPLATE = app 4 | TARGET = qmlogre 5 | 6 | LIBS += -L../lib -lqmlogre 7 | 8 | UI_DIR = ./.ui 9 | OBJECTS_DIR = ./.obj 10 | MOC_DIR = ./.moc 11 | 12 | SOURCES += main.cpp \ 13 | cameranodeobject.cpp \ 14 | exampleapp.cpp 15 | 16 | HEADERS += cameranodeobject.h \ 17 | exampleapp.h 18 | 19 | OTHER_FILES += \ 20 | resources/example.qml 21 | 22 | macx { 23 | OGREDIR = $$(OGRE_HOME) 24 | isEmpty(OGREDIR) { 25 | error(QmlOgre needs Ogre to be built. Please set the environment variable OGRE_HOME pointing to your Ogre root directory.) 26 | } else { 27 | message(Using Ogre libraries in $$OGREDIR) 28 | INCLUDEPATH += $$OGREDIR/include/OGRE 29 | INCLUDEPATH += $$OGREDIR/include/OGRE/RenderSystems/GL 30 | QMAKE_LFLAGS += -F$$OGREDIR/lib/release 31 | LIBS += -framework Ogre 32 | 33 | BOOSTDIR = $$OGREDIR/boost_1_42 34 | !isEmpty(BOOSTDIR) { 35 | INCLUDEPATH += $$BOOSTDIR 36 | # LIBS += -L$$BOOSTDIR/lib -lboost_date_time-xgcc40-mt-1_42 -lboost_thread-xgcc40-mt-1_42 37 | } 38 | } 39 | } else:unix { 40 | CONFIG += link_pkgconfig 41 | PKGCONFIG += OGRE 42 | } else:win32 { 43 | OGREDIR = $$(OGRE_HOME) 44 | isEmpty(OGREDIR) { 45 | error(QmlOgre needs Ogre to be built. Please set the environment variable OGRE_HOME pointing to your Ogre root directory.) 46 | } else { 47 | message(Using Ogre libraries in $$OGREDIR) 48 | INCLUDEPATH += $$OGREDIR/include/OGRE 49 | INCLUDEPATH += $$OGREDIR/include/OGRE/RenderSystems/GL 50 | CONFIG(release, debug|release) { 51 | LIBS += -L$$OGREDIR/lib/release -L$$OGREDIR/lib/release/opt -lOgreMain -lRenderSystem_GL 52 | } else { 53 | LIBS += -L$$OGREDIR/lib/debug -L$$OGREDIR/lib/debug/opt -lOgreMain_d -lRenderSystem_GL_d 54 | } 55 | 56 | BOOSTDIR = $$OGREDIR/boost_1_42 57 | !isEmpty(BOOSTDIR) { 58 | INCLUDEPATH += $$BOOSTDIR 59 | CONFIG(release, debug|release) { 60 | LIBS += -L$$BOOSTDIR/lib -llibboost_date_time-vc90-mt-1_42 -llibboost_thread-vc90-mt-1_42 61 | } else { 62 | LIBS += -L$$BOOSTDIR/lib -llibboost_date_time-vc90-mt-gd-1_42 -llibboost_thread-vc90-mt-gd-1_42 63 | } 64 | } 65 | } 66 | } 67 | 68 | RESOURCES += resources/resources.qrc 69 | 70 | # Copy all resources to build folder 71 | Resources.path = $$OUT_PWD/resources 72 | Resources.files = resources/*.zip 73 | 74 | # Copy all config files to build folder 75 | Config.path = $$OUT_PWD 76 | Config.files = config/* 77 | 78 | # make install 79 | INSTALLS += Resources Config 80 | -------------------------------------------------------------------------------- /example/exampleapp.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #include "exampleapp.h" 11 | 12 | #include "cameranodeobject.h" 13 | 14 | #include "../lib/ogreitem.h" 15 | #include "../lib/ogreengine.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | static QString appPath() 22 | { 23 | QString path = QCoreApplication::applicationDirPath(); 24 | QDir dir(path); 25 | #ifdef Q_WS_MAC 26 | dir.cdUp(); 27 | dir.cdUp(); 28 | dir.cdUp(); 29 | #elif defined(Q_WS_WIN) 30 | dir.cdUp(); 31 | #endif 32 | return dir.absolutePath(); 33 | } 34 | 35 | ExampleApp::ExampleApp(QWindow *parent) : 36 | QQuickView(parent) 37 | , m_ogreEngine(0) 38 | , m_sceneManager(0) 39 | , m_root(0) 40 | { 41 | qmlRegisterType("Example", 1, 0, "Camera"); 42 | 43 | // start Ogre once we are in the rendering thread (Ogre must live in the rendering thread) 44 | connect(this, &ExampleApp::beforeRendering, this, &ExampleApp::initializeOgre, Qt::DirectConnection); 45 | connect(this, &ExampleApp::ogreInitialized, this, &ExampleApp::addContent); 46 | } 47 | 48 | ExampleApp::~ExampleApp() 49 | { 50 | if (m_sceneManager) { 51 | m_root->destroySceneManager(m_sceneManager); 52 | } 53 | } 54 | 55 | void ExampleApp::initializeOgre() 56 | { 57 | // we only want to initialize once 58 | disconnect(this, &ExampleApp::beforeRendering, this, &ExampleApp::initializeOgre); 59 | 60 | // start up Ogre 61 | m_ogreEngine = new OgreEngine(this); 62 | m_root = m_ogreEngine->startEngine(); 63 | m_ogreEngine->setupResources(); 64 | 65 | // set up Ogre scene 66 | m_sceneManager = m_root->createSceneManager(Ogre::ST_GENERIC, "mySceneManager"); 67 | 68 | m_sceneManager->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.3)); 69 | m_sceneManager->createLight("myLight")->setPosition(20, 80, 50); 70 | 71 | // Resources with textures must be loaded within Ogre's GL context 72 | m_ogreEngine->activateOgreContext(); 73 | 74 | m_sceneManager->setSkyBox(true, "SpaceSkyBox", 10000); 75 | m_sceneManager->getRootSceneNode()->attachObject(m_sceneManager->createEntity("Head", "ogrehead.mesh")); 76 | 77 | m_ogreEngine->doneOgreContext(); 78 | 79 | emit(ogreInitialized()); 80 | } 81 | 82 | void ExampleApp::addContent() 83 | { 84 | // expose objects as QML globals 85 | rootContext()->setContextProperty("Window", this); 86 | rootContext()->setContextProperty("OgreEngine", m_ogreEngine); 87 | 88 | // load the QML scene 89 | setResizeMode(QQuickView::SizeRootObjectToView); 90 | setSource(QUrl("qrc:/qml/example.qml")); 91 | } 92 | -------------------------------------------------------------------------------- /example/exampleapp.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #ifndef EXAMPLEAPP_H 11 | #define EXAMPLEAPP_H 12 | 13 | #include "../lib/ogreengine.h" 14 | 15 | #include 16 | 17 | class ExampleApp : public QQuickView 18 | { 19 | Q_OBJECT 20 | public: 21 | explicit ExampleApp(QWindow *parent = 0); 22 | ~ExampleApp(); 23 | 24 | signals: 25 | void ogreInitialized(); 26 | 27 | public slots: 28 | void initializeOgre(); 29 | void addContent(); 30 | 31 | private: 32 | OgreEngine *m_ogreEngine; 33 | 34 | Ogre::SceneManager *m_sceneManager; 35 | Ogre::Root *m_root; 36 | }; 37 | 38 | #endif // EXAMPLEAPP_H 39 | -------------------------------------------------------------------------------- /example/main.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #include "exampleapp.h" 11 | 12 | #include 13 | 14 | int main(int argc, char **argv) 15 | { 16 | QGuiApplication app(argc, argv); 17 | 18 | ExampleApp eApp; 19 | 20 | eApp.resize(900, 700); 21 | eApp.show(); 22 | eApp.raise(); 23 | 24 | return app.exec(); 25 | } 26 | -------------------------------------------------------------------------------- /example/resources/GrassandSky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advancingu/QmlOgre/cad4d3a62af4ec70541f90269761ec17a9cfb71c/example/resources/GrassandSky.png -------------------------------------------------------------------------------- /example/resources/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advancingu/QmlOgre/cad4d3a62af4ec70541f90269761ec17a9cfb71c/example/resources/arrow.png -------------------------------------------------------------------------------- /example/resources/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advancingu/QmlOgre/cad4d3a62af4ec70541f90269761ec17a9cfb71c/example/resources/circle.png -------------------------------------------------------------------------------- /example/resources/data.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advancingu/QmlOgre/cad4d3a62af4ec70541f90269761ec17a9cfb71c/example/resources/data.zip -------------------------------------------------------------------------------- /example/resources/example.qml: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | import QtQuick 2.0 11 | import Ogre 1.0 12 | import Example 1.0 13 | 14 | Rectangle { 15 | id: ogre 16 | width: 1024 17 | height: 768 18 | color: "black" 19 | 20 | Image { 21 | id: back 22 | anchors.fill: parent 23 | source: "qrc:/images/GrassandSky.png" 24 | Behavior on opacity { NumberAnimation { } } 25 | } 26 | 27 | Camera { 28 | id: cam1 29 | } 30 | 31 | OgreItem { 32 | id: ogreitem 33 | width: 600; height: 400 34 | anchors.left: toolbar1.left 35 | anchors.leftMargin: -5 36 | anchors.top: toolbar1.bottom 37 | anchors.topMargin: 6 38 | camera: cam1 39 | ogreEngine: OgreEngine 40 | 41 | Behavior on opacity { NumberAnimation { } } 42 | Behavior on width { NumberAnimation { } } 43 | Behavior on height { NumberAnimation { } } 44 | 45 | states: [ 46 | State { 47 | name: "State1" 48 | 49 | PropertyChanges { 50 | target: ogreitem 51 | width: ogre.width 52 | height: ogre.height 53 | } 54 | PropertyChanges { 55 | target: toolbar1 56 | x: 5 57 | y: -toolbar1.height - 6 58 | } 59 | 60 | PropertyChanges { 61 | target: toolbar4 62 | anchors.top: ogreitem.top 63 | anchors.topMargin: 5 64 | } 65 | PropertyChanges { 66 | target: toolbar3 67 | anchors.top: ogreitem.top 68 | anchors.topMargin: 5 69 | } 70 | PropertyChanges { 71 | target: back 72 | opacity: 0 73 | } 74 | } 75 | ] 76 | 77 | MouseArea { 78 | anchors.fill: parent 79 | acceptedButtons: Qt.LeftButton | Qt.RightButton 80 | 81 | property int prevX: -1 82 | property int prevY: -1 83 | 84 | onPositionChanged: { 85 | if (pressedButtons & Qt.LeftButton) { 86 | if (prevX > -1) 87 | ogreitem.camera.yaw -= (mouse.x - prevX) / 2 88 | if (prevY > -1) 89 | ogreitem.camera.pitch -= (mouse.y - prevY) / 2 90 | prevX = mouse.x 91 | prevY = mouse.y 92 | } 93 | if (pressedButtons & Qt.RightButton) { 94 | if (prevY > -1) 95 | ogreitem.camera.zoom = Math.min(6, Math.max(0.1, ogreitem.camera.zoom - (mouse.y - prevY) / 100)); 96 | prevY = mouse.y 97 | } 98 | } 99 | onReleased: { prevX = -1; prevY = -1 } 100 | } 101 | } 102 | 103 | Rectangle { 104 | id: toolbar1 105 | x: 200 106 | y: 200 107 | width: 25 108 | height: 25 109 | radius: 5 110 | Behavior on x { NumberAnimation { } } 111 | Behavior on y { NumberAnimation { } } 112 | 113 | gradient: Gradient { 114 | GradientStop { 115 | position: 0 116 | color: "#c83e3e3e" 117 | } 118 | 119 | GradientStop { 120 | position: 1 121 | color: "#c8919191" 122 | } 123 | } 124 | 125 | border.width: 2 126 | border.color: "#1a1a1a" 127 | 128 | Image { 129 | anchors.rightMargin: 5 130 | anchors.leftMargin: 5 131 | anchors.bottomMargin: 5 132 | anchors.topMargin: 5 133 | anchors.fill: parent 134 | smooth: true 135 | fillMode: "Stretch" 136 | source: "qrc:/images/move.gif" 137 | } 138 | 139 | MouseArea { 140 | anchors.fill: parent 141 | drag.target: toolbar1 142 | drag.axis: "XandYAxis" 143 | drag.minimumX: 0 144 | drag.minimumY: 0 145 | drag.maximumX: ogre.width - toolbar1.width 146 | drag.maximumY: ogre.height - toolbar1.height 147 | } 148 | } 149 | 150 | Rectangle { 151 | id: toolbar2 152 | width: 25 153 | radius: 5 154 | gradient: Gradient { 155 | GradientStop { 156 | position: 0 157 | color: "#c83e3e3e" 158 | } 159 | 160 | GradientStop { 161 | position: 1 162 | color: "#c8919191" 163 | } 164 | } 165 | anchors.left: toolbar1.right 166 | anchors.leftMargin: 6 167 | anchors.top: toolbar1.top 168 | anchors.bottom: toolbar1.bottom 169 | border.color: "#1a1a1a" 170 | 171 | MouseArea { 172 | anchors.fill: parent 173 | 174 | onClicked: ogreitem.opacity = ogreitem.opacity == 1 ? 0 : 1 175 | } 176 | 177 | Rectangle { 178 | id: toolbar22 179 | x: 0 180 | y: -2 181 | radius: 12 182 | gradient: Gradient { 183 | GradientStop { 184 | position: 0 185 | color: "#5a5a5a" 186 | } 187 | 188 | GradientStop { 189 | position: 1 190 | color: "#000000" 191 | } 192 | } 193 | rotation: -35 194 | anchors.rightMargin: 6 195 | anchors.bottomMargin: 6 196 | anchors.leftMargin: 6 197 | anchors.topMargin: 6 198 | anchors.fill: parent 199 | } 200 | border.width: 2 201 | } 202 | 203 | Rectangle { 204 | id: toolbar4 205 | width: 25 206 | height: 25 207 | radius: 5 208 | gradient: Gradient { 209 | GradientStop { 210 | position: 0 211 | color: "#c83e3e3e" 212 | } 213 | 214 | GradientStop { 215 | position: 1 216 | color: "#c8919191" 217 | } 218 | } 219 | anchors.top: toolbar1.top 220 | anchors.right: toolbar3.left 221 | anchors.rightMargin: 6 222 | border.color: "#1a1a1a" 223 | 224 | MouseArea { 225 | anchors.fill: parent 226 | onClicked: { ogreitem.smooth = !ogreitem.smooth } 227 | } 228 | 229 | Text { 230 | anchors.fill: parent 231 | text: "AA" 232 | font.bold: true 233 | font.pixelSize: parent.height * 0.55 234 | verticalAlignment: Text.AlignVCenter 235 | horizontalAlignment: Text.AlignHCenter 236 | 237 | Rectangle { 238 | height: parent.height 239 | width: 2 240 | anchors.centerIn: parent 241 | color: "#BB1111" 242 | rotation: 40 243 | visible: !ogreitem.smooth 244 | } 245 | } 246 | border.width: 2 247 | } 248 | 249 | Rectangle { 250 | id: toolbar3 251 | width: 25 252 | height: 25 253 | radius: 5 254 | gradient: Gradient { 255 | GradientStop { 256 | position: 0 257 | color: "#c83e3e3e" 258 | } 259 | 260 | GradientStop { 261 | position: 1 262 | color: "#c8919191" 263 | } 264 | } 265 | anchors.top: toolbar1.top 266 | anchors.right: ogreitem.right 267 | anchors.rightMargin: 5 268 | border.color: "#1a1a1a" 269 | 270 | MouseArea { 271 | anchors.fill: parent 272 | onClicked: { ogreitem.state = ogreitem.state == '' ? 'State1' : '' } 273 | } 274 | 275 | Rectangle { 276 | id: toolbar31 277 | color: "#28ffffff" 278 | radius: 2 279 | border.width: 2 280 | border.color: "#000000" 281 | anchors.rightMargin: 7 282 | anchors.leftMargin: 7 283 | anchors.topMargin: 7 284 | anchors.bottomMargin: 7 285 | anchors.fill: parent 286 | 287 | Rectangle { 288 | id: toolbar311 289 | height: 3 290 | color: "#000000" 291 | anchors.right: parent.right 292 | anchors.left: parent.left 293 | anchors.top: parent.top 294 | } 295 | } 296 | border.width: 2 297 | } 298 | 299 | Item { 300 | id: camerawrapper 301 | property real yaw: 0 302 | property real pitch: 0 303 | property real zoom: 1 304 | 305 | onYawChanged: ogreitem.camera.yaw = yaw 306 | onPitchChanged: ogreitem.camera.pitch = pitch 307 | onZoomChanged: ogreitem.camera.zoom = zoom 308 | 309 | Behavior on yaw { NumberAnimation{ } } 310 | Behavior on pitch { NumberAnimation{ } } 311 | Behavior on zoom { NumberAnimation{ } } 312 | } 313 | 314 | Rectangle { 315 | id: rectangle1 316 | width: 139 317 | height: 208 318 | radius: 15 319 | gradient: Gradient { 320 | GradientStop { 321 | position: 0 322 | color: "#6f6f6f" 323 | } 324 | 325 | GradientStop { 326 | position: 0.24 327 | color: "#141414" 328 | } 329 | 330 | GradientStop { 331 | position: 1 332 | color: "#50000000" 333 | } 334 | } 335 | anchors.left: rectangle2.left 336 | anchors.leftMargin: -5 337 | anchors.top: rectangle2.bottom 338 | anchors.topMargin: 6 339 | border.width: 4 340 | border.color: "#1a1a1a" 341 | clip: false 342 | 343 | Behavior on opacity { PropertyAnimation { } } 344 | 345 | Image { 346 | id: image1 347 | width: 135 348 | height: 31 349 | anchors.top: parent.top 350 | anchors.topMargin: 9 351 | anchors.right: parent.right 352 | anchors.rightMargin: 0 353 | anchors.left: parent.left 354 | anchors.leftMargin: 0 355 | fillMode: "PreserveAspectFit" 356 | smooth: true 357 | source: "qrc:/images/qt-logo.png" 358 | } 359 | 360 | Item { 361 | id: rectangle3 362 | x: 89 363 | y: 95 364 | width: 30 365 | height: 30 366 | anchors.horizontalCenterOffset: 35 367 | anchors.centerIn: image7 368 | 369 | MouseArea { 370 | id: mouse_area1 371 | anchors.fill: parent 372 | 373 | onPressed: camerawrapper.yaw += 20 374 | } 375 | 376 | Image { 377 | id: image5 378 | rotation: -90 379 | smooth: true 380 | anchors.fill: parent 381 | source: "qrc:/images/arrow.png" 382 | } 383 | } 384 | 385 | Item { 386 | id: rectangle4 387 | x: 27 388 | y: 95 389 | width: 30 390 | height: 30 391 | anchors.horizontalCenterOffset: -35 392 | anchors.centerIn: image7 393 | MouseArea { 394 | id: mouse_area2 395 | anchors.fill: parent 396 | 397 | onPressed: camerawrapper.yaw -= 20 398 | } 399 | 400 | Image { 401 | id: image4 402 | rotation: 90 403 | smooth: true 404 | anchors.fill: parent 405 | source: "qrc:/images/arrow.png" 406 | } 407 | } 408 | 409 | Item { 410 | id: rectangle5 411 | y: 64 412 | width: 30 413 | height: 30 414 | anchors.verticalCenterOffset: -35 415 | anchors.centerIn: image7 416 | MouseArea { 417 | id: mouse_area3 418 | anchors.fill: parent 419 | 420 | onPressed: camerawrapper.pitch -= 20 421 | } 422 | 423 | Image { 424 | id: image3 425 | rotation: 180 426 | smooth: true 427 | anchors.fill: parent 428 | source: "qrc:/images/arrow.png" 429 | } 430 | } 431 | 432 | Item { 433 | id: rectangle6 434 | x: 58 435 | y: 124 436 | width: 30 437 | height: 30 438 | anchors.verticalCenterOffset: 35 439 | anchors.centerIn: image7 440 | anchors.horizontalCenterOffset: 0 441 | MouseArea { 442 | id: mouse_area4 443 | x: 0 444 | y: -1 445 | anchors.rightMargin: 0 446 | anchors.bottomMargin: 0 447 | anchors.leftMargin: 0 448 | anchors.topMargin: 0 449 | anchors.fill: parent 450 | 451 | onPressed: camerawrapper.pitch += 20 452 | } 453 | 454 | Image { 455 | id: image6 456 | smooth: true 457 | anchors.fill: parent 458 | source: "qrc:/images/arrow.png" 459 | } 460 | } 461 | 462 | Image { 463 | id: image7 464 | x: 84 465 | y: 0 466 | width: 24 467 | height: 24 468 | anchors.verticalCenterOffset: 9 469 | anchors.centerIn: parent 470 | smooth: true 471 | source: "qrc:/images/circle.png" 472 | 473 | MouseArea { 474 | id: mouse_area5 475 | x: 0 476 | y: -1 477 | anchors.fill: parent 478 | anchors.topMargin: 0 479 | anchors.rightMargin: 0 480 | anchors.bottomMargin: 0 481 | anchors.leftMargin: 0 482 | 483 | onClicked: { camerawrapper.yaw = 0; camerawrapper.pitch = 0 } 484 | } 485 | } 486 | 487 | Image { 488 | id: image8 489 | x: 20 490 | y: 182 491 | width: 30 492 | height: 30 493 | anchors.bottomMargin: 9 494 | anchors.bottom: parent.bottom 495 | anchors.horizontalCenterOffset: 14 496 | anchors.horizontalCenter: rectangle4.horizontalCenter 497 | smooth: true 498 | source: "qrc:/images/minus.png" 499 | 500 | MouseArea { 501 | id: mouse_area6 502 | x: 0 503 | y: -1 504 | anchors.fill: parent 505 | anchors.topMargin: 0 506 | anchors.rightMargin: 0 507 | anchors.bottomMargin: 0 508 | anchors.leftMargin: 0 509 | 510 | onPressed: camerawrapper.zoom /= 1.3 511 | } 512 | } 513 | 514 | Image { 515 | id: image9 516 | width: 30 517 | height: 30 518 | anchors.horizontalCenterOffset: -14 519 | anchors.bottom: parent.bottom 520 | anchors.bottomMargin: 9 521 | anchors.horizontalCenter: rectangle3.horizontalCenter 522 | smooth: true 523 | source: "qrc:/images/plus.png" 524 | 525 | MouseArea { 526 | id: mouse_area7 527 | x: 0 528 | y: 0 529 | anchors.fill: parent 530 | anchors.topMargin: 0 531 | anchors.rightMargin: 0 532 | anchors.bottomMargin: 0 533 | anchors.leftMargin: 0 534 | 535 | onPressed: camerawrapper.zoom *= 1.3 536 | } 537 | } 538 | } 539 | 540 | Rectangle { 541 | id: rectangle2 542 | x: 31 543 | y: 269 544 | width: 25 545 | height: 25 546 | radius: 5 547 | gradient: Gradient { 548 | GradientStop { 549 | position: 0 550 | color: "#c83e3e3e" 551 | } 552 | 553 | GradientStop { 554 | position: 1 555 | color: "#c8919191" 556 | } 557 | } 558 | 559 | border.width: 2 560 | border.color: "#1a1a1a" 561 | 562 | Image { 563 | id: image2 564 | anchors.rightMargin: 5 565 | anchors.leftMargin: 5 566 | anchors.bottomMargin: 5 567 | anchors.topMargin: 5 568 | anchors.fill: parent 569 | smooth: true 570 | fillMode: "Stretch" 571 | source: "qrc:/images/move.gif" 572 | } 573 | 574 | MouseArea { 575 | anchors.fill: parent 576 | drag.target: rectangle2 577 | drag.axis: "XandYAxis" 578 | drag.minimumX: 0 579 | drag.minimumY: 0 580 | drag.maximumX: ogre.width - rectangle2.width 581 | drag.maximumY: ogre.height - rectangle2.height 582 | } 583 | } 584 | 585 | Rectangle { 586 | id: rectangle10 587 | width: 25 588 | radius: 5 589 | gradient: Gradient { 590 | GradientStop { 591 | position: 0 592 | color: "#c83e3e3e" 593 | } 594 | 595 | GradientStop { 596 | position: 1 597 | color: "#c8919191" 598 | } 599 | } 600 | anchors.left: rectangle2.right 601 | anchors.leftMargin: 6 602 | anchors.top: rectangle2.top 603 | anchors.bottom: rectangle2.bottom 604 | border.color: "#1a1a1a" 605 | 606 | MouseArea { 607 | anchors.fill: parent 608 | drag.minimumY: 0 609 | drag.axis: "XandYAxis" 610 | drag.minimumX: 0 611 | drag.target: rectangle10 612 | drag.maximumY: ogre.height - rectangle10.height 613 | drag.maximumX: ogre.width - rectangle10.width 614 | 615 | onClicked: ogre.state = ogre.state == '' ? 'State1' : '' 616 | } 617 | 618 | Rectangle { 619 | id: rectangle11 620 | x: 0 621 | y: -2 622 | radius: 12 623 | gradient: Gradient { 624 | GradientStop { 625 | position: 0 626 | color: "#5a5a5a" 627 | } 628 | 629 | GradientStop { 630 | position: 1 631 | color: "#000000" 632 | } 633 | } 634 | rotation: -35 635 | anchors.rightMargin: 6 636 | anchors.bottomMargin: 6 637 | anchors.leftMargin: 6 638 | anchors.topMargin: 6 639 | anchors.fill: parent 640 | } 641 | border.width: 2 642 | } 643 | 644 | Rectangle { 645 | id: rectangle12 646 | width: 25 647 | height: 25 648 | radius: 5 649 | gradient: Gradient { 650 | GradientStop { 651 | position: 0 652 | color: "#c83e3e3e" 653 | } 654 | 655 | GradientStop { 656 | position: 1 657 | color: "#c8919191" 658 | } 659 | } 660 | anchors.top: rectangle2.top 661 | anchors.right: rectangle1.right 662 | anchors.rightMargin: 5 663 | border.color: "#1a1a1a" 664 | 665 | MouseArea { 666 | property bool fullscreen: false 667 | anchors.fill: parent 668 | onClicked: { 669 | if (fullscreen) 670 | Window.showNormal(); 671 | else 672 | Window.showFullScreen(); 673 | fullscreen = !fullscreen; 674 | } 675 | } 676 | 677 | Rectangle { 678 | id: rectangle13 679 | color: "#28ffffff" 680 | radius: 2 681 | border.width: 2 682 | border.color: "#000000" 683 | anchors.rightMargin: 7 684 | anchors.leftMargin: 7 685 | anchors.topMargin: 7 686 | anchors.bottomMargin: 7 687 | anchors.fill: parent 688 | 689 | Rectangle { 690 | id: rectangle14 691 | height: 3 692 | color: "#000000" 693 | anchors.right: parent.right 694 | anchors.left: parent.left 695 | anchors.top: parent.top 696 | } 697 | } 698 | border.width: 2 699 | } 700 | states: [ 701 | State { 702 | name: "State1" 703 | 704 | PropertyChanges { 705 | target: rectangle1 706 | opacity: 0 707 | } 708 | } 709 | ] 710 | } 711 | -------------------------------------------------------------------------------- /example/resources/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advancingu/QmlOgre/cad4d3a62af4ec70541f90269761ec17a9cfb71c/example/resources/minus.png -------------------------------------------------------------------------------- /example/resources/move.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advancingu/QmlOgre/cad4d3a62af4ec70541f90269761ec17a9cfb71c/example/resources/move.gif -------------------------------------------------------------------------------- /example/resources/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advancingu/QmlOgre/cad4d3a62af4ec70541f90269761ec17a9cfb71c/example/resources/plus.png -------------------------------------------------------------------------------- /example/resources/qt-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advancingu/QmlOgre/cad4d3a62af4ec70541f90269761ec17a9cfb71c/example/resources/qt-logo.png -------------------------------------------------------------------------------- /example/resources/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | example.qml 4 | 5 | 6 | arrow.png 7 | circle.png 8 | GrassandSky.png 9 | minus.png 10 | move.gif 11 | plus.png 12 | qt-logo.png 13 | 14 | 15 | -------------------------------------------------------------------------------- /lib/lib.pro: -------------------------------------------------------------------------------- 1 | CONFIG += qt 2 | QT += qml quick 3 | TEMPLATE = lib 4 | TARGET = qmlogre 5 | 6 | macx { 7 | OGREDIR = $$(OGRE_HOME) 8 | isEmpty(OGREDIR) { 9 | error(QmlOgre needs Ogre to be built. Please set the environment variable OGRE_HOME pointing to your Ogre root directory.) 10 | } else { 11 | message(Using Ogre libraries in $$OGREDIR) 12 | INCLUDEPATH += $$OGREDIR/include/OGRE 13 | INCLUDEPATH += $$OGREDIR/include/OGRE/RenderSystems/GL 14 | QMAKE_LFLAGS += -F$$OGREDIR/lib/release 15 | LIBS += -framework Ogre 16 | 17 | BOOSTDIR = $$OGREDIR/boost_1_42 18 | !isEmpty(BOOSTDIR) { 19 | INCLUDEPATH += $$BOOSTDIR 20 | # LIBS += -L$$BOOSTDIR/lib -lboost_date_time-xgcc40-mt-1_42 -lboost_thread-xgcc40-mt-1_42 21 | } 22 | } 23 | } else:unix { 24 | CONFIG += link_pkgconfig 25 | PKGCONFIG += OGRE 26 | } else:win32 { 27 | OGREDIR = $$(OGRE_HOME) 28 | isEmpty(OGREDIR) { 29 | error(QmlOgre needs Ogre to be built. Please set the environment variable OGRE_HOME pointing to your Ogre root directory.) 30 | } else { 31 | message(Using Ogre libraries in $$OGREDIR) 32 | INCLUDEPATH += $$OGREDIR/include/OGRE 33 | INCLUDEPATH += $$OGREDIR/include/OGRE/RenderSystems/GL 34 | CONFIG(release, debug|release) { 35 | LIBS += -L$$OGREDIR/lib/release -L$$OGREDIR/lib/release/opt -lOgreMain -lRenderSystem_GL 36 | } else { 37 | LIBS += -L$$OGREDIR/lib/debug -L$$OGREDIR/lib/debug/opt -lOgreMain_d -lRenderSystem_GL_d 38 | } 39 | 40 | BOOSTDIR = $$OGREDIR/boost_1_42 41 | !isEmpty(BOOSTDIR) { 42 | INCLUDEPATH += $$BOOSTDIR 43 | CONFIG(release, debug|release) { 44 | LIBS += -L$$BOOSTDIR/lib -llibboost_date_time-vc90-mt-1_42 -llibboost_thread-vc90-mt-1_42 45 | } else { 46 | LIBS += -L$$BOOSTDIR/lib -llibboost_date_time-vc90-mt-gd-1_42 -llibboost_thread-vc90-mt-gd-1_42 47 | } 48 | } 49 | } 50 | } 51 | 52 | UI_DIR = ./.ui 53 | OBJECTS_DIR = ./.obj 54 | MOC_DIR = ./.moc 55 | 56 | 57 | SOURCES += ogreitem.cpp \ 58 | ogrenode.cpp \ 59 | ogrecamerawrapper.cpp \ 60 | ogreengine.cpp 61 | 62 | HEADERS += \ 63 | ogreitem.h \ 64 | ogrenode.h \ 65 | ogrecamerawrapper.h \ 66 | ogreengine.h 67 | 68 | # Copy all headers to build folder 69 | Headers.path = $$OUT_PWD/include 70 | Headers.files = $$files(*.h) 71 | INSTALLS += Headers 72 | -------------------------------------------------------------------------------- /lib/ogrecamerawrapper.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #include "ogrecamerawrapper.h" 11 | 12 | OgreCameraWrapper::OgreCameraWrapper() 13 | { 14 | } 15 | -------------------------------------------------------------------------------- /lib/ogrecamerawrapper.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #ifndef OGRECAMERAWRAPPER_H 11 | #define OGRECAMERAWRAPPER_H 12 | 13 | #include 14 | 15 | /** 16 | * @brief The OgreCameraWrapper class defines an interface 17 | * that allows assigning Ogre::Camera instances to OgreItem 18 | * via QML. 19 | * 20 | * Implementing classes must inherit from QObject. 21 | */ 22 | class OgreCameraWrapper 23 | { 24 | public: 25 | OgreCameraWrapper(); 26 | virtual ~OgreCameraWrapper() {} 27 | virtual Ogre::Camera* camera() const = 0; 28 | }; 29 | 30 | #endif // OGRECAMERAWRAPPER_H 31 | -------------------------------------------------------------------------------- /lib/ogreengine.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #include "ogreengine.h" 11 | #include "ogreitem.h" 12 | 13 | #include 14 | 15 | OgreEngine::OgreEngine(QQuickWindow *window) 16 | : QObject(), 17 | m_resources_cfg(Ogre::StringUtil::BLANK) 18 | { 19 | qmlRegisterType("Ogre", 1, 0, "OgreItem"); 20 | qmlRegisterType("OgreEngine", 1, 0, "OgreEngine"); 21 | 22 | setQuickWindow(window); 23 | } 24 | 25 | OgreEngine::~OgreEngine() 26 | { 27 | delete m_ogreContext; 28 | } 29 | 30 | Ogre::Root* OgreEngine::startEngine() 31 | { 32 | m_resources_cfg = "resources.cfg"; 33 | 34 | activateOgreContext(); 35 | 36 | Ogre::Root *ogreRoot = new Ogre::Root; 37 | Ogre::RenderSystem *renderSystem = ogreRoot->getRenderSystemByName("OpenGL Rendering Subsystem"); 38 | ogreRoot->setRenderSystem(renderSystem); 39 | ogreRoot->initialise(false); 40 | 41 | Ogre::NameValuePairList params; 42 | 43 | params["externalGLControl"] = "true"; 44 | params["currentGLContext"] = "true"; 45 | 46 | //Finally create our window. 47 | m_ogreWindow = ogreRoot->createRenderWindow("OgreWindow", 1, 1, false, ¶ms); 48 | m_ogreWindow->setVisible(false); 49 | m_ogreWindow->update(false); 50 | 51 | doneOgreContext(); 52 | 53 | return ogreRoot; 54 | } 55 | 56 | void OgreEngine::stopEngine(Ogre::Root *ogreRoot) 57 | { 58 | if (ogreRoot) { 59 | // m_root->detachRenderTarget(m_renderTexture); 60 | // TODO tell node(s) to detach 61 | 62 | } 63 | 64 | delete ogreRoot; 65 | } 66 | 67 | void OgreEngine::setQuickWindow(QQuickWindow *window) 68 | { 69 | Q_ASSERT(window); 70 | 71 | m_quickWindow = window; 72 | m_qtContext = QOpenGLContext::currentContext(); 73 | 74 | // create a new shared OpenGL context to be used exclusively by Ogre 75 | m_ogreContext = new QOpenGLContext(); 76 | m_ogreContext->setFormat(m_quickWindow->requestedFormat()); 77 | m_ogreContext->setShareContext(m_qtContext); 78 | m_ogreContext->create(); 79 | } 80 | 81 | void OgreEngine::activateOgreContext() 82 | { 83 | glPopAttrib(); 84 | glPopClientAttrib(); 85 | 86 | m_qtContext->functions()->glUseProgram(0); 87 | m_qtContext->doneCurrent(); 88 | 89 | m_ogreContext->makeCurrent(m_quickWindow); 90 | } 91 | 92 | void OgreEngine::doneOgreContext() 93 | { 94 | m_ogreContext->functions()->glBindBuffer(GL_ARRAY_BUFFER, 0); 95 | m_ogreContext->functions()->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 96 | m_ogreContext->functions()->glBindRenderbuffer(GL_RENDERBUFFER, 0); 97 | m_ogreContext->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); 98 | 99 | // unbind all possible remaining buffers; just to be on safe side 100 | m_ogreContext->functions()->glBindBuffer(GL_ARRAY_BUFFER, 0); 101 | m_ogreContext->functions()->glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0); 102 | m_ogreContext->functions()->glBindBuffer(GL_COPY_READ_BUFFER, 0); 103 | m_ogreContext->functions()->glBindBuffer(GL_COPY_WRITE_BUFFER, 0); 104 | m_ogreContext->functions()->glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); 105 | // m_ogreContext->functions()->glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0); 106 | m_ogreContext->functions()->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 107 | m_ogreContext->functions()->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); 108 | m_ogreContext->functions()->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 109 | // m_ogreContext->functions()->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); 110 | m_ogreContext->functions()->glBindBuffer(GL_TEXTURE_BUFFER, 0); 111 | m_ogreContext->functions()->glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 112 | m_ogreContext->functions()->glBindBuffer(GL_UNIFORM_BUFFER, 0); 113 | 114 | m_ogreContext->doneCurrent(); 115 | 116 | m_qtContext->makeCurrent(m_quickWindow); 117 | glPushAttrib(GL_ALL_ATTRIB_BITS); 118 | glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); 119 | } 120 | 121 | QOpenGLContext* OgreEngine::ogreContext() const 122 | { 123 | return m_ogreContext; 124 | } 125 | 126 | QSGTexture* OgreEngine::createTextureFromId(uint id, const QSize &size, QQuickWindow::CreateTextureOptions options) const 127 | { 128 | return m_quickWindow->createTextureFromId(id, size, options); 129 | } 130 | 131 | void OgreEngine::setupResources(void) 132 | { 133 | // Load resource paths from config file 134 | Ogre::ConfigFile cf; 135 | cf.load(m_resources_cfg); 136 | 137 | // Go through all sections & settings in the file 138 | Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator(); 139 | 140 | Ogre::String secName, typeName, archName; 141 | while (seci.hasMoreElements()) 142 | { 143 | secName = seci.peekNextKey(); 144 | Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext(); 145 | Ogre::ConfigFile::SettingsMultiMap::iterator i; 146 | for (i = settings->begin(); i != settings->end(); ++i) 147 | { 148 | typeName = i->first; 149 | archName = i->second; 150 | 151 | Ogre::ResourceGroupManager::getSingleton().addResourceLocation( 152 | archName, typeName, secName); 153 | } 154 | } 155 | 156 | Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); 157 | } 158 | -------------------------------------------------------------------------------- /lib/ogreengine.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #ifndef OGREENGINEITEM_H 11 | #define OGREENGINEITEM_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace Ogre { 19 | class Root; 20 | class RenderTexture; 21 | class Viewport; 22 | class RenderTarget; 23 | } 24 | 25 | /** 26 | * @brief The OgreEngineItem class 27 | * Must only be constructed from within Qt QML rendering thread. 28 | */ 29 | class OgreEngine : public QObject 30 | { 31 | Q_OBJECT 32 | 33 | public: 34 | OgreEngine(QQuickWindow *window = 0); 35 | ~OgreEngine(); 36 | Ogre::Root *startEngine(); 37 | void stopEngine(Ogre::Root *ogreRoot); 38 | 39 | void activateOgreContext(); 40 | void doneOgreContext(); 41 | 42 | QOpenGLContext* ogreContext() const; 43 | 44 | QSGTexture* createTextureFromId(uint id, const QSize &size, QQuickWindow::CreateTextureOptions options = QQuickWindow::CreateTextureOption(0)) const; 45 | 46 | void setupResources(void); 47 | 48 | private: 49 | Ogre::String m_resources_cfg; 50 | Ogre::RenderWindow *m_ogreWindow; 51 | 52 | QQuickWindow *m_quickWindow; 53 | 54 | /** Pointer to QOpenGLContext to be used by Ogre. */ 55 | QOpenGLContext* m_ogreContext; 56 | /** Pointer to QOpenGLContext to be restored after Ogre context. */ 57 | QOpenGLContext* m_qtContext; 58 | 59 | protected: 60 | void setQuickWindow(QQuickWindow *window); 61 | }; 62 | 63 | #endif // OGREENGINEITEM_H 64 | -------------------------------------------------------------------------------- /lib/ogreitem.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #include "ogreitem.h" 11 | #include "ogrenode.h" 12 | 13 | OgreItem::OgreItem(QQuickItem *parent) 14 | : QQuickItem(parent) 15 | , m_timerID(0) 16 | , m_camera(0) 17 | , m_ogreEngineItem(0) 18 | { 19 | setFlag(ItemHasContents); 20 | setSmooth(false); 21 | 22 | startTimer(16); 23 | } 24 | 25 | QSGNode *OgreItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) 26 | { 27 | if (width() <= 0 || height() <= 0 || !m_camera || !m_camera->camera() || !m_ogreEngineItem) { 28 | delete oldNode; 29 | return 0; 30 | } 31 | 32 | OgreNode *node = static_cast(oldNode); 33 | if (!node) 34 | { 35 | node = new OgreNode(); 36 | node->setOgreEngineItem(m_ogreEngineItem); 37 | node->setCamera(m_camera->camera()); 38 | } 39 | 40 | node->setSize(QSize(width(), height())); 41 | node->update(); 42 | // mark texture dirty, otherwise Qt will not trigger a redraw (preprocess()) 43 | node->markDirty(QSGNode::DirtyMaterial); 44 | 45 | return node; 46 | } 47 | 48 | void OgreItem::timerEvent(QTimerEvent *) 49 | { 50 | update(); 51 | } 52 | 53 | void OgreItem::setCamera(QObject *camera) 54 | { 55 | m_camera = dynamic_cast(camera); 56 | } 57 | 58 | void OgreItem::setOgreEngine(OgreEngine *ogreEngine) 59 | { 60 | m_ogreEngineItem = ogreEngine; 61 | } 62 | -------------------------------------------------------------------------------- /lib/ogreitem.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #ifndef OGREITEM_H 11 | #define OGREITEM_H 12 | 13 | #include "ogreengine.h" 14 | #include "ogrecamerawrapper.h" 15 | 16 | #include 17 | #include 18 | 19 | class OgreItem : public QQuickItem 20 | { 21 | Q_OBJECT 22 | 23 | Q_PROPERTY(QObject *camera READ camera WRITE setCamera) 24 | Q_PROPERTY(OgreEngine *ogreEngine READ ogreEngine WRITE setOgreEngine) 25 | 26 | public: 27 | OgreItem(QQuickItem *parent = 0); 28 | 29 | QObject *camera() const { return dynamic_cast(m_camera); } 30 | void setCamera(QObject *camera); 31 | 32 | OgreEngine *ogreEngine() const { return m_ogreEngineItem; } 33 | void setOgreEngine(OgreEngine *ogreEngine); 34 | 35 | protected: 36 | virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); 37 | 38 | void timerEvent(QTimerEvent *); 39 | 40 | private: 41 | int m_timerID; 42 | 43 | OgreCameraWrapper *m_camera; 44 | OgreEngine *m_ogreEngineItem; 45 | }; 46 | 47 | #endif // OGREITEM_H 48 | -------------------------------------------------------------------------------- /lib/ogrenode.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "ogrenode.h" 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | OgreNode::OgreNode() 25 | : QSGGeometryNode() 26 | , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) 27 | , m_texture(0) 28 | , m_ogreEngineItem(0) 29 | , m_camera(0) 30 | , m_renderTarget(0) 31 | , m_viewport(0) 32 | , m_window(0) 33 | , m_ogreFboId(0) 34 | , m_dirtyFBO(false) 35 | { 36 | setMaterial(&m_material); 37 | setOpaqueMaterial(&m_materialO); 38 | setGeometry(&m_geometry); 39 | setFlag(UsePreprocess); 40 | } 41 | 42 | OgreNode::~OgreNode() 43 | { 44 | if (m_renderTarget) { 45 | m_renderTarget->removeAllViewports(); 46 | } 47 | 48 | if (Ogre::Root::getSingletonPtr()) { 49 | Ogre::Root::getSingletonPtr()->detachRenderTarget(m_renderTarget); 50 | } 51 | } 52 | 53 | void OgreNode::setOgreEngineItem(OgreEngine *ogreRootItem) 54 | { 55 | m_ogreEngineItem = ogreRootItem; 56 | } 57 | 58 | void OgreNode::doneOgreContext() 59 | { 60 | if (m_ogreFboId != 0) 61 | { 62 | Ogre::GLFrameBufferObject *ogreFbo = NULL; 63 | m_renderTarget->getCustomAttribute("FBO", &ogreFbo); 64 | Ogre::GLFBOManager *manager = ogreFbo->getManager(); 65 | manager->unbind(m_renderTarget); 66 | } 67 | 68 | m_ogreEngineItem->doneOgreContext(); 69 | } 70 | 71 | void OgreNode::activateOgreContext() 72 | { 73 | m_ogreEngineItem->activateOgreContext(); 74 | m_ogreEngineItem->ogreContext()->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_ogreFboId); 75 | } 76 | 77 | GLuint OgreNode::getOgreFboId() 78 | { 79 | if (!m_renderTarget) 80 | return 0; 81 | 82 | Ogre::GLFrameBufferObject *ogreFbo = 0; 83 | m_renderTarget->getCustomAttribute("FBO", &ogreFbo); 84 | Ogre::GLFBOManager *manager = ogreFbo->getManager(); 85 | manager->bind(m_renderTarget); 86 | 87 | GLint id; 88 | glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id); 89 | 90 | return id; 91 | } 92 | 93 | void OgreNode::preprocess() 94 | { 95 | activateOgreContext(); 96 | m_renderTarget->update(true); 97 | doneOgreContext(); 98 | } 99 | 100 | void OgreNode::update() 101 | { 102 | if (m_dirtyFBO) { 103 | activateOgreContext(); 104 | updateFBO(); 105 | m_ogreFboId = getOgreFboId(); 106 | m_dirtyFBO = false; 107 | doneOgreContext(); 108 | } 109 | } 110 | 111 | void OgreNode::updateFBO() 112 | { 113 | if (m_renderTarget) 114 | Ogre::TextureManager::getSingleton().remove("RttTex"); 115 | 116 | int samples = m_ogreEngineItem->ogreContext()->format().samples(); 117 | m_rttTexture = Ogre::TextureManager::getSingleton().createManual("RttTex", 118 | Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 119 | Ogre::TEX_TYPE_2D, 120 | m_size.width(), 121 | m_size.height(), 122 | 0, 123 | Ogre::PF_R8G8B8A8, 124 | Ogre::TU_RENDERTARGET, 0, false, 125 | samples); 126 | 127 | m_renderTarget = m_rttTexture->getBuffer()->getRenderTarget(); 128 | 129 | m_renderTarget->addViewport(m_camera); 130 | m_renderTarget->getViewport(0)->setClearEveryFrame(true); 131 | m_renderTarget->getViewport(0)->setBackgroundColour(Ogre::ColourValue::Black); 132 | m_renderTarget->getViewport(0)->setOverlaysEnabled(false); 133 | 134 | Ogre::Real aspectRatio = Ogre::Real(m_size.width()) / Ogre::Real(m_size.height()); 135 | m_camera->setAspectRatio(aspectRatio); 136 | 137 | QSGGeometry::updateTexturedRectGeometry(&m_geometry, 138 | QRectF(0, 0, m_size.width(), m_size.height()), 139 | QRectF(0, 0, 1, 1)); 140 | 141 | Ogre::GLTexture *nativeTexture = static_cast(m_rttTexture.get()); 142 | 143 | delete m_texture; 144 | m_texture = m_ogreEngineItem->createTextureFromId(nativeTexture->getGLID(), m_size); 145 | 146 | m_material.setTexture(m_texture); 147 | m_materialO.setTexture(m_texture); 148 | } 149 | 150 | void OgreNode::setSize(const QSize &size) 151 | { 152 | if (size == m_size) 153 | return; 154 | 155 | m_size = size; 156 | m_dirtyFBO = true; 157 | markDirty(DirtyGeometry); 158 | } 159 | -------------------------------------------------------------------------------- /lib/ogrenode.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \copyright (c) Nokia Corporation and/or its subsidiary(-ies) (qt-info@nokia.com) and/or contributors 3 | * For the full copyright and license information, please view the LICENSE 4 | * file that was distributed with this source code. 5 | * 6 | * \license{This source file is part of QmlOgre abd subject to the BSD license that is bundled 7 | * with this source code in the file LICENSE.} 8 | */ 9 | 10 | #ifndef OGRENODE_H 11 | #define OGRENODE_H 12 | 13 | #include "Ogre.h" 14 | #include "ogreengine.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace Ogre { 21 | class Root; 22 | class Camera; 23 | class SceneManager; 24 | class RenderTexture; 25 | class Viewport; 26 | class RenderTarget; 27 | } 28 | 29 | class CameraNodeObject; 30 | 31 | class OgreNode : public QSGGeometryNode 32 | { 33 | public: 34 | OgreNode(); 35 | ~OgreNode(); 36 | 37 | void setSize(const QSize &size); 38 | QSize size() const { return m_size; } 39 | 40 | void update(); 41 | void updateFBO(); 42 | 43 | GLuint getOgreFboId(); 44 | 45 | void setOgreEngineItem(OgreEngine *ogreRootItem); 46 | void doneOgreContext(); 47 | void activateOgreContext(); 48 | 49 | void preprocess(); 50 | 51 | void setCamera(Ogre::Camera *camera) { m_camera = camera; } 52 | 53 | private: 54 | QSGTextureMaterial m_material; 55 | QSGOpaqueTextureMaterial m_materialO; 56 | QSGGeometry m_geometry; 57 | QSGTexture *m_texture; 58 | OgreEngine *m_ogreEngineItem; 59 | 60 | QSize m_size; 61 | 62 | Ogre::Camera *m_camera; 63 | Ogre::RenderTexture *m_renderTarget; 64 | Ogre::Viewport *m_viewport; 65 | Ogre::TexturePtr m_rttTexture; 66 | Ogre::RenderWindow *m_window; 67 | 68 | GLuint m_ogreFboId; 69 | 70 | bool m_dirtyFBO; 71 | }; 72 | 73 | #endif // OGRENODE_H 74 | -------------------------------------------------------------------------------- /qmlogre.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | SUBDIRS = lib \ 3 | example 4 | --------------------------------------------------------------------------------