├── .gitignore
├── README.md
├── fbo
├── fbo.pro
├── fbo.qrc
├── main.cpp
├── main.qml
├── myframebufferobject.cpp
└── myframebufferobject.h
├── integrating-qq2-with-opengl.pro
├── lgpl-3.0.txt
├── lib
├── CameraControls.qml
├── assets.qrc
├── assets
│ ├── phong.frag
│ ├── phong.vert
│ └── trefoil.obj
├── axisalignedboundingbox.cpp
├── axisalignedboundingbox.h
├── camera.cpp
├── camera.h
├── lib.pri
├── lib.pro
├── meshrenderer.cpp
├── meshrenderer.h
├── objloader.cpp
└── objloader.h
├── rendercontrol
├── main.cpp
├── main.qml
├── rendercontrol.pro
├── rendercontrol.qrc
├── renderwindow.cpp
└── renderwindow.h
└── underlay
├── main.cpp
├── main.qml
├── myquickview.cpp
├── myquickview.h
├── underlay.pro
└── underlay.qrc
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | *.a
3 | *.la
4 | *.core
5 | *.d
6 | *.dylib
7 | *.moc
8 | *.o
9 | *.obj
10 | *.orig
11 | *.swp
12 | *.rej
13 | *.so
14 | *.so.*
15 | *.pbxuser
16 | *.mode1
17 | *.mode1v3
18 | *_pch.h.cpp
19 | *_resource.rc
20 | .#*
21 | *.*#
22 | *_wrapper.sh
23 | *_wrapper.bat
24 | wrapper.sh
25 | wrapper.bat
26 | core
27 | .qmake.cache
28 | .qmake.vars
29 | .device.vars
30 | *.prl
31 | tags
32 | .DS_Store
33 | *.debug
34 | Makefile*
35 | !qmake/Makefile.win32*
36 | !qmake/Makefile.unix
37 | *.prl
38 | *.app
39 | *.pro.user*
40 | *.qmlproject.user*
41 | *.gcov
42 | *.gcda
43 | *.gcno
44 | moc_*.cpp
45 | ui_*.h
46 | qrc_*.cpp
47 | *.Debug
48 | *.Release
49 | *.ib_pdb_index
50 | *.idb
51 | *.ilk
52 | *.pdb
53 | *.sln
54 | *.suo
55 | *.vcproj
56 | *vcproj.*.*.user
57 | *.ncb
58 | *.vcxproj
59 | *.vcxproj.filters
60 | *.vcxproj.user
61 | *.exe.embed.manifest
62 | *.exe_manifest.rc
63 | *.exe_manifest.res
64 | .DS_Store
65 | .pch
66 | .rcc
67 | *.app
68 | *.autosave
69 | *.qmlproject.user
70 | *.qmlproject.user.*
71 | CMakeLists.txt.user
72 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Integrating Qt Quick 2 with OpenGL
2 |
3 | This is the code for Giuseppe D'Angelo's talk at the Qt World Summit 2015,
4 | QtCon 2016, Qt World Summit 2017.
5 |
6 | * Slides: http://www.kdab.com/kdab-at-qt-world-summit/ https://conf.qtcon.org/system/attachments/99/original/integrating-opengl-qq2.pdf%3F1473007100
7 | * Video: https://www.youtube.com/watch?v=D-7fVGIBz6k https://www.youtube.com/watch?v=V_idc9BBRuI
8 | * Blog posts: http://www.kdab.com/integrating-opengl-with-qt-quick-2-applications-part-1/
9 |
10 |
11 | ```
12 | Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
13 | Author: Giuseppe D'Angelo
14 | Contact: info@kdab.com
15 |
16 | This program is free software: you can redistribute it and/or modify
17 | it under the terms of the GNU Lesser General Public License as published by
18 | the Free Software Foundation, either version 3 of the License, or
19 | (at your option) any later version.
20 |
21 | This program is distributed in the hope that it will be useful,
22 | but WITHOUT ANY WARRANTY; without even the implied warranty of
23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 | GNU Lesser General Public License for more details.
25 |
26 | You should have received a copy of the GNU Lesser General Public License
27 | along with this program. If not, see .
28 | ```
29 |
30 |
--------------------------------------------------------------------------------
/fbo/fbo.pro:
--------------------------------------------------------------------------------
1 | include(../lib/lib.pri)
2 |
3 | TEMPLATE = app
4 | TARGET = fbo
5 |
6 | QT += quick
7 |
8 | SOURCES += \
9 | main.cpp \
10 | myframebufferobject.cpp
11 |
12 | HEADERS += \
13 | myframebufferobject.h
14 |
15 | RESOURCES += \
16 | fbo.qrc
17 |
18 |
19 |
--------------------------------------------------------------------------------
/fbo/fbo.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | main.qml
4 |
5 |
6 |
--------------------------------------------------------------------------------
/fbo/main.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include "myframebufferobject.h"
28 |
29 | int main(int argc, char **argv)
30 | {
31 | QGuiApplication app(argc, argv);
32 |
33 | Q_INIT_RESOURCE(assets);
34 |
35 | QSurfaceFormat format;
36 | format.setMajorVersion(3);
37 | format.setMinorVersion(3);
38 | format.setProfile(QSurfaceFormat::CoreProfile);
39 | format.setDepthBufferSize(24);
40 | format.setStencilBufferSize(8);
41 | format.setSamples(4);
42 | QSurfaceFormat::setDefaultFormat(format);
43 |
44 | qmlRegisterType("MyRenderLibrary", 42, 0, "MeshRenderer");
45 |
46 | QQuickView view;
47 | view.setResizeMode(QQuickView::SizeRootObjectToView);
48 | view.setSource(QUrl("qrc:///qml/main.qml"));
49 | view.resize(600, 600);
50 | view.show();
51 |
52 | return app.exec();
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/fbo/main.qml:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | import QtQuick 2.0
23 | import MyRenderLibrary 42.0
24 |
25 | Rectangle {
26 | id: root
27 | width: 600
28 | height: 600
29 |
30 | color: "lightblue"
31 |
32 | MeshRenderer {
33 | id: renderer
34 | width: 200
35 | height: 200
36 | smooth: true
37 |
38 | Text {
39 | text: "OpenGL in QtQuick!"
40 | anchors.top: parent.bottom
41 | anchors.horizontalCenter: parent.horizontalCenter
42 | }
43 |
44 | MouseArea {
45 | anchors.fill: parent
46 | onClicked: flashyThing.flash()
47 | }
48 |
49 | Rectangle {
50 | id: flashyThing
51 | anchors.fill: parent
52 | opacity: 0
53 |
54 | color: "yellow"
55 |
56 | Text {
57 | id: flashyThingText
58 | anchors.centerIn: parent
59 | text: "Clicked!"
60 | font.pointSize: 40
61 | }
62 |
63 | function flash() {
64 | flashyAnimation.restart()
65 | }
66 |
67 | ParallelAnimation {
68 | id: flashyAnimation
69 |
70 | NumberAnimation {
71 | target: flashyThingText
72 | properties: "font.pointSize"
73 | from: 20
74 | to: 60
75 | duration: 2000
76 | easing.type: Easing.OutCubic
77 | }
78 |
79 | SequentialAnimation {
80 | PropertyAction {
81 | target: flashyThing
82 | properties: "opacity"
83 | value: 1
84 | }
85 |
86 | NumberAnimation {
87 | target: flashyThing
88 | properties: "opacity"
89 | to: 0
90 | easing.type: Easing.InCubic
91 | duration: 1500
92 | }
93 | }
94 | }
95 |
96 | }
97 | }
98 |
99 | CameraControls {
100 | camera: renderer
101 |
102 | anchors.bottom: root.bottom
103 | anchors.horizontalCenter: root.horizontalCenter
104 | }
105 |
106 | ParallelAnimation {
107 | loops: Animation.Infinite
108 | running: true
109 |
110 | SequentialAnimation {
111 | loops: Animation.Infinite
112 |
113 | NumberAnimation {
114 | target: renderer
115 | properties: "x"
116 | from: 50
117 | to: root.width - renderer.width
118 | duration: 4000
119 | }
120 | NumberAnimation {
121 | target: renderer
122 | properties: "x"
123 | from: root.width - renderer.width
124 | to: 0
125 | duration: 5000
126 | }
127 | NumberAnimation {
128 | target: renderer
129 | properties: "x"
130 | from: 0
131 | to: 50
132 | duration: 1000
133 | }
134 | }
135 |
136 | SequentialAnimation {
137 | loops: Animation.Infinite
138 | NumberAnimation {
139 | target: renderer
140 | properties: "y"
141 | from: 100
142 | to: 0
143 | duration: 1500
144 | }
145 |
146 | NumberAnimation {
147 | target: renderer
148 | properties: "y"
149 | from: 0
150 | to: root.height - renderer.height
151 | duration: 5000
152 | }
153 |
154 | NumberAnimation {
155 | target: renderer
156 | properties: "y"
157 | from: root.height - renderer.height
158 | to: 100
159 | duration: 4000
160 | }
161 |
162 | }
163 |
164 | SequentialAnimation {
165 | loops: Animation.Infinite
166 |
167 | PauseAnimation {
168 | duration: 10000
169 | }
170 |
171 | RotationAnimation {
172 | target: renderer
173 | properties: "rotation"
174 | from: 0
175 | to: 45
176 | duration: 500
177 | easing.type: Easing.OutBack
178 | }
179 |
180 | RotationAnimation {
181 | target: renderer
182 | properties: "rotation"
183 | to: -45
184 | duration: 1000
185 | easing.type: Easing.OutBack
186 | }
187 |
188 | RotationAnimation {
189 | target: renderer
190 | properties: "rotation"
191 | to: 0
192 | duration: 500
193 | easing.type: Easing.OutBack
194 | }
195 | }
196 |
197 | }
198 | }
199 |
200 |
--------------------------------------------------------------------------------
/fbo/myframebufferobject.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include "myframebufferobject.h"
23 |
24 | #include
25 |
26 | #include
27 | #include
28 | #include
29 |
30 | class MyFrameBufferObjectRenderer : public QQuickFramebufferObject::Renderer
31 | {
32 | public:
33 | MyFrameBufferObjectRenderer()
34 | {
35 |
36 | m_render.initialize();
37 | }
38 |
39 | void synchronize(QQuickFramebufferObject *item) Q_DECL_OVERRIDE
40 | {
41 | m_window = item->window();
42 |
43 | MyFrameBufferObject *i = static_cast(item);
44 | m_render.setAzimuth(i->azimuth());
45 | m_render.setElevation(i->elevation());
46 | m_render.setDistance(i->distance());
47 | }
48 |
49 | void render() Q_DECL_OVERRIDE
50 | {
51 | m_render.render();
52 | m_window->resetOpenGLState();
53 | }
54 |
55 | QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) Q_DECL_OVERRIDE
56 | {
57 | QOpenGLFramebufferObjectFormat format;
58 | format.setSamples(4);
59 | format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
60 | return new QOpenGLFramebufferObject(size, format);
61 | }
62 |
63 | private:
64 | MeshRenderer m_render;
65 | QQuickWindow *m_window;
66 | };
67 |
68 |
69 |
70 | // MyFrameBufferObject implementation
71 |
72 | MyFrameBufferObject::MyFrameBufferObject(QQuickItem *parent)
73 | : QQuickFramebufferObject(parent)
74 | , m_azimuth(0.0)
75 | , m_elevation(15.0)
76 | , m_distance(5.0)
77 | {
78 | setMirrorVertically(true);
79 | }
80 |
81 | QQuickFramebufferObject::Renderer *MyFrameBufferObject::createRenderer() const
82 | {
83 | return new MyFrameBufferObjectRenderer;
84 | }
85 |
86 | float MyFrameBufferObject::azimuth() const
87 | {
88 | return m_azimuth;
89 | }
90 |
91 | float MyFrameBufferObject::distance() const
92 | {
93 | return m_distance;
94 | }
95 |
96 | float MyFrameBufferObject::elevation() const
97 | {
98 | return m_elevation;
99 | }
100 |
101 | void MyFrameBufferObject::setAzimuth(float azimuth)
102 | {
103 | if (m_azimuth == azimuth)
104 | return;
105 |
106 | m_azimuth = azimuth;
107 | emit azimuthChanged(azimuth);
108 | update();
109 | }
110 |
111 | void MyFrameBufferObject::setDistance(float distance)
112 | {
113 | if (m_distance == distance)
114 | return;
115 |
116 | m_distance = distance;
117 | emit distanceChanged(distance);
118 | update();
119 | }
120 |
121 | void MyFrameBufferObject::setElevation(float elevation)
122 | {
123 | if (m_elevation == elevation)
124 | return;
125 |
126 | m_elevation = elevation;
127 | emit elevationChanged(elevation);
128 | update();
129 | }
130 |
--------------------------------------------------------------------------------
/fbo/myframebufferobject.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #ifndef MYFRAMEBUFFEROBJECT_H
23 | #define MYFRAMEBUFFEROBJECT_H
24 |
25 | #include
26 |
27 | class MyFrameBufferObject : public QQuickFramebufferObject
28 | {
29 | Q_OBJECT
30 |
31 | Q_PROPERTY(float azimuth READ azimuth WRITE setAzimuth NOTIFY azimuthChanged)
32 | Q_PROPERTY(float elevation READ elevation WRITE setElevation NOTIFY elevationChanged)
33 | Q_PROPERTY(float distance READ distance WRITE setDistance NOTIFY distanceChanged)
34 |
35 | public:
36 | explicit MyFrameBufferObject(QQuickItem *parent = 0);
37 | Renderer *createRenderer() const Q_DECL_OVERRIDE;
38 |
39 | float azimuth() const;
40 | float distance() const;
41 | float elevation() const;
42 |
43 | signals:
44 | void azimuthChanged(float azimuth);
45 | void distanceChanged(float distance);
46 | void elevationChanged(float elevation);
47 |
48 | public slots:
49 | void setAzimuth(float azimuth);
50 | void setDistance(float distance);
51 | void setElevation(float elevation);
52 |
53 | private:
54 | float m_azimuth;
55 | float m_elevation;
56 | float m_distance;
57 | };
58 |
59 | #endif // MYFRAMEBUFFEROBJECT_H
60 |
--------------------------------------------------------------------------------
/integrating-qq2-with-opengl.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += \
4 | lib \
5 | underlay \
6 | fbo \
7 | rendercontrol \
8 |
9 | CONFIG += ordered
10 |
--------------------------------------------------------------------------------
/lgpl-3.0.txt:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/lib/CameraControls.qml:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | import QtQuick 2.0
23 | import QtQuick.Controls 2.0
24 | import QtQuick.Layouts 1.0
25 |
26 | Rectangle {
27 | id: cameraControls
28 | property var camera
29 |
30 | border.color: "#000000"
31 | border.width: 2
32 | radius: 5
33 | color: "#55ffffff"
34 |
35 | width: parent ? parent.width - 10 : 400
36 | height: 150
37 |
38 | Component.onCompleted: if (camera) actualStuff.createObject(cameraControls)
39 |
40 | Component {
41 | id: actualStuff
42 | GridLayout {
43 | anchors.fill: parent
44 | anchors.margins: 5
45 | columns: 3
46 |
47 | Label { text: "Azimuth" }
48 | Slider {
49 | Layout.fillWidth: true
50 | from: 0
51 | to: 360
52 | value: 180
53 | onValueChanged: cameraControls.camera.azimuth = value
54 | }
55 | Label { text: cameraControls.camera.azimuth.toFixed(2) }
56 |
57 | Label { text: "Elevation" }
58 | Slider {
59 | Layout.fillWidth: true
60 | from: 0
61 | to: 90
62 | value: 10
63 | onValueChanged: cameraControls.camera.elevation = value
64 | }
65 | Label { text: cameraControls.camera.elevation.toFixed(2) }
66 |
67 | Label { text: "Distance" }
68 | Slider {
69 | id: distanceSlider
70 | Layout.fillWidth: true
71 | from: 1
72 | to: 25
73 | value: 15
74 | onValueChanged: cameraControls.camera.distance = value
75 | }
76 | Label { text: cameraControls.camera.distance.toFixed(2) }
77 | }
78 | }
79 |
80 |
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/lib/assets.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | assets/phong.frag
4 | assets/phong.vert
5 | assets/trefoil.obj
6 |
7 |
8 | CameraControls.qml
9 |
10 |
11 |
--------------------------------------------------------------------------------
/lib/assets/phong.frag:
--------------------------------------------------------------------------------
1 | #version 330 core
2 |
3 | /****************************************************************************
4 | **
5 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
6 | ** Author: Giuseppe D'Angelo
7 | ** Contact: info@kdab.com
8 | **
9 | ** This program is free software: you can redistribute it and/or modify
10 | ** it under the terms of the GNU Lesser General Public License as published by
11 | ** the Free Software Foundation, either version 3 of the License, or
12 | ** (at your option) any later version.
13 | **
14 | ** This program is distributed in the hope that it will be useful,
15 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ** GNU Lesser General Public License for more details.
18 | **
19 | ** You should have received a copy of the GNU Lesser General Public License
20 | ** along with this program. If not, see .
21 | **
22 | ****************************************************************************/
23 |
24 | uniform struct LightInfo {
25 | vec4 position;
26 | vec3 intensity;
27 | } light;
28 |
29 | struct MaterialInfo
30 | {
31 | vec3 ka; // Ambient reflectivity
32 | vec3 kd; // Diffuse reflectivity
33 | vec3 ks; // Specular reflectivity
34 | float shininess; // Specular shininess factor
35 | };
36 | uniform MaterialInfo material;
37 |
38 | in vec3 position;
39 | in vec3 normal;
40 |
41 | out vec4 fragColor;
42 |
43 |
44 | vec3 adsModel( const in vec3 pos, const in vec3 n )
45 | {
46 | vec3 s = normalize( vec3( light.position ) - pos );
47 | vec3 v = normalize( -pos );
48 | vec3 r = reflect( -s, n );
49 |
50 | float diffuse = max( dot( s, n ), 0.0 );
51 |
52 | float specular = 0.0;
53 | if ( dot( s, n ) > 0.0 )
54 | specular = pow( max( dot( r, v ), 0.0 ), material.shininess );
55 |
56 | return light.intensity * ( material.ka + material.kd * diffuse + material.ks * specular );
57 | }
58 |
59 | void main()
60 | {
61 | fragColor = vec4( adsModel( position, normalize( normal ) ), 1.0 );
62 | }
63 |
--------------------------------------------------------------------------------
/lib/assets/phong.vert:
--------------------------------------------------------------------------------
1 | #version 330 core
2 |
3 | /****************************************************************************
4 | **
5 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
6 | ** Author: Giuseppe D'Angelo
7 | ** Contact: info@kdab.com
8 | **
9 | ** This program is free software: you can redistribute it and/or modify
10 | ** it under the terms of the GNU Lesser General Public License as published by
11 | ** the Free Software Foundation, either version 3 of the License, or
12 | ** (at your option) any later version.
13 | **
14 | ** This program is distributed in the hope that it will be useful,
15 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ** GNU Lesser General Public License for more details.
18 | **
19 | ** You should have received a copy of the GNU Lesser General Public License
20 | ** along with this program. If not, see .
21 | **
22 | ****************************************************************************/
23 |
24 | in vec3 vertexPosition;
25 | in vec3 vertexNormal;
26 |
27 | out vec3 position;
28 | out vec3 normal;
29 |
30 | uniform mat4 modelViewMatrix;
31 | uniform mat3 normalMatrix;
32 | uniform mat4 projectionMatrix;
33 | uniform mat4 mvp;
34 |
35 | void main()
36 | {
37 | normal = normalize( normalMatrix * vertexNormal );
38 | position = vec3( modelViewMatrix * vec4( vertexPosition, 1.0 ) );
39 |
40 | gl_Position = mvp * vec4( vertexPosition, 1.0 );
41 | }
42 |
--------------------------------------------------------------------------------
/lib/axisalignedboundingbox.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include "axisalignedboundingbox.h"
23 |
24 | #include
25 |
26 | AxisAlignedBoundingBox::AxisAlignedBoundingBox()
27 | : m_center(),
28 | m_radii()
29 | {
30 | }
31 |
32 | AxisAlignedBoundingBox::AxisAlignedBoundingBox( const QVector& points )
33 | {
34 | update( points );
35 | }
36 |
37 | void AxisAlignedBoundingBox::update( const QVector& points )
38 | {
39 | if (points.isEmpty()) {
40 | m_center = QVector3D();
41 | m_radii = QVector3D();
42 | return;
43 | }
44 |
45 | QVector3D minPoint = points.at( 0 );
46 | QVector3D maxPoint = points.at( 0 );
47 |
48 | for ( int i = 1; i < points.size(); ++i )
49 | {
50 | const QVector3D& point = points.at( i );
51 | if ( point.x() > maxPoint.x() )
52 | maxPoint.setX( point.x() );
53 | if ( point.y() > maxPoint.y() )
54 | maxPoint.setY( point.y() );
55 | if ( point.z() > maxPoint.z() )
56 | maxPoint.setZ( point.z() );
57 | if ( point.x() < minPoint.x() )
58 | minPoint.setX( point.x() );
59 | if ( point.y() < minPoint.y() )
60 | minPoint.setY( point.y() );
61 | if ( point.z() < minPoint.z() )
62 | minPoint.setZ( point.z() );
63 | }
64 |
65 | m_center = 0.5 * ( minPoint + maxPoint );
66 | m_radii = 0.5 * ( maxPoint - minPoint );
67 | #if 0
68 | qDebug() << "AABB:";
69 | qDebug() << " min =" << minPoint;
70 | qDebug() << " max =" << maxPoint;
71 | qDebug() << " center =" << m_center;
72 | qDebug() << " radii =" << m_radii;
73 | #endif
74 | }
75 |
76 |
77 | QDebug &operator<<(QDebug &stream, const AxisAlignedBoundingBox &bbox)
78 | {
79 | stream << "AABB: min=" << bbox.minPoint() << ", max=" << bbox.maxPoint();
80 | return stream;
81 | }
82 |
--------------------------------------------------------------------------------
/lib/axisalignedboundingbox.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #ifndef AXIS_ALIGNED_BOUNDING_BOX
23 | #define AXIS_ALIGNED_BOUNDING_BOX
24 |
25 | #include
26 | #include
27 |
28 | class QDebug;
29 |
30 | class AxisAlignedBoundingBox
31 | {
32 | public:
33 | AxisAlignedBoundingBox();
34 |
35 | AxisAlignedBoundingBox(const QVector& points);
36 |
37 | void update( const QVector& points );
38 |
39 | QVector3D center() const { return m_center; }
40 | QVector3D radii() const { return m_radii; }
41 |
42 | QVector3D minPoint() const { return m_center - m_radii; }
43 | QVector3D maxPoint() const { return m_center + m_radii; }
44 |
45 | float xExtent() const { return 2.0f * m_radii.x(); }
46 | float yExtent() const { return 2.0f * m_radii.y(); }
47 | float zExtent() const { return 2.0f * m_radii.z(); }
48 |
49 | float maxExtent() const { return qMax( xExtent(), qMax( yExtent(), zExtent() ) ); }
50 | float minExtent() const { return qMin( xExtent(), qMin( yExtent(), zExtent() ) ); }
51 |
52 | private:
53 | QVector3D m_center;
54 | QVector3D m_radii;
55 | };
56 |
57 | QDebug & operator<<(QDebug & stream, const AxisAlignedBoundingBox & bbox);
58 |
59 | #endif // AXIS_ALIGNED_BOUNDING_BOX
60 |
--------------------------------------------------------------------------------
/lib/camera.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include "camera.h"
23 |
24 | Camera::Camera(QObject *parent)
25 | : QObject(parent)
26 | , m_azimuth(0.0)
27 | , m_elevation(15.0)
28 | , m_distance(15.0)
29 | {
30 | }
31 |
32 | float Camera::azimuth() const
33 | {
34 | return m_azimuth;
35 | }
36 |
37 | float Camera::distance() const
38 | {
39 | return m_distance;
40 | }
41 |
42 | float Camera::elevation() const
43 | {
44 | return m_elevation;
45 | }
46 |
47 | void Camera::setAzimuth(float azimuth)
48 | {
49 | if (m_azimuth == azimuth)
50 | return;
51 |
52 | m_azimuth = azimuth;
53 | emit azimuthChanged(azimuth);
54 | }
55 |
56 | void Camera::setDistance(float distance)
57 | {
58 | if (m_distance == distance)
59 | return;
60 |
61 | m_distance = distance;
62 | emit distanceChanged(distance);
63 | }
64 |
65 | void Camera::setElevation(float elevation)
66 | {
67 | if (m_elevation == elevation)
68 | return;
69 |
70 | m_elevation = elevation;
71 | emit elevationChanged(elevation);
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/lib/camera.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #ifndef CAMERA_H
23 | #define CAMERA_H
24 |
25 | #include
26 |
27 | class Camera : public QObject
28 | {
29 | Q_OBJECT
30 | Q_PROPERTY(float azimuth READ azimuth WRITE setAzimuth NOTIFY azimuthChanged)
31 | Q_PROPERTY(float elevation READ elevation WRITE setElevation NOTIFY elevationChanged)
32 | Q_PROPERTY(float distance READ distance WRITE setDistance NOTIFY distanceChanged)
33 |
34 | public:
35 | explicit Camera(QObject *parent = 0);
36 |
37 | float azimuth() const;
38 | float distance() const;
39 | float elevation() const;
40 |
41 | signals:
42 | void azimuthChanged(float azimuth);
43 | void distanceChanged(float distance);
44 | void elevationChanged(float elevation);
45 |
46 | public slots:
47 | void setAzimuth(float azimuth);
48 | void setDistance(float distance);
49 | void setElevation(float elevation);
50 |
51 | private:
52 | float m_azimuth;
53 | float m_elevation;
54 | float m_distance;
55 | };
56 |
57 | #endif // CAMERA_H
58 |
--------------------------------------------------------------------------------
/lib/lib.pri:
--------------------------------------------------------------------------------
1 | INCLUDEPATH += ../lib/
2 |
3 | win32 {
4 | CONFIG(debug,debug|release) {
5 | LIBS += $$OUT_PWD/../lib/debug/librenderlib.a
6 | PRE_TARGETDEPS = $$OUT_PWD/../lib/debug/librenderlib.a
7 | }
8 | CONFIG(release,debug|release) {
9 | LIBS += $$OUT_PWD/../lib/release/librenderlib.a
10 | PRE_TARGETDEPS = $$OUT_PWD/../lib/release/librenderlib.a
11 | }
12 | } else {
13 | LIBS += $$OUT_PWD/../lib/librenderlib.a
14 | PRE_TARGETDEPS = $$OUT_PWD/../lib/librenderlib.a
15 | }
16 |
--------------------------------------------------------------------------------
/lib/lib.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = lib
2 | CONFIG += static
3 | TARGET = renderlib
4 |
5 | SOURCES += \
6 | objloader.cpp \
7 | axisalignedboundingbox.cpp \
8 | camera.cpp \
9 | meshrenderer.cpp
10 |
11 |
12 | HEADERS += \
13 | objloader.h \
14 | axisalignedboundingbox.h \
15 | camera.h \
16 | meshrenderer.h
17 |
18 | DISTFILES += \
19 | lib.pri
20 |
21 | RESOURCES += \
22 | assets.qrc
23 |
--------------------------------------------------------------------------------
/lib/meshrenderer.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include "meshrenderer.h"
23 |
24 | #include "objloader.h"
25 |
26 | #include
27 | #include
28 |
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | #include
35 |
36 | #include
37 |
38 | #include
39 | #include
40 |
41 | MeshRenderer::MeshRenderer(QObject *parent)
42 | : QObject(parent)
43 | , m_positionsBuffer(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer))
44 | , m_normalsBuffer(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer))
45 | , m_indicesBuffer(new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer))
46 | , m_shaderProgram()
47 | , m_vao(new QOpenGLVertexArrayObject)
48 | , m_indicesCount(0)
49 | , m_coordinateMirroring(DoNotMirrorCoordinates)
50 | , m_azimuth(0.0)
51 | , m_elevation(15.0)
52 | , m_distance(15.0)
53 | {
54 | }
55 |
56 | MeshRenderer::~MeshRenderer()
57 | {
58 | invalidate();
59 | }
60 |
61 | void MeshRenderer::initialize(CoordinateMirroring cm)
62 | {
63 | if (m_vao->isCreated())
64 | return; // already initialized
65 |
66 | m_coordinateMirroring = cm;
67 |
68 | ObjLoader loader;
69 |
70 | if (!loader.load(":/assets/trefoil.obj"))
71 | qFatal("Could not load mesh");
72 |
73 | if (!m_vao->create())
74 | qFatal("Unable to create VAO");
75 |
76 | m_vao->bind();
77 |
78 | const QVector vertices = loader.vertices();
79 | if (!m_positionsBuffer->create())
80 | qFatal("Unable to create position buffer");
81 | m_positionsBuffer->bind();
82 | m_positionsBuffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
83 | m_positionsBuffer->allocate(vertices.constData(), vertices.size() * sizeof(QVector3D));
84 |
85 | const QVector normals = loader.normals();
86 | m_normalsBuffer->create();
87 | m_normalsBuffer->bind();
88 | m_normalsBuffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
89 | m_normalsBuffer->allocate(normals.constData(), normals.size() * sizeof(QVector3D));
90 |
91 | const QVector indices = loader.indices();
92 | m_indicesCount = indices.size();
93 | if (!m_indicesBuffer->create())
94 | qFatal("Unable to create index buffer");
95 |
96 | m_indicesBuffer->bind();
97 | m_indicesBuffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
98 | m_indicesBuffer->allocate(indices.constData(), indices.size() * sizeof(unsigned int));
99 |
100 | m_shaderProgram.reset(new QOpenGLShaderProgram);
101 | if (!m_shaderProgram->create())
102 | qFatal("Unable to create shader program");
103 | if (!m_shaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/assets/phong.vert"))
104 | qFatal("Vertex shader compilation failed");
105 | if (!m_shaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/assets/phong.frag"))
106 | qFatal("Fragment shader compilation failed");
107 | if (!m_shaderProgram->link())
108 | qFatal("Shader program not linked");
109 |
110 | m_shaderProgram->bind();
111 |
112 | m_positionsBuffer->bind();
113 | m_shaderProgram->enableAttributeArray("vertexPosition");
114 | m_shaderProgram->setAttributeBuffer("vertexPosition", GL_FLOAT, 0, 3);
115 |
116 | m_normalsBuffer->bind();
117 | m_shaderProgram->enableAttributeArray("vertexNormal");
118 | m_shaderProgram->setAttributeBuffer("vertexNormal", GL_FLOAT, 0, 3);
119 |
120 | m_vao->release();
121 | }
122 |
123 | void MeshRenderer::render()
124 | {
125 | QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
126 |
127 | QMatrix4x4 modelMatrix;
128 | QMatrix4x4 viewMatrix;
129 | QMatrix4x4 projectionMatrix;
130 |
131 | modelMatrix.rotate(-90, 0, 1, 0);
132 |
133 | const float azimuthInRadians = qDegreesToRadians(m_azimuth);
134 | const float elevationInRadians = qDegreesToRadians(m_elevation);
135 |
136 | const QVector3D eyePosition(std::cos(elevationInRadians) * std::cos(azimuthInRadians),
137 | std::sin(elevationInRadians),
138 | -std::cos(elevationInRadians) * std::sin(azimuthInRadians));
139 |
140 | QVector3D upVector = qFuzzyCompare(m_elevation, 90.0f)
141 | ? QVector3D(-std::cos(azimuthInRadians), 0, std::sin(azimuthInRadians))
142 | : QVector3D(0, 1, 0);
143 |
144 | viewMatrix.lookAt(eyePosition * m_distance,
145 | QVector3D(0, 0, 0),
146 | upVector);
147 |
148 | GLint viewportSize[4];
149 | functions->glGetIntegerv(GL_VIEWPORT, viewportSize);
150 |
151 | projectionMatrix.perspective(30, float(viewportSize[2]) / viewportSize[3], 0.01, 1000);
152 |
153 | switch (m_coordinateMirroring) {
154 | case MeshRenderer::DoNotMirrorCoordinates:
155 | break;
156 | case MeshRenderer::MirrorYCoordinate:
157 | projectionMatrix.scale(1, -1, 1);
158 | break;
159 | }
160 |
161 | const QMatrix4x4 modelViewMatrix = viewMatrix * modelMatrix;
162 | const QMatrix4x4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix;
163 |
164 | functions->glClearColor(1.0, 1.0, 1.0, 1.0);
165 | functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
166 | functions->glEnable(GL_DEPTH_TEST);
167 |
168 | m_shaderProgram->bind();
169 |
170 | m_shaderProgram->setUniformValue("modelViewMatrix", modelViewMatrix);
171 | m_shaderProgram->setUniformValue("normalMatrix", modelViewMatrix.normalMatrix());
172 | m_shaderProgram->setUniformValue("projectionMatrix", projectionMatrix);
173 | m_shaderProgram->setUniformValue("mvp", modelViewProjectionMatrix);
174 |
175 | m_shaderProgram->setUniformValue("light.position", QVector4D(0.0, 0.0, 0.0, 1.0));
176 | m_shaderProgram->setUniformValue("light.intensity", QVector3D(1.0, 1.0, 1.0));
177 |
178 | m_shaderProgram->setUniformValue("material.ka", QVector3D(0.1, 0.1, 0.1));
179 | m_shaderProgram->setUniformValue("material.kd", QVector3D(1.0, 0.1, 0.1));
180 | m_shaderProgram->setUniformValue("material.ks", QVector3D(1.0, 1.0, 1.0));
181 | m_shaderProgram->setUniformValue("material.shininess", 32.0f);
182 |
183 | m_vao->bind();
184 | functions->glDrawElements(GL_TRIANGLES, m_indicesCount, GL_UNSIGNED_INT, Q_NULLPTR);
185 | m_vao->release();
186 | }
187 |
188 | void MeshRenderer::invalidate()
189 | {
190 | m_positionsBuffer->destroy();
191 | m_normalsBuffer->destroy();
192 | m_indicesBuffer->destroy();
193 | m_shaderProgram.reset();
194 | m_vao->destroy();
195 | }
196 |
197 | void MeshRenderer::setAzimuth(float azimuth)
198 | {
199 | m_azimuth = azimuth;
200 | }
201 |
202 | void MeshRenderer::setElevation(float elevation)
203 | {
204 | m_elevation = elevation;
205 | }
206 |
207 | void MeshRenderer::setDistance(float distance)
208 | {
209 | m_distance = distance;
210 | }
211 |
--------------------------------------------------------------------------------
/lib/meshrenderer.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #ifndef MESHRENDERER_H
23 | #define MESHRENDERER_H
24 |
25 | #include
26 |
27 | #include
28 |
29 | class QOpenGLBuffer;
30 | class QOpenGLShaderProgram;
31 | class QOpenGLVertexArrayObject;
32 |
33 | class MeshRenderer : public QObject
34 | {
35 | Q_OBJECT
36 | public:
37 | explicit MeshRenderer(QObject *parent = 0);
38 | ~MeshRenderer();
39 |
40 | enum CoordinateMirroring {
41 | DoNotMirrorCoordinates,
42 | MirrorYCoordinate
43 | };
44 |
45 | // All assume that the GL context is current.
46 | void initialize(CoordinateMirroring cm = DoNotMirrorCoordinates);
47 | void render();
48 | void invalidate();
49 |
50 | void setAzimuth(float azimuth);
51 | void setElevation(float elevation);
52 | void setDistance(float distance);
53 |
54 | private:
55 | QScopedPointer m_positionsBuffer;
56 | QScopedPointer m_normalsBuffer;
57 | QScopedPointer m_indicesBuffer;
58 | QScopedPointer m_shaderProgram;
59 | QScopedPointer m_vao;
60 |
61 | int m_indicesCount;
62 |
63 | CoordinateMirroring m_coordinateMirroring;
64 |
65 | float m_azimuth;
66 | float m_elevation;
67 | float m_distance;
68 | };
69 |
70 | #endif // MESHRENDERER_H
71 |
72 |
73 |
--------------------------------------------------------------------------------
/lib/objloader.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include "objloader.h"
23 |
24 | #include "axisalignedboundingbox.h"
25 |
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | struct FaceIndices
35 | {
36 | FaceIndices()
37 | : positionIndex(std::numeric_limits::max())
38 | , texCoordIndex(std::numeric_limits::max())
39 | , normalIndex(std::numeric_limits::max())
40 | {}
41 |
42 | FaceIndices(unsigned int posIndex, unsigned int tcIndex, unsigned int nIndex)
43 | : positionIndex(posIndex)
44 | , texCoordIndex(tcIndex)
45 | , normalIndex(nIndex)
46 | {}
47 |
48 | bool operator == (const FaceIndices &other) const
49 | {
50 | return positionIndex == other.positionIndex &&
51 | texCoordIndex == other.texCoordIndex &&
52 | normalIndex == other.normalIndex;
53 | }
54 |
55 | unsigned int positionIndex;
56 | unsigned int texCoordIndex;
57 | unsigned int normalIndex;
58 | };
59 |
60 | inline uint qHash(const FaceIndices &faceIndices, uint seed = 0)
61 | {
62 | QtPrivate::QHashCombine hash;
63 | seed = hash(faceIndices.positionIndex, seed);
64 | seed = hash(faceIndices.normalIndex, seed);
65 | seed = hash(faceIndices.texCoordIndex, seed);
66 | return seed;
67 | }
68 |
69 | ObjLoader::ObjLoader()
70 | : m_loadTextureCoords( true ),
71 | m_centerMesh( false )
72 | {
73 | }
74 |
75 | bool ObjLoader::load( const QString& fileName )
76 | {
77 | QFile file( fileName );
78 | if ( !file.open( ::QIODevice::ReadOnly | ::QIODevice::Text ) )
79 | {
80 | qDebug() << "Could not open file" << fileName << "for reading";
81 | return false;
82 | }
83 |
84 | return load( &file );
85 | }
86 |
87 | static void addFaceVertex( const FaceIndices& faceIndices,
88 | QVector& faceIndexVector,
89 | QHash& faceIndexMap )
90 | {
91 | if (faceIndices.positionIndex != std::numeric_limits::max()) {
92 | faceIndexVector.append(faceIndices);
93 | if (!faceIndexMap.contains(faceIndices))
94 | faceIndexMap.insert(faceIndices, faceIndexMap.size());
95 | } else {
96 | qWarning( "Missing position index" );
97 | }
98 | }
99 |
100 | bool ObjLoader::load( QIODevice* ioDev )
101 | {
102 | Q_CHECK_PTR(ioDev);
103 | if (!ioDev->isOpen()) {
104 | qWarning() << "iodevice" << ioDev << "not open for reading";
105 | return false;
106 | }
107 |
108 | int faceCount = 0;
109 |
110 | // Parse faces taking into account each vertex in a face can index different indices
111 | // for the positions, normals and texture coords;
112 | // Generate unique vertices (in OpenGL parlance) and output to m_points, m_texCoords,
113 | // m_normals and calculate mapping from faces to unique indices
114 | QVector positions;
115 | QVector normals;
116 | QVector texCoords;
117 | QHash faceIndexMap;
118 | QVector faceIndexVector;
119 |
120 | QTextStream stream(ioDev);
121 | while (!stream.atEnd()) {
122 | QString line = stream.readLine();
123 | line = line.simplified();
124 |
125 | if (line.length() > 0 && line.at(0) != QChar::fromLatin1('#')) {
126 | QTextStream lineStream(&line, QIODevice::ReadOnly);
127 | QString token;
128 | lineStream >> token;
129 |
130 | if (token == QStringLiteral("v")) {
131 | float x, y, z;
132 | lineStream >> x >> y >> z;
133 | positions.append(QVector3D( x, y, z ));
134 | } else if (token == QStringLiteral("vt") && m_loadTextureCoords) {
135 | // Process texture coordinate
136 | float s,t;
137 | lineStream >> s >> t;
138 | texCoords.append(QVector2D(s, t));
139 | } else if (token == QStringLiteral("vn")) {
140 | float x, y, z;
141 | lineStream >> x >> y >> z;
142 | normals.append(QVector3D( x, y, z ));
143 | } else if (token == QStringLiteral("f")) {
144 | // Process face
145 | ++faceCount;
146 | QVector face;
147 | int faceVertices = 0;
148 | while (!lineStream.atEnd()) {
149 | QString faceString;
150 | lineStream >> faceString;
151 |
152 | FaceIndices faceIndices;
153 | QStringList indices = faceString.split(QChar::fromLatin1('/'));
154 | switch (indices.size()) {
155 | case 3:
156 | faceIndices.normalIndex = indices.at(2).toInt() - 1; // fall through
157 | case 2:
158 | faceIndices.texCoordIndex = indices.at(1).toInt() - 1; // fall through
159 | case 1:
160 | faceIndices.positionIndex = indices.at(0).toInt() - 1;
161 | break;
162 | default:
163 | qWarning() << "Unsupported number of indices in face element";
164 | }
165 |
166 | face.append(faceIndices);
167 | ++faceVertices;
168 | }
169 |
170 | // If number of edges in face is greater than 3,
171 | // decompose into triangles as a triangle fan.
172 | FaceIndices v0 = face[0];
173 | FaceIndices v1 = face[1];
174 | FaceIndices v2 = face[2];
175 |
176 | // First face
177 | addFaceVertex(v0, faceIndexVector, faceIndexMap);
178 | addFaceVertex(v1, faceIndexVector, faceIndexMap);
179 | addFaceVertex(v2, faceIndexVector, faceIndexMap);
180 |
181 | for ( int i = 3; i < face.size(); ++i ) {
182 | v1 = v2;
183 | v2 = face[i];
184 | addFaceVertex(v0, faceIndexVector, faceIndexMap);
185 | addFaceVertex(v1, faceIndexVector, faceIndexMap);
186 | addFaceVertex(v2, faceIndexVector, faceIndexMap);
187 | }
188 | } // end of face
189 | } // end of input line
190 | } // while (!stream.atEnd())
191 |
192 | updateIndices(positions, normals, texCoords, faceIndexMap, faceIndexVector);
193 |
194 | if (m_normals.isEmpty())
195 | generateAveragedNormals(m_points, m_normals, m_indices);
196 |
197 | if (m_centerMesh)
198 | center(m_points);
199 |
200 | qDebug() << "Loaded mesh:";
201 | qDebug() << " " << m_points.size() << "points";
202 | qDebug() << " " << faceCount << "faces";
203 | qDebug() << " " << m_indices.size() / 3 << "triangles.";
204 | qDebug() << " " << m_normals.size() << "normals";
205 | qDebug() << " " << m_texCoords.size() << "texture coordinates.";
206 |
207 | return true;
208 | }
209 |
210 | void ObjLoader::updateIndices( const QVector& positions,
211 | const QVector& normals,
212 | const QVector& texCoords,
213 | const QHash& faceIndexMap,
214 | const QVector& faceIndexVector )
215 | {
216 | // Iterate over the faceIndexMap and pull out pos, texCoord and normal data
217 | // thereby generating unique vertices of data (by OpenGL definition)
218 | const int vertexCount = faceIndexMap.size();
219 | const bool hasTexCoords = !texCoords.isEmpty();
220 | const bool hasNormals = !normals.isEmpty();
221 |
222 | m_points.resize(vertexCount);
223 | m_texCoords.clear();
224 | if (hasTexCoords)
225 | m_texCoords.resize(vertexCount);
226 | m_normals.clear();
227 | if (hasNormals)
228 | m_normals.resize(vertexCount);
229 |
230 | foreach (const FaceIndices &faceIndices, faceIndexMap.keys()) {
231 | const int i = faceIndexMap.value(faceIndices);
232 |
233 | m_points[i] = positions[faceIndices.positionIndex];
234 | if (hasTexCoords)
235 | m_texCoords[i] = texCoords[faceIndices.texCoordIndex];
236 | if (hasNormals)
237 | m_normals[i] = normals[faceIndices.normalIndex];
238 | }
239 |
240 | // Now iterate over the face indices and lookup the unique vertex index
241 | const int indexCount = faceIndexVector.size();
242 | m_indices.clear();
243 | m_indices.reserve(indexCount);
244 | foreach (const FaceIndices &faceIndices, faceIndexVector) {
245 | const unsigned int i = faceIndexMap.value(faceIndices);
246 | m_indices.append(i);
247 | }
248 | }
249 |
250 | void ObjLoader::generateAveragedNormals( const QVector& points,
251 | QVector& normals,
252 | const QVector& faces ) const
253 | {
254 | for ( int i = 0; i < points.size(); ++i )
255 | normals.append( QVector3D() );
256 |
257 | for ( int i = 0; i < faces.size(); i += 3 )
258 | {
259 | const QVector3D& p1 = points[ faces[i] ];
260 | const QVector3D& p2 = points[ faces[i+1] ];
261 | const QVector3D& p3 = points[ faces[i+2] ];
262 |
263 | QVector3D a = p2 - p1;
264 | QVector3D b = p3 - p1;
265 | QVector3D n = QVector3D::crossProduct( a, b ).normalized();
266 |
267 | normals[ faces[i] ] += n;
268 | normals[ faces[i+1] ] += n;
269 | normals[ faces[i+2] ] += n;
270 | }
271 |
272 | for ( int i = 0; i < normals.size(); ++i )
273 | normals[i].normalize();
274 | }
275 |
276 | void ObjLoader::center( QVector& points )
277 | {
278 | if ( points.isEmpty() )
279 | return;
280 |
281 | AxisAlignedBoundingBox bb(points);
282 | QVector3D center = bb.center();
283 |
284 | // Translate center of the AABB to the origin
285 | for ( int i = 0; i < points.size(); ++i )
286 | {
287 | QVector3D& point = points[i];
288 | point = point - center;
289 | }
290 | }
291 |
--------------------------------------------------------------------------------
/lib/objloader.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #ifndef OBJLOADER_H
23 | #define OBJLOADER_H
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include
31 |
32 | class QString;
33 | class QIODevice;
34 |
35 | struct FaceIndices;
36 |
37 | class ObjLoader
38 | {
39 | public:
40 | ObjLoader();
41 |
42 | void setLoadTextureCoordinatesEnabled( bool b ) { m_loadTextureCoords = b; }
43 | bool isLoadTextureCoordinatesEnabled() const { return m_loadTextureCoords; }
44 |
45 | void setMeshCenteringEnabled( bool b ) { m_centerMesh = b; }
46 | bool isMeshCenteringEnabled() const { return m_centerMesh; }
47 |
48 | bool hasNormals() const { return !m_normals.isEmpty(); }
49 | bool hasTextureCoordinates() const { return !m_texCoords.isEmpty(); }
50 |
51 | bool load( const QString& fileName );
52 | bool load( QIODevice* ioDev );
53 |
54 | QVector vertices() const { return m_points; }
55 | QVector normals() const { return m_normals; }
56 | QVector textureCoordinates() const { return m_texCoords; }
57 | QVector indices() const { return m_indices; }
58 |
59 | private:
60 | void updateIndices(const QVector &positions,
61 | const QVector &normals,
62 | const QVector &texCoords,
63 | const QHash &faceIndexMap,
64 | const QVector &faceIndexVector);
65 | void generateAveragedNormals( const QVector& points,
66 | QVector& normals,
67 | const QVector& faces ) const;
68 | void center( QVector& points );
69 |
70 | bool m_loadTextureCoords;
71 | bool m_generateTangents;
72 | bool m_centerMesh;
73 |
74 | QVector m_points;
75 | QVector m_normals;
76 | QVector m_texCoords;
77 | QVector m_indices;
78 | };
79 |
80 | #endif // OBJLOADER_H
81 |
--------------------------------------------------------------------------------
/rendercontrol/main.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include
23 |
24 | #include "renderwindow.h"
25 |
26 | int main(int argc, char **argv)
27 | {
28 | QGuiApplication app(argc, argv);
29 |
30 | Q_INIT_RESOURCE(assets);
31 |
32 | RenderWindow w;
33 | w.resize(600, 600);
34 | w.show();
35 |
36 | return app.exec();
37 | }
38 |
--------------------------------------------------------------------------------
/rendercontrol/main.qml:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | import QtQuick 2.4
23 |
24 | Item {
25 | id: root
26 |
27 | width: 400
28 | height: 400
29 |
30 | CameraControls {
31 | camera: _camera
32 |
33 | anchors.bottom: root.bottom
34 | anchors.horizontalCenter: root.horizontalCenter
35 | }
36 | }
37 |
38 |
39 |
--------------------------------------------------------------------------------
/rendercontrol/rendercontrol.pro:
--------------------------------------------------------------------------------
1 | include(../lib/lib.pri)
2 |
3 | TEMPLATE = app
4 | TARGET = rendercontrol
5 |
6 | QT += quick
7 |
8 | SOURCES += \
9 | main.cpp \
10 | renderwindow.cpp
11 |
12 | HEADERS += \
13 | renderwindow.h
14 |
15 | RESOURCES += \
16 | rendercontrol.qrc
17 |
18 |
19 |
--------------------------------------------------------------------------------
/rendercontrol/rendercontrol.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | main.qml
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rendercontrol/renderwindow.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include "renderwindow.h"
23 |
24 | #include
25 | #include
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | #include
32 | #include
33 | #include
34 |
35 | #include
36 | #include
37 | #include
38 |
39 | #include
40 |
41 | RenderWindow::RenderWindow(QWindow *parent)
42 | : QWindow(parent)
43 | , m_context(0)
44 | , m_renderer(0)
45 | , m_camera(0)
46 | , m_renderControl(0)
47 | , m_quickWindow(0)
48 | , m_qmlComponent(0)
49 | , m_rootItem(0)
50 | {
51 | // set the window up
52 | setSurfaceType(QSurface::OpenGLSurface);
53 |
54 | QSurfaceFormat format;
55 | format.setMajorVersion(3);
56 | format.setMinorVersion(3);
57 | format.setProfile(QSurfaceFormat::CoreProfile);
58 | format.setDepthBufferSize(24);
59 | format.setStencilBufferSize(8);
60 | format.setSamples(4);
61 |
62 | setFormat(format);
63 | create();
64 |
65 | // create the GL context
66 |
67 | m_context = new QOpenGLContext(this);
68 | m_context->setFormat(format);
69 | if (!m_context->create())
70 | qFatal("Unable to create context");
71 |
72 | m_context->makeCurrent(this);
73 |
74 | // set up our stuff
75 |
76 | m_renderer = new MeshRenderer(this);
77 | m_renderer->initialize();
78 |
79 | m_camera = new Camera(this);
80 |
81 | // set up QtQuick
82 |
83 | m_renderControl = new QQuickRenderControl(this);
84 | m_quickWindow = new QQuickWindow(m_renderControl);
85 | m_quickWindow->setClearBeforeRendering(false);
86 |
87 | // try to "batch" multiple scene changed signals in one sync
88 | QTimer *sceneSyncTimer = new QTimer(this);
89 | sceneSyncTimer->setInterval(5);
90 | sceneSyncTimer->setSingleShot(true);
91 | connect(sceneSyncTimer, &QTimer::timeout,
92 | this, &RenderWindow::syncScene);
93 |
94 | connect(m_renderControl, &QQuickRenderControl::sceneChanged,
95 | sceneSyncTimer, static_cast(&QTimer::start));
96 |
97 | connect(m_renderControl, &QQuickRenderControl::renderRequested,
98 | this, &RenderWindow::draw);
99 |
100 | m_renderControl->initialize(m_context);
101 |
102 |
103 | // load a QML scene "manually"
104 | QQmlEngine *engine = new QQmlEngine(this);
105 |
106 | if (!engine->incubationController())
107 | engine->setIncubationController(m_quickWindow->incubationController());
108 |
109 | engine->rootContext()->setContextProperty("_camera", m_camera);
110 | m_qmlComponent = new QQmlComponent(engine, this);
111 |
112 | connect(m_qmlComponent, &QQmlComponent::statusChanged,
113 | this, &RenderWindow::onQmlComponentLoadingComplete);
114 |
115 | m_qmlComponent->loadUrl(QUrl("qrc:///qml/main.qml"));
116 |
117 |
118 |
119 | // also, just for the sake of it, trigger a redraw every 500 ms no matter what
120 | QTimer *redrawTimer = new QTimer(this);
121 | connect(redrawTimer, &QTimer::timeout, this, &RenderWindow::draw);
122 | redrawTimer->start(500);
123 | }
124 |
125 | RenderWindow::~RenderWindow()
126 | {
127 | m_context->makeCurrent(this);
128 |
129 | m_renderer->invalidate();
130 | delete m_renderer;
131 |
132 | delete m_rootItem;
133 | delete m_qmlComponent;
134 | delete m_renderControl;
135 | delete m_quickWindow;
136 |
137 | m_context->doneCurrent();
138 | delete m_context;
139 | }
140 |
141 | void RenderWindow::resizeEvent(QResizeEvent *e)
142 | {
143 | // Simulate the "resize root item to follow window"
144 | updateRootItemSize();
145 | QWindow::resizeEvent(e);
146 | }
147 |
148 | void RenderWindow::syncScene()
149 | {
150 | m_renderControl->polishItems();
151 |
152 | m_renderer->setAzimuth(m_camera->azimuth());
153 | m_renderer->setElevation(m_camera->elevation());
154 | m_renderer->setDistance(m_camera->distance());
155 |
156 | m_renderControl->sync();
157 | draw();
158 | }
159 |
160 | void RenderWindow::draw()
161 | {
162 | if (!isExposed())
163 | return;
164 | m_context->makeCurrent(this);
165 | m_context->functions()->glViewport(0, 0, width() * devicePixelRatio(), height() * devicePixelRatio());
166 |
167 | m_renderer->render();
168 | m_quickWindow->resetOpenGLState();
169 |
170 | m_renderControl->render();
171 |
172 | m_context->swapBuffers(this);
173 | }
174 |
175 | void RenderWindow::onQmlComponentLoadingComplete()
176 | {
177 | if (m_qmlComponent->isLoading())
178 | return;
179 | if (m_qmlComponent->isError()) {
180 | const QList errorList = m_qmlComponent->errors();
181 | foreach (const QQmlError &error, errorList)
182 | qWarning() << error.url() << error.line() << error;
183 |
184 | qFatal("Unable to load QML file");
185 | }
186 |
187 | QObject *rootObject = m_qmlComponent->create();
188 | m_rootItem = qobject_cast(rootObject);
189 | if (!m_rootItem)
190 | qFatal("Did not load a Qt Quick scene");
191 |
192 | m_rootItem->setParentItem(m_quickWindow->contentItem());
193 | }
194 |
195 | void RenderWindow::updateRootItemSize()
196 | {
197 | if (m_rootItem) {
198 | m_rootItem->setWidth(width());
199 | m_rootItem->setHeight(height());
200 | }
201 |
202 | m_quickWindow->setHeight(height());
203 | m_quickWindow->setWidth(width());
204 | }
205 |
206 | void RenderWindow::mousePressEvent(QMouseEvent *e)
207 | {
208 | qApp->sendEvent(m_quickWindow, e);
209 | if (!e->isAccepted())
210 | QWindow::mousePressEvent(e);
211 | }
212 |
213 | void RenderWindow::mouseMoveEvent(QMouseEvent *e)
214 | {
215 | qApp->sendEvent(m_quickWindow, e);
216 | if (!e->isAccepted())
217 | QWindow::mousePressEvent(e);
218 | }
219 |
220 | void RenderWindow::mouseReleaseEvent(QMouseEvent *e)
221 | {
222 | qApp->sendEvent(m_quickWindow, e);
223 | if (!e->isAccepted())
224 | QWindow::mousePressEvent(e);
225 | }
226 |
227 |
--------------------------------------------------------------------------------
/rendercontrol/renderwindow.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #ifndef RENDERWINDOW_H
23 | #define RENDERWINDOW_H
24 |
25 | #include
26 |
27 | class MeshRenderer;
28 | class Camera;
29 | class QOpenGLContext;
30 | class QQuickWindow;
31 | class QQuickRenderControl;
32 | class QQmlComponent;
33 | class QQuickItem;
34 |
35 | class RenderWindow : public QWindow
36 | {
37 | public:
38 | RenderWindow(QWindow *parent = 0);
39 | ~RenderWindow();
40 |
41 | protected:
42 | void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;
43 |
44 | void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
45 | void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
46 | void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
47 |
48 | private:
49 | void syncScene();
50 | void draw();
51 |
52 | void onQmlComponentLoadingComplete();
53 | void updateRootItemSize();
54 |
55 | QOpenGLContext *m_context;
56 |
57 | MeshRenderer *m_renderer;
58 | Camera *m_camera;
59 |
60 | QQuickRenderControl *m_renderControl;
61 | QQuickWindow *m_quickWindow;
62 | QQmlComponent *m_qmlComponent;
63 | QQuickItem *m_rootItem;
64 | };
65 |
66 | #endif // RENDERWINDOW_H
67 |
68 |
--------------------------------------------------------------------------------
/underlay/main.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include "myquickview.h"
23 |
24 | #include
25 |
26 | int main(int argc, char **argv)
27 | {
28 | QGuiApplication app(argc, argv);
29 |
30 | Q_INIT_RESOURCE(assets);
31 |
32 | MyQuickView view;
33 | view.show();
34 | view.resize(600, 600);
35 |
36 | return app.exec();
37 | }
38 |
--------------------------------------------------------------------------------
/underlay/main.qml:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | import QtQuick 2.4
23 |
24 | Item {
25 | id: root
26 |
27 | width: 400
28 | height: 400
29 |
30 | CameraControls {
31 | camera: _camera
32 |
33 | anchors.bottom: root.bottom
34 | anchors.horizontalCenter: root.horizontalCenter
35 | }
36 | }
37 |
38 |
39 |
--------------------------------------------------------------------------------
/underlay/myquickview.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #include "myquickview.h"
23 |
24 | #include
25 | #include
26 |
27 | #include
28 | #include
29 |
30 | MyQuickView::MyQuickView(QWindow *parent)
31 | : QQuickView(parent)
32 | , m_camera(new Camera(this))
33 | , m_renderer(new MeshRenderer(this))
34 | {
35 | QSurfaceFormat format;
36 | format.setMajorVersion(3);
37 | format.setMinorVersion(3);
38 | format.setProfile(QSurfaceFormat::CoreProfile);
39 | format.setDepthBufferSize(24);
40 | format.setStencilBufferSize(8);
41 | format.setSamples(4);
42 | setFormat(format);
43 |
44 | connect(this, &QQuickWindow::sceneGraphInitialized,
45 | this, &MyQuickView::initializeUnderlay,
46 | Qt::DirectConnection);
47 |
48 | connect(this, &QQuickWindow::beforeSynchronizing,
49 | this, &MyQuickView::synchronizeUnderlay,
50 | Qt::DirectConnection);
51 |
52 | connect(this, &QQuickWindow::beforeRendering,
53 | this, &MyQuickView::renderUnderlay,
54 | Qt::DirectConnection);
55 |
56 | connect(this, &QQuickWindow::sceneGraphInvalidated,
57 | this, &MyQuickView::invalidateUnderlay,
58 | Qt::DirectConnection);
59 |
60 | connect(m_camera, &Camera::azimuthChanged,
61 | this, &QQuickWindow::update);
62 |
63 | connect(m_camera, &Camera::elevationChanged,
64 | this, &QQuickWindow::update);
65 |
66 | connect(m_camera, &Camera::distanceChanged,
67 | this, &QQuickWindow::update);
68 |
69 | setClearBeforeRendering(false);
70 | setPersistentOpenGLContext(true);
71 |
72 | setResizeMode(SizeRootObjectToView);
73 | rootContext()->setContextProperty("_camera", m_camera);
74 | setSource(QUrl("qrc:///qml/main.qml"));
75 | }
76 |
77 | void MyQuickView::initializeUnderlay()
78 | {
79 | m_renderer->initialize();
80 | resetOpenGLState();
81 | }
82 |
83 | void MyQuickView::synchronizeUnderlay()
84 | {
85 | m_renderer->setAzimuth(m_camera->azimuth());
86 | m_renderer->setElevation(m_camera->elevation());
87 | m_renderer->setDistance(m_camera->distance());
88 | }
89 |
90 | void MyQuickView::renderUnderlay()
91 | {
92 | m_renderer->render();
93 | resetOpenGLState();
94 | }
95 |
96 | void MyQuickView::invalidateUnderlay()
97 | {
98 | m_renderer->invalidate();
99 | resetOpenGLState();
100 | }
101 |
--------------------------------------------------------------------------------
/underlay/myquickview.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company.
4 | ** Author: Giuseppe D'Angelo
5 | ** Contact: info@kdab.com
6 | **
7 | ** This program is free software: you can redistribute it and/or modify
8 | ** it under the terms of the GNU Lesser General Public License as published by
9 | ** the Free Software Foundation, either version 3 of the License, or
10 | ** (at your option) any later version.
11 | **
12 | ** This program is distributed in the hope that it will be useful,
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ** GNU Lesser General Public License for more details.
16 | **
17 | ** You should have received a copy of the GNU Lesser General Public License
18 | ** along with this program. If not, see .
19 | **
20 | ****************************************************************************/
21 |
22 | #ifndef MYQUICKVIEW_H
23 | #define MYQUICKVIEW_H
24 |
25 | #include
26 |
27 | class MeshRenderer;
28 | class Camera;
29 |
30 | class MyQuickView : public QQuickView
31 | {
32 | Q_OBJECT
33 | public:
34 | explicit MyQuickView(QWindow *parent = 0);
35 |
36 | private:
37 | void initializeUnderlay();
38 | void synchronizeUnderlay();
39 | void renderUnderlay();
40 | void invalidateUnderlay();
41 |
42 | Camera *m_camera;
43 | MeshRenderer *m_renderer;
44 | };
45 |
46 | #endif // MYQUICKVIEW_H
47 |
--------------------------------------------------------------------------------
/underlay/underlay.pro:
--------------------------------------------------------------------------------
1 | include(../lib/lib.pri)
2 |
3 | TEMPLATE = app
4 | TARGET = underlay
5 |
6 | QT += quick
7 |
8 | SOURCES += \
9 | main.cpp \
10 | myquickview.cpp
11 |
12 | HEADERS += \
13 | myquickview.h
14 |
15 | RESOURCES += \
16 | underlay.qrc
17 |
18 |
19 |
--------------------------------------------------------------------------------
/underlay/underlay.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | main.qml
4 |
5 |
6 |
--------------------------------------------------------------------------------