summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/abstractaspect.cpp84
-rw-r--r--src/core/abstractaspect.h104
-rw-r--r--src/core/abstracttransform.cpp55
-rw-r--r--src/core/abstracttransform.h64
-rw-r--r--src/core/axisalignedboundingbox.cpp86
-rw-r--r--src/core/axisalignedboundingbox.h157
-rw-r--r--src/core/bounds.cpp61
-rw-r--r--src/core/bounds.h67
-rw-r--r--src/core/cameracontroller.cpp292
-rw-r--r--src/core/cameracontroller.h134
-rw-r--r--src/core/component.cpp65
-rw-r--r--src/core/component.h69
-rw-r--r--src/core/core.pri56
-rw-r--r--src/core/core.pro27
-rw-r--r--src/core/entity.cpp232
-rw-r--r--src/core/entity.h162
-rw-r--r--src/core/lookattransform.cpp112
-rw-r--r--src/core/lookattransform.h93
-rw-r--r--src/core/matrixtransform.cpp60
-rw-r--r--src/core/matrixtransform.h66
-rw-r--r--src/core/node.cpp228
-rw-r--r--src/core/node.h103
-rw-r--r--src/core/nodevisitor.cpp129
-rw-r--r--src/core/nodevisitor.h90
-rw-r--r--src/core/qaspectengine.cpp88
-rw-r--r--src/core/qaspectengine.h80
-rw-r--r--src/core/qaspectmanager.cpp191
-rw-r--r--src/core/qaspectmanager.h92
-rw-r--r--src/core/qaspectscheduler.cpp54
-rw-r--r--src/core/qaspectscheduler.h60
-rw-r--r--src/core/qaspectthread.cpp92
-rw-r--r--src/core/qaspectthread.h76
-rw-r--r--src/core/qchangearbiter.cpp249
-rw-r--r--src/core/qchangearbiter.h232
-rw-r--r--src/core/qjob.cpp59
-rw-r--r--src/core/qjob.h71
-rw-r--r--src/core/qjobmanagerinterface.h70
-rw-r--r--src/core/qjobproviderinterface.h60
-rw-r--r--src/core/qscheduler.cpp92
-rw-r--r--src/core/qscheduler.h69
-rw-r--r--src/core/qt3dcore_global.h53
-rw-r--r--src/core/qtickclock.cpp106
-rw-r--r--src/core/qtickclock.h73
-rw-r--r--src/core/rotatetransform.cpp98
-rw-r--r--src/core/rotatetransform.h91
-rw-r--r--src/core/scene.cpp134
-rw-r--r--src/core/scene.h96
-rw-r--r--src/core/sphere.cpp175
-rw-r--r--src/core/sphere.h138
-rw-r--r--src/core/translatetransform.cpp110
-rw-r--r--src/core/translatetransform.h88
-rw-r--r--src/core/window.cpp249
-rw-r--r--src/core/window.h115
-rw-r--r--src/render/backend/drawable.cpp79
-rw-r--r--src/render/backend/drawable.h103
-rw-r--r--src/render/backend/drawstate.cpp182
-rw-r--r--src/render/backend/drawstate.h121
-rw-r--r--src/render/backend/framegraph/cameraselectornode.cpp65
-rw-r--r--src/render/backend/framegraph/cameraselectornode.h68
-rw-r--r--src/render/backend/framegraph/framegraph.pri15
-rw-r--r--src/render/backend/framegraph/framegraphnode.cpp72
-rw-r--r--src/render/backend/framegraph/framegraphnode.h80
-rw-r--r--src/render/backend/framegraph/framegraphvisitor.cpp86
-rw-r--r--src/render/backend/framegraph/framegraphvisitor.h67
-rw-r--r--src/render/backend/framegraph/renderpassfilternode.cpp65
-rw-r--r--src/render/backend/framegraph/renderpassfilternode.h68
-rw-r--r--src/render/backend/framegraph/techniquefilternode.cpp65
-rw-r--r--src/render/backend/framegraph/techniquefilternode.h69
-rw-r--r--src/render/backend/framegraph/viewportnode.cpp69
-rw-r--r--src/render/backend/framegraph/viewportnode.h68
-rw-r--r--src/render/backend/genericstate.h114
-rw-r--r--src/render/backend/jobs/jobs.pri11
-rw-r--r--src/render/backend/jobs/loadmeshdatajob.cpp89
-rw-r--r--src/render/backend/jobs/loadmeshdatajob.h73
-rw-r--r--src/render/backend/jobs/updateboundingvolumejob.cpp105
-rw-r--r--src/render/backend/jobs/updateboundingvolumejob.h71
-rw-r--r--src/render/backend/jobs/updateworldtransformjob.cpp88
-rw-r--r--src/render/backend/jobs/updateworldtransformjob.h71
-rw-r--r--src/render/backend/meshmanager.cpp64
-rw-r--r--src/render/backend/meshmanager.h81
-rw-r--r--src/render/backend/qgraphicscontext.cpp466
-rw-r--r--src/render/backend/qgraphicscontext.h177
-rw-r--r--src/render/backend/quniformvalue.cpp306
-rw-r--r--src/render/backend/quniformvalue.h142
-rw-r--r--src/render/backend/render-backend.pri52
-rw-r--r--src/render/backend/renderbin.cpp204
-rw-r--r--src/render/backend/renderbin.h94
-rw-r--r--src/render/backend/rendercamera.cpp121
-rw-r--r--src/render/backend/rendercamera.h96
-rw-r--r--src/render/backend/renderconfiguration.cpp52
-rw-r--r--src/render/backend/renderconfiguration.h57
-rw-r--r--src/render/backend/renderdevice.cpp52
-rw-r--r--src/render/backend/renderdevice.h57
-rw-r--r--src/render/backend/renderer.cpp524
-rw-r--r--src/render/backend/renderer.h171
-rw-r--r--src/render/backend/rendereraspect.cpp129
-rw-r--r--src/render/backend/rendereraspect.h78
-rw-r--r--src/render/backend/rendermaterial.cpp204
-rw-r--r--src/render/backend/rendermaterial.h102
-rw-r--r--src/render/backend/rendermesh.cpp333
-rw-r--r--src/render/backend/rendermesh.h125
-rw-r--r--src/render/backend/rendernode.cpp108
-rw-r--r--src/render/backend/rendernode.h90
-rw-r--r--src/render/backend/renderscenebuilder.cpp111
-rw-r--r--src/render/backend/renderscenebuilder.h75
-rw-r--r--src/render/backend/rendershader.cpp150
-rw-r--r--src/render/backend/rendershader.h103
-rw-r--r--src/render/backend/rendertechnique.cpp156
-rw-r--r--src/render/backend/rendertechnique.h94
-rw-r--r--src/render/backend/rendertexture.cpp149
-rw-r--r--src/render/backend/rendertexture.h72
-rw-r--r--src/render/backend/rendertextureprovider.cpp63
-rw-r--r--src/render/backend/rendertextureprovider.h67
-rw-r--r--src/render/backend/renderthread.cpp84
-rw-r--r--src/render/backend/renderthread.h80
-rw-r--r--src/render/backend/states/blendstate.cpp197
-rw-r--r--src/render/backend/states/blendstate.h153
-rw-r--r--src/render/frontend/camera.cpp483
-rw-r--r--src/render/frontend/camera.h184
-rw-r--r--src/render/frontend/camera_p.h129
-rw-r--r--src/render/frontend/cameraselector.cpp65
-rw-r--r--src/render/frontend/cameraselector.h73
-rw-r--r--src/render/frontend/effect.cpp81
-rw-r--r--src/render/frontend/effect.h82
-rw-r--r--src/render/frontend/material.cpp157
-rw-r--r--src/render/frontend/material.h108
-rw-r--r--src/render/frontend/mesh.cpp129
-rw-r--r--src/render/frontend/mesh.h83
-rw-r--r--src/render/frontend/qitemmodelbuffer.cpp289
-rw-r--r--src/render/frontend/qitemmodelbuffer.h103
-rw-r--r--src/render/frontend/render-frontend.pri37
-rw-r--r--src/render/frontend/renderpass.cpp120
-rw-r--r--src/render/frontend/renderpass.h104
-rw-r--r--src/render/frontend/renderpassfilter.cpp64
-rw-r--r--src/render/frontend/renderpassfilter.h73
-rw-r--r--src/render/frontend/shaderprogram.cpp133
-rw-r--r--src/render/frontend/shaderprogram.h92
-rw-r--r--src/render/frontend/shape.cpp386
-rw-r--r--src/render/frontend/shape.h118
-rw-r--r--src/render/frontend/tag.h97
-rw-r--r--src/render/frontend/technique.cpp281
-rw-r--r--src/render/frontend/technique.h194
-rw-r--r--src/render/frontend/techniquefilter.cpp95
-rw-r--r--src/render/frontend/techniquefilter.h80
-rw-r--r--src/render/frontend/texture.cpp101
-rw-r--r--src/render/frontend/texture.h86
-rw-r--r--src/render/frontend/transform.cpp147
-rw-r--r--src/render/frontend/transform.h94
-rw-r--r--src/render/frontend/viewport.cpp64
-rw-r--r--src/render/frontend/viewport.h76
-rw-r--r--src/render/io/gltfparser.cpp842
-rw-r--r--src/render/io/gltfparser.h157
-rw-r--r--src/render/io/meshdata.cpp422
-rw-r--r--src/render/io/meshdata.h181
-rw-r--r--src/render/io/objloader.cpp442
-rw-r--r--src/render/io/objloader.h143
-rw-r--r--src/render/io/render-io.pri13
-rw-r--r--src/render/io/texturedata.cpp167
-rw-r--r--src/render/io/texturedata.h164
-rw-r--r--src/render/render.pri3
-rw-r--r--src/src.pro6
-rw-r--r--sync.profile1
162 files changed, 20107 insertions, 2 deletions
diff --git a/src/core/abstractaspect.cpp b/src/core/abstractaspect.cpp
new file mode 100644
index 000000000..3096aa58f
--- /dev/null
+++ b/src/core/abstractaspect.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractaspect.h"
+
+namespace Qt3D {
+
+AbstractAspect::AbstractAspect(AspectType aspectType, QObject *parent)
+ : QObject(parent)
+ , m_aspectType(aspectType)
+{
+}
+
+void AbstractAspect::registerAspect(Node *rootObject)
+{
+ if (rootObject == m_root)
+ return;
+
+ m_root = rootObject;
+ registerAspectHelper(rootObject);
+}
+
+void AbstractAspect::unregisterAspect(Node *rootObject)
+{
+ unregisterAspectHelper(rootObject);
+ m_root = rootObject;
+}
+
+void AbstractAspect::initialize(QAspectManager *aspectManager)
+{
+ m_aspectManager = aspectManager;
+ initializeHelper(aspectManager);
+}
+
+void AbstractAspect::cleanup()
+{
+ cleanupHelper();
+}
+
+void AbstractAspect::setWindow(QWindow *win)
+{
+ Q_UNUSED(win);
+}
+
+} // of namespace Qt3D
+
diff --git a/src/core/abstractaspect.h b/src/core/abstractaspect.h
new file mode 100644
index 000000000..7dd555b32
--- /dev/null
+++ b/src/core/abstractaspect.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTASPECT_H
+#define ABSTRACTASPECT_H
+
+#include <QObject>
+#include "qt3dcore_global.h"
+
+#include "qjobproviderinterface.h"
+
+#include <QSharedPointer>
+
+// forward decls
+class QWindow;
+
+namespace Qt3D {
+
+class QAspectManager;
+class Node;
+
+class QT3DCORESHARED_EXPORT AbstractAspect : public QObject, public QJobProviderInterface
+{
+ Q_OBJECT
+
+public:
+ enum AspectType {
+ AspectRenderer,
+ AspectAnimation,
+ AspectCollision,
+ AspectPhysics,
+ AspectPhysicsAndCollision,
+ AspectAI,
+ AspectAudio,
+ AspectOther
+ };
+
+ explicit AbstractAspect(AspectType aspectType, QObject *parent = 0);
+
+ AspectType aspectType() const { return m_aspectType; }
+ QAspectManager *aspectManager() const { return m_aspectManager; }
+
+ void registerAspect(Node *rootObject);
+ void unregisterAspect(Node *rootObject);
+
+ void initialize(QAspectManager *aspectManager);
+ void cleanup();
+
+ virtual void setWindow(QWindow* win);
+
+protected:
+ virtual void registerAspectHelper(Node *rootObject) = 0;
+ virtual void unregisterAspectHelper(Node *rootObject) = 0;
+
+ virtual void initializeHelper(QAspectManager *aspectManager) = 0;
+ virtual void cleanupHelper() = 0;
+
+private:
+ QAspectManager *m_aspectManager;
+ Node *m_root;
+ AspectType m_aspectType;
+};
+
+}
+
+#endif // ABSTRACTASPECT_H
diff --git a/src/core/abstracttransform.cpp b/src/core/abstracttransform.cpp
new file mode 100644
index 000000000..a7a892259
--- /dev/null
+++ b/src/core/abstracttransform.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstracttransform.h"
+
+namespace Qt3D {
+
+AbstractTransform::AbstractTransform(Node *parent)
+ : Node(parent)
+{
+}
+
+AbstractTransform::~AbstractTransform()
+{
+}
+
+} // of namespace Qt3D
diff --git a/src/core/abstracttransform.h b/src/core/abstracttransform.h
new file mode 100644
index 000000000..1715bd70c
--- /dev/null
+++ b/src/core/abstracttransform.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_ABSTRACT_TRANSFORM_H
+#define QT3D_ABSTRACT_TRANSFORM_H
+
+#include <node.h>
+#include "qt3dcore_global.h"
+
+#include <QMatrix4x4>
+
+namespace Qt3D {
+
+class AbstractTransform : public Node
+{
+ Q_OBJECT
+public:
+ explicit AbstractTransform(Node *parent = 0);
+ virtual ~AbstractTransform();
+
+ virtual QMatrix4x4 matrix() const = 0;
+};
+
+} // of namespace Qt3D
+
+#endif // of QT3D_ABSTRACT_TRANSFORM_H
diff --git a/src/core/axisalignedboundingbox.cpp b/src/core/axisalignedboundingbox.cpp
new file mode 100644
index 000000000..8ee394127
--- /dev/null
+++ b/src/core/axisalignedboundingbox.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "axisalignedboundingbox.h"
+
+#include <QDebug>
+#include <QMatrix4x4>
+
+namespace Qt3D {
+
+void AxisAlignedBoundingBox::update(const QVector<QVector3D> &points)
+{
+ QVector3D minPoint, maxPoint;
+ for (int i = 0; i < points.size(); ++i)
+ {
+ const QVector3D &point = points.at(i);
+ if (point.x() > maxPoint.x())
+ maxPoint.setX(point.x());
+ if (point.y() > maxPoint.y())
+ maxPoint.setY(point.y());
+ if (point.z() > maxPoint.z())
+ maxPoint.setZ(point.z());
+ if (point.x() < minPoint.x())
+ minPoint.setX(point.x());
+ if (point.y() < minPoint.y())
+ minPoint.setY(point.y());
+ if (point.z() < minPoint.z())
+ minPoint.setZ(point.z());
+ }
+
+ m_center = 0.5 * (minPoint + maxPoint);
+ m_radii = 0.5 * (maxPoint - minPoint);
+#if 0
+ qDebug() << "AABB:";
+ qDebug() << " min =" << minPoint;
+ qDebug() << " max =" << maxPoint;
+ qDebug() << " center =" << m_center;
+ qDebug() << " radii =" << m_radii;
+#endif
+}
+
+QDebug operator<<(QDebug dbg, const AxisAlignedBoundingBox &c)
+{
+ dbg.nospace() << "AABB ( min:" << c.minPoint() << ", max:" << c.maxPoint() << ")";
+ return dbg.space();
+}
+
+}
diff --git a/src/core/axisalignedboundingbox.h b/src/core/axisalignedboundingbox.h
new file mode 100644
index 000000000..e16dda1a8
--- /dev/null
+++ b/src/core/axisalignedboundingbox.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AXIS_ALIGNED_BOUNDING_BOX
+#define AXIS_ALIGNED_BOUNDING_BOX
+
+#include "qt3dcore_global.h"
+
+#include <QMatrix4x4>
+#include <QVector>
+#include <QVector3D>
+
+// forward decls
+class QDebug;
+
+namespace Qt3D {
+
+class AxisAlignedBoundingBox
+{
+public:
+ inline AxisAlignedBoundingBox()
+ : m_center(),
+ m_radii()
+ {}
+
+ inline explicit AxisAlignedBoundingBox(const QVector<QVector3D> &points)
+ : m_center(),
+ m_radii()
+ {
+ update(points);
+ }
+
+ void clear()
+ {
+ m_center = QVector3D();
+ m_radii = QVector3D();
+ }
+
+ void update(const QVector<QVector3D> &points);
+
+ inline QVector3D center() const { return m_center; }
+ inline QVector3D radii() const { return m_radii; }
+
+ inline QVector3D minPoint() const { return m_center - m_radii; }
+ inline QVector3D maxPoint() const { return m_center + m_radii; }
+
+ inline float xExtent() const { return 2.0f * m_radii.x(); }
+ inline float yExtent() const { return 2.0f * m_radii.y(); }
+ inline float zExtent() const { return 2.0f * m_radii.z(); }
+
+ inline float maxExtent() const { return qMax( xExtent(), qMax( yExtent(), zExtent() ) ); }
+ inline float minExtent() const { return qMin( xExtent(), qMin( yExtent(), zExtent() ) ); }
+
+ inline bool contains( const QVector3D& pt ) const
+ {
+ QVector3D minP(minPoint()), maxP(maxPoint());
+ if ((pt.x() < minP.x()) || (pt.x() > maxP.x()) ||
+ (pt.y() < minP.y()) || (pt.y() > maxP.y()) ||
+ (pt.z() < minP.z()) || (pt.z() > maxP.z()) )
+ {
+ return false;
+ }
+ return true;
+ }
+
+ inline void expandToContain(const QVector3D &pt)
+ {
+ QVector<QVector3D> pts = QVector<QVector3D>() << pt;
+ update(pts);
+ }
+
+ inline void expandToContain(const AxisAlignedBoundingBox &other)
+ {
+ QVector<QVector3D> pts = QVector<QVector3D>() << other.minPoint() << other.maxPoint();
+ update(pts);
+ }
+
+ inline AxisAlignedBoundingBox transformBy(const QMatrix4x4 &mat) const
+ {
+ AxisAlignedBoundingBox r;
+ r.m_center = mat.map(m_center);
+ r.m_radii = mat.map(m_radii);
+ return r;
+ }
+
+ inline AxisAlignedBoundingBox &transform(const QMatrix4x4 &mat)
+ {
+ m_center = mat.map(m_center);
+ m_radii = mat.map(m_radii);
+ return *this;
+ }
+
+private:
+ QVector3D m_center;
+ QVector3D m_radii;
+
+ friend bool intersects(const AxisAlignedBoundingBox &a,
+ const AxisAlignedBoundingBox &b);
+};
+
+QDebug operator<<(QDebug dbg, const AxisAlignedBoundingBox &c);
+
+inline bool intersects(const AxisAlignedBoundingBox &a,
+ const AxisAlignedBoundingBox &b)
+{
+ // Test y axis last as this is often the least discriminatory in OpenGL applications
+ // where worlds tend to be mostly in the xz-plane
+ if (qAbs(a.m_center[0] - b.m_center[0]) > a.m_radii[0] + b.m_radii[0])
+ return false;
+ if (qAbs(a.m_center[2] - b.m_center[2]) > a.m_radii[2] + b.m_radii[2])
+ return false;
+ if (qAbs(a.m_center[1] - b.m_center[1]) > a.m_radii[1] + b.m_radii[1])
+ return false;
+ return true;
+}
+
+}
+
+#endif // AXIS_ALIGNED_BOUNDING_BOX
diff --git a/src/core/bounds.cpp b/src/core/bounds.cpp
new file mode 100644
index 000000000..89db913ae
--- /dev/null
+++ b/src/core/bounds.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "bounds.h"
+
+namespace Qt3D {
+
+Bounds::Bounds(QObject *parent) :
+ QObject(parent)
+{
+}
+
+AxisAlignedBoundingBox Bounds::box() const
+{
+ return m_box;
+}
+
+void Bounds::setBox( const AxisAlignedBoundingBox& aabb )
+{
+ m_box = aabb;
+}
+
+}
diff --git a/src/core/bounds.h b/src/core/bounds.h
new file mode 100644
index 000000000..cf59d7776
--- /dev/null
+++ b/src/core/bounds.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BOUNDS_H
+#define BOUNDS_H
+
+#include <QObject>
+#include "qt3dcore_global.h"
+
+#include "axisalignedboundingbox.h"
+
+namespace Qt3D {
+
+class Bounds : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Bounds(QObject *parent = 0);
+
+ AxisAlignedBoundingBox box() const;
+ void setBox( const AxisAlignedBoundingBox& aabb );
+
+private:
+ AxisAlignedBoundingBox m_box;
+};
+
+}
+
+#endif // BOUNDS_H
diff --git a/src/core/cameracontroller.cpp b/src/core/cameracontroller.cpp
new file mode 100644
index 000000000..10d1aa386
--- /dev/null
+++ b/src/core/cameracontroller.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "cameracontroller.h"
+
+#include <QMouseEvent>
+#include <QKeyEvent>
+
+#include "camera.h"
+#include "entity.h"
+#include "matrixtransform.h"
+
+namespace Qt3D
+{
+
+CameraController::CameraController() :
+ m_camera( 0 ),
+ m_vx( 0.0f ),
+ m_vy( 0.0f ),
+ m_vz( 0.0f ),
+ m_viewCenterFixed( false ),
+ m_panAngle( 0.0f ),
+ m_tiltAngle( 0.0f ),
+ m_leftButtonPressed( false ),
+ m_orbitMode( false ),
+ m_linearSpeed( 40.0f ),
+ m_time( 0.0f ),
+ m_orbitRate( -1.0f ),
+ m_lookRate( 0.1f ),
+ m_translateFast( false ),
+ m_multisampleEnabled( true )
+{
+}
+
+void CameraController::setCamera( Camera* cam )
+{
+ m_camera = cam;
+ m_camera->setPerspectiveProjection( 25.0, 1.0, 0.1, 1000 );
+
+ Entity* cameraEntity = cam->parentNode()->asEntity();
+ Q_ASSERT(cameraEntity);
+ m_cameraEntity = cameraEntity;
+}
+
+void CameraController::setLinearSpeed( float speed )
+{
+ if ( qFuzzyCompare( m_linearSpeed, speed ) )
+ return;
+ m_linearSpeed = speed;
+ emit linearSpeedChanged();
+}
+
+float CameraController::linearSpeed() const
+{
+ return m_linearSpeed;
+}
+
+float CameraController::orbitRate() const
+{
+ return m_orbitRate;
+}
+
+void CameraController::setOrbitRate( float rate )
+{
+ if ( qFuzzyCompare( m_orbitRate, rate ) )
+ return;
+ m_orbitRate = rate;
+ emit orbitRateChanged();
+}
+
+float CameraController::lookRate() const
+{
+ return m_lookRate;
+}
+
+void CameraController::setLookRate( float rate )
+{
+ if ( qFuzzyCompare( m_lookRate, rate ) )
+ return;
+ m_lookRate = rate;
+ emit lookRateChanged();
+}
+
+void CameraController::update(double dt)
+{
+ if ( !m_camera )
+ return;
+
+ if (m_translateFast)
+ dt *= 10;
+
+ // Update the camera position and orientation
+ Camera::CameraTranslationOption option = m_viewCenterFixed
+ ? Camera::DontTranslateViewCenter
+ : Camera::TranslateViewCenter;
+ m_camera->translate(dt * QVector3D(m_vx, m_vy, m_vz), option);
+
+ m_cameraEntity->setMatrix(m_camera->viewMatrix().inverted());
+
+ if (!qFuzzyIsNull(m_panAngle)) {
+ m_camera->pan(m_panAngle);
+ m_panAngle = 0.0f;
+ }
+
+ if (!qFuzzyIsNull(m_tiltAngle)) {
+ m_camera->tilt(m_tiltAngle);
+ m_tiltAngle = 0.0f;
+ }
+}
+
+bool CameraController::keyPressEvent( QKeyEvent* e )
+{
+ switch ( e->key() )
+ {
+ case Qt::Key_Right:
+ m_vx = m_linearSpeed;
+ break;
+
+ case Qt::Key_Left:
+ m_vx = -m_linearSpeed;
+ break;
+
+ case Qt::Key_Up:
+ m_vz = m_linearSpeed;
+ break;
+
+ case Qt::Key_Down:
+ m_vz = -m_linearSpeed;
+ break;
+
+ case Qt::Key_PageUp:
+ m_vy = m_linearSpeed;
+ break;
+
+ case Qt::Key_PageDown:
+ m_vy = -m_linearSpeed;
+ break;
+
+ case Qt::Key_Shift:
+ m_viewCenterFixed = true;
+ break;
+
+ case Qt::Key_Alt:
+ m_translateFast = true;
+ break;
+
+ case Qt::Key_A:
+ toggleMSAA();
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool CameraController::keyReleaseEvent( QKeyEvent* e )
+{
+ switch ( e->key() )
+ {
+ case Qt::Key_Right:
+ case Qt::Key_Left:
+ m_vx = 0.0;
+ break;
+
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ m_vz = 0.0;
+ break;
+
+ case Qt::Key_PageUp:
+ case Qt::Key_PageDown:
+ m_vy = 0.0;
+ break;
+
+ case Qt::Key_Shift:
+ m_viewCenterFixed = false;
+ break;
+
+ case Qt::Key_Alt:
+ m_translateFast = false;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+void CameraController::mousePressEvent( QMouseEvent* e )
+{
+ if ( e->button() == Qt::LeftButton )
+ {
+ m_leftButtonPressed = true;
+ m_pos = m_prevPos = e->pos();
+ }
+ else if ( e->button() == Qt::RightButton )
+ {
+ m_orbitMode = true;
+ m_pos = m_prevPos = e->pos();
+ }
+}
+
+void CameraController::mouseReleaseEvent( QMouseEvent* e )
+{
+ if ( e->button() == Qt::LeftButton )
+ {
+ m_leftButtonPressed = false;
+ }
+ else if ( e->button() == Qt::RightButton )
+ {
+ m_orbitMode = false;
+ }
+}
+
+void CameraController::mouseMoveEvent( QMouseEvent* e )
+{
+ if (!m_camera )
+ return;
+
+ if (!m_leftButtonPressed && !m_orbitMode)
+ return;
+
+ m_pos = e->pos();
+ float dx = m_pos.x() - m_prevPos.x();
+ float dy = m_pos.y() - m_prevPos.y();
+ m_prevPos = m_pos;
+
+ if ( m_leftButtonPressed )
+ {
+ m_camera->pan( dx * m_lookRate );
+ m_camera->tilt( dy * m_lookRate );
+ }
+ else if ( m_orbitMode )
+ {
+ m_camera->panAboutViewCenter( dx * m_orbitRate );
+ m_camera->tiltAboutViewCenter( dy * m_orbitRate );
+ }
+}
+
+bool CameraController::isMultisampleEnabled() const
+{
+ return m_multisampleEnabled;
+}
+
+void CameraController::toggleMSAA()
+{
+ m_multisampleEnabled = !m_multisampleEnabled;
+ emit multisampleEnabledChanged();
+}
+
+} // of namespace Qt3D
diff --git a/src/core/cameracontroller.h b/src/core/cameracontroller.h
new file mode 100644
index 000000000..28a9ec6cd
--- /dev/null
+++ b/src/core/cameracontroller.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CAMERA_CONTROLLER_H
+#define CAMERA_CONTROLLER_H
+
+#include <QObject>
+#include "qt3dcore_global.h"
+
+#include <QPoint>
+
+class QMouseEvent;
+class QWheelEvent;
+class QKeyEvent;
+
+
+namespace Qt3D
+{
+
+class Camera;
+class Entity;
+
+class CameraController : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY( float linearSpeed READ linearSpeed WRITE setLinearSpeed NOTIFY linearSpeedChanged )
+
+ Q_PROPERTY( float orbitRate READ orbitRate WRITE setOrbitRate NOTIFY orbitRateChanged )
+ Q_PROPERTY( float lookRate READ lookRate WRITE setLookRate NOTIFY lookRateChanged )
+
+ Q_PROPERTY( bool multisampleEnabled READ isMultisampleEnabled() NOTIFY multisampleEnabledChanged )
+public:
+ CameraController();
+
+ void setCamera( Camera* cam );
+ void setLinearSpeed( float speed );
+ float linearSpeed() const;
+
+ float orbitRate() const;
+ void setOrbitRate( float rate );
+
+ float lookRate() const;
+ void setLookRate( float rate );
+
+ void mousePressEvent( QMouseEvent* aEvent );
+ void mouseReleaseEvent( QMouseEvent* aEvent );
+ void mouseMoveEvent( QMouseEvent* aEvent );
+
+ bool keyPressEvent( QKeyEvent* aEvent );
+ bool keyReleaseEvent( QKeyEvent* aEvent );
+
+ bool handleScroll( QWheelEvent* aWheel );
+
+ void update( double t );
+
+ bool isMultisampleEnabled() const;
+public slots:
+ void toggleMSAA();
+
+
+
+signals:
+ void linearSpeedChanged();
+ void orbitRateChanged();
+ void lookRateChanged();
+
+ void multisampleEnabledChanged();
+private:
+
+ Camera* m_camera;
+ Entity* m_cameraEntity;
+
+ float m_vx;
+ float m_vy;
+ float m_vz;
+ bool m_viewCenterFixed;
+ float m_panAngle;
+ float m_tiltAngle;
+
+ bool m_leftButtonPressed;
+ QPoint m_prevPos;
+ QPoint m_pos;
+ bool m_orbitMode;
+
+ float m_linearSpeed;
+ float m_time;
+ float m_orbitRate;
+ float m_lookRate;
+
+ bool m_translateFast;
+ bool m_multisampleEnabled;
+};
+
+} // of namespace Qt3D
+
+#endif // of CAMERA_CONTROLLER_H
diff --git a/src/core/component.cpp b/src/core/component.cpp
new file mode 100644
index 000000000..9f5e3a26c
--- /dev/null
+++ b/src/core/component.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "component.h"
+
+namespace Qt3D {
+
+Component::Component(Node *parent)
+ : Node(parent)
+ , m_changeArbiter(0)
+{
+}
+
+void Component::registerChangeArbiter(QChangeArbiter *changeArbiter)
+{
+ Q_CHECK_PTR(changeArbiter);
+ m_changeArbiter = changeArbiter;
+}
+
+void Component::notifySceneChange(const QSceneChangePtr &change)
+{
+ Q_CHECK_PTR(change);
+ if (m_changeArbiter)
+ m_changeArbiter->sceneChangeEventWithLock(change);
+}
+
+} // namespace Qt3D
diff --git a/src/core/component.h b/src/core/component.h
new file mode 100644
index 000000000..608015e95
--- /dev/null
+++ b/src/core/component.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_COMPONENT_H
+#define QT3D_COMPONENT_H
+
+#include "node.h"
+#include "qt3dcore_global.h"
+
+#include <qchangearbiter.h>
+
+namespace Qt3D {
+
+class Component : public Node
+{
+ Q_OBJECT
+public:
+ explicit Component(Node *parent = 0);
+
+ void registerChangeArbiter(QChangeArbiter *changeArbiter);
+
+protected:
+ virtual void notifySceneChange(const QSceneChangePtr &change);
+
+private:
+ QChangeArbiter *m_changeArbiter;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_COMPONENT_H
diff --git a/src/core/core.pri b/src/core/core.pri
new file mode 100644
index 000000000..5f062c585
--- /dev/null
+++ b/src/core/core.pri
@@ -0,0 +1,56 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qt3dcore_global.h \
+ $$PWD/abstractaspect.h \
+ $$PWD/node.h \
+ $$PWD/nodevisitor.h \
+ $$PWD/abstracttransform.h \
+ $$PWD/matrixtransform.h \
+ $$PWD/axisalignedboundingbox.h \
+ $$PWD/sphere.h \
+ $$PWD/bounds.h \
+ $$PWD/component.h \
+ $$PWD/window.h \
+ $$PWD/qaspectengine.h \
+ $$PWD/qaspectscheduler.h \
+ $$PWD/qaspectthread.h \
+ $$PWD/qaspectmanager.h \
+ $$PWD/qtickclock.h \
+ $$PWD/entity.h \
+ $$PWD/scene.h \
+ $$PWD/qjob.h \
+ $$PWD/qjobmanagerinterface.h \
+ $$PWD/qscheduler.h \
+ $$PWD/qjobproviderinterface.h \
+ $$PWD/cameracontroller.h \
+ $$PWD/translatetransform.h \
+ $$PWD/rotatetransform.h \
+ $$PWD/qchangearbiter.h \
+ $$PWD/lookattransform.h
+
+SOURCES += \
+ $$PWD/abstractaspect.cpp \
+ $$PWD/node.cpp \
+ $$PWD/nodevisitor.cpp \
+ $$PWD/abstracttransform.cpp \
+ $$PWD/matrixtransform.cpp \
+ $$PWD/axisalignedboundingbox.cpp \
+ $$PWD/sphere.cpp \
+ $$PWD/bounds.cpp \
+ $$PWD/component.cpp \
+ $$PWD/window.cpp \
+ $$PWD/qaspectengine.cpp \
+ $$PWD/qaspectscheduler.cpp \
+ $$PWD/qaspectthread.cpp \
+ $$PWD/qaspectmanager.cpp \
+ $$PWD/qtickclock.cpp \
+ $$PWD/entity.cpp \
+ $$PWD/scene.cpp \
+ $$PWD/qjob.cpp \
+ $$PWD/qscheduler.cpp \
+ $$PWD/cameracontroller.cpp \
+ $$PWD/translatetransform.cpp \
+ $$PWD/rotatetransform.cpp \
+ $$PWD/qchangearbiter.cpp \
+ $$PWD/lookattransform.cpp
diff --git a/src/core/core.pro b/src/core/core.pro
new file mode 100644
index 000000000..c599bbdba
--- /dev/null
+++ b/src/core/core.pro
@@ -0,0 +1,27 @@
+TARGET = Qt3DCore
+MODULE = 3dcore
+QT = core-private gui-private qml qml-private quick
+
+load(qt_module)
+
+DEFINES += QT3DCORE_LIBRARY
+
+#QMAKE_DOCS = $$PWD/doc/qt3d.qdocconf
+
+gcov {
+ CONFIG += static
+ QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
+ QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
+} else {
+ CONFIG += dll
+}
+
+# otherwise mingw headers do not declare common functions like ::strcasecmp
+win32-g++*:QMAKE_CXXFLAGS_CXX11 = -std=gnu++0x
+
+include(core.pri)
+include(../render/render.pri)
+PUBLIC_HEADERS = $$HEADERS
+HEADERS += $$PRIVATE_HEADERS
+
+!contains(QT_CONFIG, egl):DEFINES += QT_NO_EGL
diff --git a/src/core/entity.cpp b/src/core/entity.cpp
new file mode 100644
index 000000000..136778216
--- /dev/null
+++ b/src/core/entity.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "entity.h"
+
+#include "component.h"
+#include "abstracttransform.h"
+#include "matrixtransform.h"
+
+#include <QMetaObject>
+#include <QMetaProperty>
+#include <QDebug>
+
+namespace Qt3D {
+
+Entity::Entity(Node *parent)
+ : Node(parent)
+ , m_enabled(true)
+{
+}
+
+QQmlListProperty<AbstractTransform> Entity::transformList()
+{
+ return QQmlListProperty<AbstractTransform>(this, 0,
+ Entity::qmlAppendTransform,
+ Entity::transformCount,
+ Entity::transformAt,
+ Entity::qmlClearTransforms);
+}
+
+QList<Component *> Entity::components() const
+{
+ // Construct the list of components by looking for all properties that
+ // inherit from Component
+ QList<Component *> componentList;
+ const QMetaObject *meta = metaObject();
+ for (int i = 0; i < meta->propertyCount(); ++i) {
+ const QMetaProperty metaProperty = meta->property(i);
+ const QVariant value = property(metaProperty.name());
+ Component *component = value.value<Component *>();
+ if (component)
+ componentList.append(component);
+ }
+
+ return componentList + m_components;
+}
+
+void Entity::addComponent(Component *comp)
+{
+ Q_CHECK_PTR( comp );
+ Q_ASSERT(m_components.count(comp) == 0);
+ comp->setParent(this);
+ m_components.append(comp);
+}
+
+void Entity::removeComponent(Component *comp)
+{
+ Q_CHECK_PTR(comp);
+ m_components.removeOne(comp);
+}
+
+bool Entity::isEnabled() const
+{
+ return m_enabled;
+}
+
+void Entity::setEnabled(bool on)
+{
+ if (m_enabled != on) {
+ m_enabled = on;
+ emit enabledChanged();
+ }
+}
+
+QMatrix4x4 Entity::matrix() const
+{
+ if (m_transformsDirty) {
+ m_matrix = applyTransforms();
+ m_transformsDirty = false;
+ }
+ return m_matrix;
+}
+
+void Entity::update()
+{
+ if (m_transformsDirty) {
+ m_matrix = applyTransforms();
+ m_transformsDirty = false;
+ }
+
+ QMatrix4x4 prM;
+ if (parentEntity())
+ prM = parentEntity()->sceneMatrix();
+
+ m_sceneMatrix = prM * matrix();
+ // invalidate bounding volume information as required
+}
+
+void Entity::setMatrix(const QMatrix4x4 &m)
+{
+ qDeleteAll(m_transforms);
+ m_transforms.clear();
+ appendTransfrom(new MatrixTransform(m));
+}
+
+/*!
+ The combined transform relative to the root of the scene
+*/
+QMatrix4x4 Entity::sceneMatrix() const
+{
+ return m_sceneMatrix;
+}
+
+/*!
+ The center of rotation for the entity. Defaults to the local origin.
+*/
+QVector3D Entity::rotationCenter() const
+{
+ return QVector3D();
+}
+
+QList<AbstractTransform *> Entity::transforms() const
+{
+ return m_transforms;
+}
+
+void setRotationCenter(const QVector3D &rc)
+{
+ Q_UNUSED(rc);
+}
+
+void Entity::appendTransfrom(AbstractTransform *xform)
+{
+ m_transformsDirty = true;
+ m_transforms.append( xform );
+}
+
+void Entity::removeTransform(AbstractTransform *xform)
+{
+ m_transformsDirty = true;
+ m_transforms.removeOne( xform );
+}
+
+Entity *Entity::asEntity()
+{
+ return this;
+}
+
+Entity *Entity::parentEntity()
+{
+ return qobject_cast<Entity*>(parent());
+}
+
+QMatrix4x4 Entity::applyTransforms() const
+{
+ QMatrix4x4 m;
+ m.setToIdentity();
+ Q_FOREACH (AbstractTransform *t, m_transforms)
+ m = t->matrix() * m;
+ return m;
+}
+
+
+void Entity::qmlAppendTransform(QQmlListProperty<AbstractTransform> *list, AbstractTransform *obj )
+{
+ if ( !obj )
+ return;
+
+ Entity* self = static_cast<Entity*>(list->object);
+ self->appendTransfrom(obj);
+}
+
+AbstractTransform* Entity::transformAt(QQmlListProperty<AbstractTransform>* list, int index)
+{
+ Entity* self = static_cast<Entity*>(list->object);
+ return self->transforms().at(index);
+}
+
+int Entity::transformCount(QQmlListProperty<AbstractTransform>* list)
+{
+ Entity* self = static_cast<Entity*>(list->object);
+ return self->transforms().count();
+}
+
+void Entity::qmlClearTransforms(QQmlListProperty<AbstractTransform> *list)
+{
+ Entity* self = static_cast<Entity*>(list->object);
+ qDeleteAll(self->m_transforms);
+ self->m_transforms.clear();
+ self->m_transformsDirty = true;
+}
+
+
+} // namespace Qt3D
diff --git a/src/core/entity.h b/src/core/entity.h
new file mode 100644
index 000000000..e79856e70
--- /dev/null
+++ b/src/core/entity.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_ENTITY_H
+#define QT3D_ENTITY_H
+
+#include "node.h"
+#include "qt3dcore_global.h"
+
+#include <QMatrix4x4>
+
+namespace Qt3D {
+
+class AbstractTransform;
+class Component;
+
+typedef QList<Component*> ComponentList;
+
+class Entity : public Node
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+
+ Q_PROPERTY(QQmlListProperty<Qt3D::AbstractTransform> transforms READ transformList)
+
+
+public:
+ explicit Entity(Node *parent = 0);
+
+ ComponentList components() const;
+
+ template <class T>
+ QList<T*> componentsOfType() const
+ {
+ QList<T*> result;
+ foreach (Component* comp, components()) {
+ T* i = qobject_cast<T*>(comp);
+ if (i)
+ result.append(i);
+ }
+
+ return result;
+ }
+
+ template <class T>
+ static T* findComponentInTree(Node* root)
+ {
+ if (!root)
+ return NULL;
+
+ if (root->asEntity()) {
+ foreach (Component* comp, root->asEntity()->components()) {
+ T* i = qobject_cast<T*>(comp);
+ if (i)
+ return i;
+ } // of component iteration
+ } // of is-entity
+
+ foreach (Node* child, root->children()) {
+ T* i = findComponentInTree<T>(child);
+ if (i)
+ return i;
+ } // of child nodes iteration
+
+ return NULL;
+ }
+
+ void addComponent(Component *comp);
+ void removeComponent(Component *comp);
+
+ bool isEnabled() const;
+ void setEnabled(bool on);
+
+ QMatrix4x4 matrix() const;
+ void setMatrix(const QMatrix4x4 &m);
+
+ QMatrix4x4 sceneMatrix() const;
+
+ QVector3D rotationCenter() const;
+ void setRotationCenter(const QVector3D &rc);
+
+ QList<AbstractTransform*> transforms() const;
+
+ // void insertTransformAt(...)
+ Q_INVOKABLE void appendTransfrom(AbstractTransform *xform);
+ Q_INVOKABLE void removeTransform(AbstractTransform *xform);
+
+ virtual Entity* asEntity();
+
+ Entity* parentEntity();
+
+ // TEMPORARY - should be driven by an Update traversal in the core
+ void update();
+signals:
+ void enabledChanged();
+
+private:
+ QQmlListProperty<Qt3D::AbstractTransform> transformList();
+
+ ComponentList m_components;
+
+ QMatrix4x4 applyTransforms() const;
+
+ mutable bool m_transformsDirty;
+ bool m_visible;
+ QList<AbstractTransform*> m_transforms;
+
+ mutable QMatrix4x4 m_matrix;
+ QMatrix4x4 m_sceneMatrix;
+
+ // TODO: Is a bool enough here or do we need additional states for entities?
+ // Perhaps aboutToBeDeleted would be useful?
+ bool m_enabled;
+
+ static void qmlAppendTransform(QQmlListProperty<Qt3D::AbstractTransform> *list, Qt3D::AbstractTransform *bar);
+ static AbstractTransform* transformAt(QQmlListProperty<Qt3D::AbstractTransform> *list, int index);
+ static int transformCount(QQmlListProperty<Qt3D::AbstractTransform> *list);
+ static void qmlClearTransforms(QQmlListProperty<Qt3D::AbstractTransform> *list);
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_ENTITY_H
diff --git a/src/core/lookattransform.cpp b/src/core/lookattransform.cpp
new file mode 100644
index 000000000..6d2109906
--- /dev/null
+++ b/src/core/lookattransform.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "lookattransform.h"
+
+namespace Qt3D {
+
+LookAtTransform::LookAtTransform(Node *parent)
+ : AbstractTransform(parent)
+{
+}
+
+QMatrix4x4 LookAtTransform::matrix() const
+{
+ if (m_matrixDirty) {
+ m_matrix.setToIdentity();
+ m_matrix.lookAt(m_position, m_viewCenter, m_upVector);
+ m_matrixDirty = false;
+ }
+ return m_matrix;
+}
+
+QVector3D LookAtTransform::position() const
+{
+ return m_position;
+}
+
+void LookAtTransform::setPosition(const QVector3D &position)
+{
+ if (m_position != position) {
+ m_position = position;
+ m_viewVector = m_viewCenter - position;
+ m_matrixDirty = true;
+ emit positionChanged();
+ emit viewVectorChanged();
+ }
+}
+
+void LookAtTransform::setUpVector(const QVector3D &upVector)
+{
+ if (m_upVector != upVector) {
+ m_upVector = upVector;
+ m_matrixDirty = true;
+ emit upVectorChanged();
+ }
+}
+
+QVector3D LookAtTransform::upVector() const
+{
+ return m_upVector;
+}
+
+void LookAtTransform::setViewCenter(const QVector3D &viewCenter)
+{
+ if (m_viewCenter != viewCenter) {
+ m_viewCenter = viewCenter;
+ m_viewVector = viewCenter - m_position;
+ m_matrixDirty = true;
+ emit viewCenterChanged();
+ emit viewVectorChanged();
+ }
+}
+
+QVector3D LookAtTransform::viewCenter() const
+{
+ return m_viewCenter;
+}
+
+QVector3D LookAtTransform::viewVector() const
+{
+ return m_viewVector;
+}
+
+} // namespace Qt3D
diff --git a/src/core/lookattransform.h b/src/core/lookattransform.h
new file mode 100644
index 000000000..c032f32dc
--- /dev/null
+++ b/src/core/lookattransform.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_LOOKATTRANSFORM_H
+#define QT3D_LOOKATTRANSFORM_H
+
+#include "abstracttransform.h"
+#include "qt3dcore_global.h"
+
+#include <QVector3D>
+
+namespace Qt3D {
+
+class LookAtTransform : public Qt3D::AbstractTransform
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector3D position READ position WRITE setPosition)
+ Q_PROPERTY(QVector3D upVector READ upVector WRITE setUpVector)
+ Q_PROPERTY(QVector3D viewCenter READ viewCenter WRITE setViewCenter)
+ Q_PROPERTY(QVector3D viewVector READ viewVector NOTIFY viewVectorChanged)
+
+public:
+ explicit LookAtTransform(Node *parent = 0);
+
+ QMatrix4x4 matrix() const Q_DECL_OVERRIDE;
+
+ void setPosition(const QVector3D &position);
+ QVector3D position() const;
+
+ void setUpVector(const QVector3D &upVector);
+ QVector3D upVector() const;
+
+ void setViewCenter(const QVector3D &viewCenter);
+ QVector3D viewCenter() const;
+
+ QVector3D viewVector() const;
+
+signals:
+ void positionChanged();
+ void upVectorChanged();
+ void viewCenterChanged();
+ void viewVectorChanged();
+
+private:
+ mutable QMatrix4x4 m_matrix;
+ QVector3D m_position;
+ QVector3D m_upVector;
+ QVector3D m_viewCenter;
+ QVector3D m_viewVector; // From "camera" position to view center
+ mutable bool m_matrixDirty;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_LOOKATTRANSFORM_H
diff --git a/src/core/matrixtransform.cpp b/src/core/matrixtransform.cpp
new file mode 100644
index 000000000..e93b96835
--- /dev/null
+++ b/src/core/matrixtransform.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "matrixtransform.h"
+
+namespace Qt3D {
+
+MatrixTransform::MatrixTransform()
+{
+}
+
+MatrixTransform::MatrixTransform(const QMatrix4x4& m) :
+ m_matrix(m)
+{
+}
+
+QMatrix4x4 MatrixTransform::matrix() const
+{
+ return m_matrix;
+}
+
+}
diff --git a/src/core/matrixtransform.h b/src/core/matrixtransform.h
new file mode 100644
index 000000000..0019a2aef
--- /dev/null
+++ b/src/core/matrixtransform.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MATRIXTRANSFORM_H
+#define MATRIXTRANSFORM_H
+
+#include "abstracttransform.h"
+#include "qt3dcore_global.h"
+
+#include <QMatrix4x4>
+
+namespace Qt3D {
+
+class MatrixTransform : public AbstractTransform
+{
+public:
+ MatrixTransform();
+
+ MatrixTransform( const QMatrix4x4& m );
+
+ virtual QMatrix4x4 matrix() const;
+private:
+ QMatrix4x4 m_matrix;
+};
+
+}
+
+#endif // MATRIXTRANSFORM_H
diff --git a/src/core/node.cpp b/src/core/node.cpp
new file mode 100644
index 000000000..81f11ea77
--- /dev/null
+++ b/src/core/node.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "node.h"
+
+#include "entity.h"
+
+#include <QEvent>
+#include <QMetaObject>
+#include <QMetaProperty>
+#include <QDebug>
+
+namespace Qt3D {
+
+Node::Node( Node* parent )
+ : QObject( parent )
+{
+ if (parent)
+ parent->m_children.append(this);
+}
+
+Node::~Node()
+{
+}
+
+QQmlListProperty<QObject> Node::data()
+{
+ return QQmlListProperty<QObject>(this, 0,
+ Node::appendData,
+ Node::dataCount,
+ Node::dataAt,
+ Node::clearData);
+}
+
+QQmlListProperty<Node> Node::childNodes()
+{
+ return QQmlListProperty<Node>(this, 0,
+ Node::appendChild,
+ Node::childCount,
+ Node::childAt,
+ Node::clearChildren);
+}
+
+void Node::dump()
+{
+ const QMetaObject *meta = metaObject();
+ QStringList result;
+ for (int i = 0; i < meta->propertyCount(); ++i) {
+ const QMetaProperty metaProperty = meta->property(i);
+ const QVariant value = property(metaProperty.name());
+ result += QString(QStringLiteral("%1 %2 = %3;"))
+ .arg(QString::fromLatin1(metaProperty.typeName()))
+ .arg(QString::fromLatin1(metaProperty.name()))
+ .arg(value.toString());
+ }
+
+ qDebug() << result.join(QStringLiteral("\n"));
+
+ foreach (QObject *child, children()) {
+ Node *node = qobject_cast<Node *>(child);
+ if (!node)
+ continue;
+ node->dump();
+ }
+}
+
+NodeList Node::children() const
+{
+ return m_children;
+}
+
+void Node::addChild(Node *childNode)
+{
+ Q_CHECK_PTR( childNode );
+ if (childNode->parent() == this)
+ return;
+
+ m_children.append(childNode);
+ childNode->setParent(this);
+
+ if (childNode->asEntity())
+ childNode->asEntity()->update();
+}
+
+void Node::removeChild(Node *childNode)
+{
+ Q_CHECK_PTR( childNode );
+ if (childNode->parent() != this)
+ qWarning() << Q_FUNC_INFO << "not a child";
+
+ m_children.removeOne(childNode);
+ childNode->setParent(NULL);
+}
+
+void Node::removeAllChildren()
+{
+ foreach (QObject *child, children()) {
+ child->deleteLater();
+ }
+
+ m_children.clear();
+}
+
+Entity *Node::asEntity()
+{
+ return NULL;
+}
+
+Node *Node::parentNode() const
+{
+ return qobject_cast<Node*>(parent());
+}
+
+bool Node::event(QEvent *e)
+{
+ if (e->type() == QEvent::DynamicPropertyChange) {
+ qDebug() << "*** Dynamic Property Change ***";
+ }
+ return QObject::event(e);
+}
+
+void Node::appendData(QQmlListProperty<QObject> *list, QObject *obj)
+{
+ if (!obj)
+ return;
+
+ QObject *self = static_cast<QObject *>(list->object);
+ if (obj->parent() == self)
+ obj->setParent(0);
+ obj->setParent(self);
+
+ Node *parentNode = qobject_cast<Qt3D::Node *>(self);
+ Node *node = qobject_cast<Qt3D::Node *>(obj);
+ if (node && parentNode)
+ parentNode->m_children.append(node);
+}
+
+QObject *Node::dataAt(QQmlListProperty<QObject> *list, int index)
+{
+ QObject *self = static_cast<QObject *>(list->object);
+ return self->children().at(index);
+}
+
+int Node::dataCount(QQmlListProperty<QObject> *list)
+{
+ QObject *self = static_cast<QObject *>(list->object);
+ return self->children().count();
+}
+
+void Node::clearData(QQmlListProperty<QObject> *list)
+{
+ QObject *self = static_cast<QObject *>(list->object);
+ Q_FOREACH (QObject *const child, self->children())
+ child->setParent(0);
+}
+
+void Node::appendChild(QQmlListProperty<Qt3D::Node> *list, Qt3D::Node *obj)
+{
+ if (!obj)
+ return;
+
+ Node *self = static_cast<Node *>(list->object);
+ Q_ASSERT(!self->m_children.contains(obj));
+ if (obj->parent() == self)
+ obj->setParent(0);
+ self->m_children.append(obj);
+ obj->setParent(self);
+}
+
+Qt3D::Node *Node::childAt(QQmlListProperty<Qt3D::Node> *list, int index)
+{
+ Node *self = static_cast<Node *>(list->object);
+ return self->m_children.at(index);
+}
+
+int Node::childCount(QQmlListProperty<Qt3D::Node> *list)
+{
+ Node *self = static_cast<Node *>(list->object);
+ return self->m_children.count();
+}
+
+void Node::clearChildren(QQmlListProperty<Qt3D::Node> *list)
+{
+ Node *self = static_cast<Node *>(list->object);
+ Q_FOREACH (Node *const child, self->m_children)
+ child->setParent(0);
+ self->m_children.clear();
+}
+
+} // of namespace Qt3D
diff --git a/src/core/node.h b/src/core/node.h
new file mode 100644
index 000000000..c1776774f
--- /dev/null
+++ b/src/core/node.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_NODE_H
+#define QT3D_NODE_H
+
+#include <QObject>
+#include "qt3dcore_global.h"
+
+#include <QQmlListProperty>
+
+namespace Qt3D {
+
+class Node;
+class Component;
+class Entity;
+
+typedef QList<Node *> NodeList;
+
+class QT3DCORESHARED_EXPORT Node : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> data READ data)
+ Q_PROPERTY(QQmlListProperty<Qt3D::Node> childNodes READ childNodes)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ explicit Node(Node *parent = 0);
+ ~Node();
+
+ QQmlListProperty<QObject> data();
+ QQmlListProperty<Qt3D::Node> childNodes();
+
+ void dump();
+
+ NodeList children() const;
+ void addChild( Node* childNode );
+ void removeChild( Node* childNode );
+
+ void removeAllChildren();
+
+ virtual Entity* asEntity();
+
+ Node* parentNode() const;
+
+protected:
+ bool event(QEvent *e);
+
+private:
+ static void appendData(QQmlListProperty<QObject> *list, QObject *obj);
+ static QObject *dataAt(QQmlListProperty<QObject> *list, int index);
+ static int dataCount(QQmlListProperty<QObject> *list);
+ static void clearData(QQmlListProperty<QObject> *list);
+
+ static void appendChild(QQmlListProperty<Qt3D::Node> *list, Qt3D::Node *obj);
+ static Node *childAt(QQmlListProperty<Qt3D::Node> *list, int index);
+ static int childCount(QQmlListProperty<Qt3D::Node> *list);
+ static void clearChildren(QQmlListProperty<Qt3D::Node> *list);
+
+ NodeList m_children;
+};
+
+}
+
+#endif
diff --git a/src/core/nodevisitor.cpp b/src/core/nodevisitor.cpp
new file mode 100644
index 000000000..5c0f99752
--- /dev/null
+++ b/src/core/nodevisitor.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nodevisitor.h"
+
+#include "node.h"
+#include "entity.h"
+
+namespace Qt3D {
+
+NodeVisitor::NodeVisitor()
+ : m_traverseDisabled(false)
+{
+}
+
+void NodeVisitor::traverse(Node *rootNode)
+{
+ m_path = NodeList() << rootNode;
+
+ m_matrixStack.clear();
+ Entity* rootEntity = rootNode->asEntity();
+
+ m_matrixStack.append(rootEntity ? rootEntity->matrix() : QMatrix4x4());
+
+ if (rootEntity)
+ visitEntity(rootEntity);
+ else
+ visitNode(rootNode);
+}
+
+Node* NodeVisitor::rootNode() const
+{
+ return m_path.front();
+}
+
+Node* NodeVisitor::currentNode() const
+{
+ return m_path.back();
+}
+
+QMatrix4x4 NodeVisitor::currentMatrix() const
+{
+ return m_matrixStack.back();
+}
+
+NodeList NodeVisitor::path() const
+{
+ return m_path;
+}
+
+void NodeVisitor::setTraverseDisabled(bool on)
+{
+ m_traverseDisabled = on;
+}
+
+void NodeVisitor::visitNode(Node *nd)
+{
+ Q_UNUSED(nd);
+ traverseChildren();
+}
+
+void NodeVisitor::visitEntity(Entity *nd)
+{
+ visitNode(nd);
+}
+
+void NodeVisitor::traverseChildren()
+{
+ foreach (Node* n, currentNode()->children()) {
+ outerVisitNode(n);
+ } // of children iteration
+}
+
+void NodeVisitor::outerVisitNode(Node *n)
+{
+ m_path.append(n);
+ Entity* e = n->asEntity();
+ if (e) {
+ QMatrix4x4 m = m_matrixStack.back() * e->matrix();
+ m_matrixStack.push_back(m);
+
+ visitEntity(e);
+
+ m_path.pop_back();
+ m_matrixStack.pop_back();
+ } else {
+ visitNode(n);
+ }
+}
+
+} // of namespace
diff --git a/src/core/nodevisitor.h b/src/core/nodevisitor.h
new file mode 100644
index 000000000..2be95a8d1
--- /dev/null
+++ b/src/core/nodevisitor.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NODEVISITOR_H
+#define NODEVISITOR_H
+
+#include "qt3dcore_global.h"
+
+#include <QMatrix4x4>
+
+namespace Qt3D
+{
+
+class Node;
+class Entity;
+
+typedef QList<Node *> NodeList;
+
+class NodeVisitor
+{
+public:
+ NodeVisitor();
+
+ void traverse(Node *rootNode);
+
+ Node *rootNode() const;
+
+ Node *currentNode() const;
+
+ QMatrix4x4 currentMatrix() const;
+
+ NodeList path() const;
+
+ void setTraverseDisabled(bool on);
+
+protected:
+ virtual void visitNode(Node *nd);
+ virtual void visitEntity(Entity *ent);
+
+ void traverseChildren();
+
+private:
+ NodeList m_path;
+ QVector<QMatrix4x4> m_matrixStack;
+ bool m_traverseDisabled;
+
+ void outerVisitNode(Node *n);
+};
+
+} // of namespace
+
+#endif // NODEVISITOR_H
diff --git a/src/core/qaspectengine.cpp b/src/core/qaspectengine.cpp
new file mode 100644
index 000000000..63e470bfc
--- /dev/null
+++ b/src/core/qaspectengine.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaspectengine.h"
+
+#include "qaspectthread.h"
+#include "qaspectmanager.h"
+#include "qchangearbiter.h"
+
+#include <QDebug>
+#include <QMetaObject>
+#include <QMutexLocker>
+
+namespace Qt3D {
+
+QAspectEngine::QAspectEngine(QObject *parent)
+ : QObject(parent)
+ , m_aspectThread(new QAspectThread(this))
+{
+ qDebug() << Q_FUNC_INFO;
+ qRegisterMetaType<QWaitCondition *>();
+ m_aspectThread->waitForStart(QThread::HighestPriority);
+}
+
+void QAspectEngine::initialize()
+{
+ QChangeArbiter *arbiter = m_aspectThread->aspectManager()->changeArbiter();
+ QChangeArbiter::createUnmanagedThreadLocalChangeQueue(arbiter);
+}
+
+void QAspectEngine::shutdown()
+{
+}
+
+void QAspectEngine::setWindow(QWindow *window)
+{
+ QMetaObject::invokeMethod(m_aspectThread->aspectManager(), "setWindow", Q_ARG(QWindow *, window));
+}
+
+void QAspectEngine::setRoot(QObject *rootObject)
+{
+ QMutexLocker locker(&m_mutex);
+ QMetaObject::invokeMethod(m_aspectThread->aspectManager(), "setRoot", Q_ARG(QObject *, rootObject), Q_ARG(QWaitCondition *, &m_waitCondition));
+
+ qDebug() << "Putting main thread to sleep whilst aspects build their local scenes...";
+ m_waitCondition.wait(&m_mutex);
+ qDebug() << "Main thread is now awake again";
+}
+
+} // namespace Qt3D
diff --git a/src/core/qaspectengine.h b/src/core/qaspectengine.h
new file mode 100644
index 000000000..a7f949088
--- /dev/null
+++ b/src/core/qaspectengine.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QASPECTENGINE_H
+#define QASPECTENGINE_H
+
+#include <QObject>
+#include "qt3dcore_global.h"
+
+#include <QList>
+#include <QMutex>
+#include <QWaitCondition>
+
+class QWindow;
+
+namespace Qt3D {
+
+class AbstractAspect;
+class QAspectThread;
+
+class QAspectEngine : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QAspectEngine(QObject *parent = 0);
+
+ void initialize();
+ void shutdown();
+
+ void setRoot(QObject *rootObject);
+ void setWindow(QWindow *window);
+private:
+ QAspectThread *m_aspectThread;
+ QMutex m_mutex;
+ QWaitCondition m_waitCondition;
+};
+
+} // namespace Qt3D
+
+Q_DECLARE_METATYPE(QWaitCondition *)
+
+#endif // QASPECTENGINE_H
diff --git a/src/core/qaspectmanager.cpp b/src/core/qaspectmanager.cpp
new file mode 100644
index 000000000..1205314e9
--- /dev/null
+++ b/src/core/qaspectmanager.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaspectmanager.h"
+
+#include "rendereraspect.h"
+#include "qchangearbiter.h"
+// TODO Make the kind of job manager configurable (e.g. ThreadWeaver vs Intel TBB)
+//#include "qjobmanager.h"
+#include "qjobmanagerinterface.h"
+#include "qscheduler.h"
+#include "qtickclock.h"
+
+#include <node.h>
+
+#include <QDebug>
+#include <QElapsedTimer>
+#include <QEventLoop>
+#include <QThread>
+#include <QWaitCondition>
+#include <QWindow>
+
+namespace Qt3D {
+
+QAspectManager::QAspectManager(QObject *parent)
+ : QObject(parent)
+ , m_root(0)
+ , m_window(0)
+ , m_scheduler(new QScheduler(this))
+ , m_jobManager(0/*new QJobManager(this)*/)
+ , m_changeArbiter(new QChangeArbiter(this))
+ , m_runMainLoop(false)
+{
+ qRegisterMetaType<QWindow*>("QWindow*");
+ qDebug() << Q_FUNC_INFO;
+}
+
+void QAspectManager::initialize()
+{
+ qDebug() << Q_FUNC_INFO;
+ m_jobManager->initialize();
+ m_scheduler->setAspectManager(this);
+ m_changeArbiter->initialize(m_jobManager);
+}
+
+void QAspectManager::shutdown()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+void QAspectManager::setRoot(QObject *rootObject, QWaitCondition *waitCondition)
+{
+ qDebug() << Q_FUNC_INFO;
+
+ Node *root = qobject_cast<Node *>(rootObject);
+ if (root == m_root)
+ return;
+
+ if (m_root) {
+ // Allow each aspect chance to cleanup any resources from this scene
+ Q_FOREACH (AbstractAspect *aspect, m_aspects)
+ aspect->unregisterAspect(m_root);
+
+ // Allow each aspect chance to cleanup any scene-independent resources
+ Q_FOREACH (AbstractAspect *aspect, m_aspects)
+ aspect->cleanup();
+
+ // Destroy all aspects
+ qDeleteAll(m_aspects);
+ m_aspects.clear();
+
+ m_root = 0;
+ }
+
+ m_root = root;
+
+ if (rootObject) {
+ // TODO Load all aspect plugins that are found and required.
+ // For now just load the render aspect
+ RendererAspect *renderAspect = new RendererAspect(this);
+ m_aspects.append(renderAspect);
+
+ Q_FOREACH (AbstractAspect *aspect, m_aspects)
+ aspect->initialize(this);
+
+ if (m_window) {
+ Q_FOREACH (AbstractAspect *aspect, m_aspects)
+ aspect->setWindow(m_window);
+ }
+
+ Q_FOREACH (AbstractAspect *aspect, m_aspects)
+ aspect->registerAspect(m_root);
+
+ m_runMainLoop = true;
+ }
+
+ if (waitCondition)
+ waitCondition->wakeOne();
+}
+
+void QAspectManager::setWindow(QWindow *window)
+{
+ qDebug() << Q_FUNC_INFO;
+
+ m_window = window;
+
+ if (m_window) {
+ Q_FOREACH (AbstractAspect *aspect, m_aspects)
+ aspect->setWindow(m_window);
+ }
+}
+
+void QAspectManager::exec()
+{
+ // Gentlemen, start your engines
+ QEventLoop eventLoop;
+
+// QElapsedTimer timer;
+// timer.start();
+// qint64 t(0);
+ QTickClock tickClock;
+ tickClock.start();
+
+ // Enter the main loop
+ while (1)
+ {
+ // Process any pending events, waiting for more to arrive if queue is empty
+ eventLoop.processEvents(QEventLoop::WaitForMoreEvents, 16);
+
+ // Only enter main render loop once the renderer and other aspects are initialized
+ while (m_runMainLoop)
+ {
+ // Process any pending events
+ eventLoop.processEvents();
+
+ // Update the clocks (just main clock for now).
+ // TODO: Add additional clocks
+ qint64 t = tickClock.waitForNextTick();
+ // qDebug() << "t =" << t / 1000000;
+// const qint64 t1 = timer.nsecsElapsed();
+// const qint64 dt = t1 - t;
+// t = t1;
+// qDebug() << "dt =" << dt;
+
+ m_scheduler->update(t);
+
+ // Distribute accumulated changes
+ m_changeArbiter->syncChanges();
+ }
+ }
+}
+
+} // namespace Qt3D
diff --git a/src/core/qaspectmanager.h b/src/core/qaspectmanager.h
new file mode 100644
index 000000000..2653d4a0f
--- /dev/null
+++ b/src/core/qaspectmanager.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QASPECTMANAGER_H
+#define QT3D_QASPECTMANAGER_H
+
+#include <QObject>
+#include "qt3dcore_global.h"
+
+#include <QList>
+
+class QWaitCondition;
+class QWindow;
+
+namespace Qt3D {
+
+class AbstractAspect;
+class Node;
+class QChangeArbiter;
+class QJobManagerInterface;
+class QScheduler;
+
+class QAspectManager : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QAspectManager(QObject *parent = 0);
+
+public slots:
+ void initialize();
+ void shutdown();
+
+ void setRoot(QObject *rootObject, QWaitCondition *waitCondition);
+ void setWindow(QWindow* window);
+
+ void exec();
+
+ const QList<AbstractAspect *> &aspects() const { return m_aspects; }
+ QJobManagerInterface *jobManager() const { return m_jobManager; }
+ QChangeArbiter *changeArbiter() const { return m_changeArbiter; }
+
+private:
+ QList<AbstractAspect *> m_aspects;
+ Node *m_root;
+ QWindow *m_window;
+ QScheduler *m_scheduler;
+ QJobManagerInterface *m_jobManager;
+ QChangeArbiter *m_changeArbiter;
+ bool m_runMainLoop;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_QASPECTMANAGER_H
diff --git a/src/core/qaspectscheduler.cpp b/src/core/qaspectscheduler.cpp
new file mode 100644
index 000000000..22febeae6
--- /dev/null
+++ b/src/core/qaspectscheduler.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaspectscheduler.h"
+
+#include <QDebug>
+
+namespace Qt3D {
+
+QAspectScheduler::QAspectScheduler(QObject *parent)
+ : QObject(parent)
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+} // namespace Qt3D
diff --git a/src/core/qaspectscheduler.h b/src/core/qaspectscheduler.h
new file mode 100644
index 000000000..6bc38c732
--- /dev/null
+++ b/src/core/qaspectscheduler.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QASPECTSCHEDULER_H
+#define QT3D_QASPECTSCHEDULER_H
+
+#include <QObject>
+#include "qt3dcore_global.h"
+
+namespace Qt3D {
+
+class QAspectScheduler : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QAspectScheduler(QObject *parent = 0);
+
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_QASPECTSCHEDULER_H
diff --git a/src/core/qaspectthread.cpp b/src/core/qaspectthread.cpp
new file mode 100644
index 000000000..22d920adb
--- /dev/null
+++ b/src/core/qaspectthread.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaspectthread.h"
+
+#include <qaspectmanager.h>
+
+#include <QDebug>
+#include <QMutexLocker>
+
+namespace Qt3D {
+
+QAspectThread::QAspectThread(QObject *parent)
+ : QThread(parent)
+ , m_aspectManager(0)
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+void QAspectThread::waitForStart(Priority priority)
+{
+ qDebug() << "Starting QAspectThread and going to sleep until it is ready for us...";
+ m_mutex.lock();
+ start(priority);
+ m_waitCondition.wait(&m_mutex);
+ qDebug() << "QAspectThead is now ready & calling thread is now awake again";
+}
+
+void QAspectThread::run()
+{
+ qDebug() << "Entering void QAspectThread::run()";
+
+ // Lock mutex and create worker objects
+ QMutexLocker locker(&m_mutex);
+ m_aspectManager = new QAspectManager;
+
+ // Wake up the calling thread now that our worker objects are ready for action
+ m_waitCondition.wakeOne();
+ m_mutex.unlock();
+
+ // Load and initialize the aspects and any other core services
+ m_aspectManager->initialize();
+
+ // Enter the main loop
+ m_aspectManager->exec();
+
+ // Clean up
+ m_aspectManager->shutdown();
+ delete m_aspectManager;
+
+ qDebug() << "Exiting void QAspectThread::run()";
+}
+
+} // namespace Qt3D
diff --git a/src/core/qaspectthread.h b/src/core/qaspectthread.h
new file mode 100644
index 000000000..6d9d76707
--- /dev/null
+++ b/src/core/qaspectthread.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QASPECTTHREAD_H
+#define QT3D_QASPECTTHREAD_H
+
+#include <QThread>
+#include "qt3dcore_global.h"
+
+#include <QMutex>
+#include <QWaitCondition>
+
+namespace Qt3D {
+
+class QAspectManager;
+
+class QAspectThread : public QThread
+{
+ Q_OBJECT
+public:
+ explicit QAspectThread(QObject *parent = 0);
+
+ void waitForStart(Priority priority);
+
+ QAspectManager *aspectManager() const { return m_aspectManager; }
+
+protected:
+ void run() Q_DECL_OVERRIDE;
+
+private:
+ QAspectManager *m_aspectManager;
+ QMutex m_mutex;
+ QWaitCondition m_waitCondition;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_QASPECTTHREAD_H
diff --git a/src/core/qchangearbiter.cpp b/src/core/qchangearbiter.cpp
new file mode 100644
index 000000000..6bfbfd015
--- /dev/null
+++ b/src/core/qchangearbiter.cpp
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qchangearbiter.h"
+#include "component.h"
+#include "qjobmanagerinterface.h"
+
+#include <QDebug>
+#include <QMutexLocker>
+#include <QReadLocker>
+#include <QThread>
+#include <QWriteLocker>
+
+namespace Qt3D {
+
+QObservable::QObservable()
+ : m_observers()
+ , m_lock(QReadWriteLock::NonRecursive)
+{
+}
+
+void QObservable::registerObserver(QObserverInterface *observer)
+{
+ QWriteLocker locker(&m_lock);
+ if (!m_observers.contains(observer))
+ m_observers.append(observer);
+}
+
+void QObservable::unregisterObserver(QObserverInterface *observer)
+{
+ QWriteLocker locker(&m_lock);
+ m_observers.removeOne(observer);
+}
+
+void QObservable::notifyObservers(const QSceneChangePtr &e)
+{
+ QReadLocker locker(&m_lock);
+ Q_FOREACH (QObserverInterface *observer, m_observers)
+ observer->sceneChangeEvent(e);
+}
+
+
+QChangeArbiter::QChangeArbiter(QObject *parent)
+ : QObject(parent)
+ , m_jobManager(0)
+{
+}
+
+void QChangeArbiter::initialize(QJobManagerInterface *jobManager)
+{
+ Q_CHECK_PTR(jobManager);
+ m_jobManager = jobManager;
+
+ // Init TLS for the change queues
+ m_jobManager->waitForPerThreadFunction(QChangeArbiter::createThreadLocalChangeQueue, this);
+}
+
+void QChangeArbiter::distributeQueueChanges(ChangeQueue *changeQueue)
+{
+ Q_FOREACH (const QSceneChangePtr &change, *changeQueue) {
+ // Lookup which observers care about the subject this change came from
+ // and distribute the change to them
+ switch (change->m_subjectType) {
+ case QSceneChange::ObservableType: {
+ QObservableInterface *subject = change->m_subject.m_observable;
+ if (m_observations.contains(subject)) {
+ QObserverList &observers = m_observations[subject];
+ Q_FOREACH (QObserverInterface *observer, observers)
+ observer->sceneChangeEvent(change);
+ }
+ break;
+ }
+
+ case QSceneChange::ComponentType: {
+ Component *subject = change->m_subject.m_component;
+ if (m_componentObservations.contains(subject)) {
+ QObserverList &observers = m_componentObservations[subject];
+ Q_FOREACH (QObserverInterface *observer, observers)
+ observer->sceneChangeEvent(change);
+ }
+ break;
+ }
+ }
+ }
+}
+
+void QChangeArbiter::syncChanges()
+{
+ //qDebug() << Q_FUNC_INFO;
+ QMutexLocker locker(&m_mutex);
+ Q_FOREACH (QChangeArbiter::ChangeQueue *changeQueue, m_changeQueues) {
+ distributeQueueChanges(changeQueue);
+ changeQueue->clear();
+ }
+
+ Q_FOREACH (ChangeQueue *changeQueue, m_lockingChangeQueues) {
+ distributeQueueChanges(changeQueue);
+ changeQueue->clear();
+ }
+}
+
+void QChangeArbiter::registerObserver(QObserverInterface *observer,
+ QObservableInterface *subject,
+ ChangeFlags changeFlags)
+{
+ qDebug() << Q_FUNC_INFO;
+ if (!observer || !subject)
+ return;
+
+ // Store info about which observers are watching which observables.
+ // Protect access as this could be called from any thread
+ QMutexLocker locker(&m_mutex);
+ QObserverList &observers = m_observations[subject];
+ observers.append(observer);
+
+ // TODO: Also store info about types of change observer is interested in so that we
+ // can reduce the amount of traffic
+ Q_UNUSED(changeFlags);
+
+ // Register ourselves with the observable as the intermediary
+ subject->registerObserver(this);
+}
+
+void QChangeArbiter::registerObserver(QObserverInterface *observer,
+ Component *component,
+ ChangeFlags changeFlags)
+{
+ qDebug() << Q_FUNC_INFO;
+ if (!observer || !component)
+ return;
+
+ // Store info about which observers are watching which observables.
+ // Protect access as this could be called from any thread
+ QMutexLocker locker(&m_mutex);
+ QObserverList &observers = m_componentObservations[component];
+ observers.append(observer);
+
+ // TODO: Also store info about types of change observer is interested in so that we
+ // can reduce the amount of traffic
+ Q_UNUSED(changeFlags);
+
+ // Register ourselves with the observable as the intermediary
+ component->registerChangeArbiter(this);
+}
+
+void QChangeArbiter::unregisterObserver(QObserverInterface *observer,
+ QObservableInterface *subject)
+{
+ // TODO: Implement me!
+}
+
+void QChangeArbiter::sceneChangeEvent(const QSceneChangePtr &e)
+{
+ //qDebug() << Q_FUNC_INFO << QThread::currentThread();
+
+ // Add the change to the thread local storage queue - no locking required => yay!
+ ChangeQueue *localChangeQueue = m_tlsChangeQueue.localData();
+ localChangeQueue->append(e);
+
+ //qDebug() << "Change queue for thread" << QThread::currentThread() << "now contains" << localChangeQueue->count() << "items";
+}
+
+void QChangeArbiter::sceneChangeEventWithLock(const QSceneChangePtr &e)
+{
+ QMutexLocker locker(&m_mutex);
+ sceneChangeEvent(e);
+}
+
+void QChangeArbiter::createUnmanagedThreadLocalChangeQueue(void *changeArbiter)
+{
+ Q_CHECK_PTR(changeArbiter);
+
+ QChangeArbiter *arbiter = static_cast<QChangeArbiter *>(changeArbiter);
+
+ qDebug() << Q_FUNC_INFO << QThread::currentThread();
+ if (!arbiter->m_tlsChangeQueue.hasLocalData()) {
+ ChangeQueue *localChangeQueue = new ChangeQueue;
+ arbiter->m_tlsChangeQueue.setLocalData(localChangeQueue);
+
+ QMutexLocker locker(&(arbiter->m_mutex));
+ arbiter->m_lockingChangeQueues.append(localChangeQueue);
+ }
+}
+
+static void destroyUnmanagedThreadLocalChangeQueue(void *changeArbiter)
+{
+ // TODO: Implement me!
+}
+
+void QChangeArbiter::createThreadLocalChangeQueue(void *changeArbiter)
+{
+ Q_CHECK_PTR(changeArbiter);
+
+ QChangeArbiter *arbiter = static_cast<QChangeArbiter *>(changeArbiter);
+
+ qDebug() << Q_FUNC_INFO << QThread::currentThread();
+ if (!arbiter->m_tlsChangeQueue.hasLocalData()) {
+ ChangeQueue *localChangeQueue = new ChangeQueue;
+ arbiter->m_tlsChangeQueue.setLocalData(localChangeQueue);
+
+ QMutexLocker locker(&(arbiter->m_mutex));
+ arbiter->m_changeQueues.append(localChangeQueue);
+ }
+}
+
+static void destroyThreadLocalChangeQueue(void *changeArbiter)
+{
+ // TODO: Implement me!
+}
+
+} // namespace Qt3D
diff --git a/src/core/qchangearbiter.h b/src/core/qchangearbiter.h
new file mode 100644
index 000000000..73a0411f9
--- /dev/null
+++ b/src/core/qchangearbiter.h
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QCHANGEARBITER_H
+#define QT3D_QCHANGEARBITER_H
+
+#include "qt3dcore_global.h"
+
+#include <QObject>
+#include <QDebug>
+#include <QFlags>
+#include <QMutex>
+#include <QReadWriteLock>
+#include <QSharedPointer>
+#include <QThreadStorage>
+#include <QVariant>
+#include <QVector>
+
+namespace Qt3D {
+
+class Component;
+
+enum ChangeFlag {
+ NodeCreated = 0x00000001,
+ NodeAboutToBeDeleted = 0x00000002,
+ NodeDeleted = 0x00000004,
+ NodeStatus = 0x00000008,
+ LocalTransform = 0x00000010,
+ MeshChange = 0x00000020,
+ MaterialParameter = 0x00000040,
+ CameraProjectionMatrix = 0x00000080,
+ AllChanges = 0xFFFFFFFF
+};
+Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag)
+Q_DECLARE_OPERATORS_FOR_FLAGS(ChangeFlags)
+
+
+class QObserverInterface;
+class QObservableInterface;
+
+class QT3DCORESHARED_EXPORT QSceneChange
+{
+public:
+ QSceneChange(ChangeFlag type, QObservableInterface *observable)
+ : m_type(type)
+ {
+ m_subject.m_observable = observable;
+ m_subjectType = ObservableType;
+ }
+
+ QSceneChange(ChangeFlag type, Component *component)
+ : m_type(type)
+ {
+ m_subject.m_component = component;
+ m_subjectType = ComponentType;
+ }
+
+ union {
+ QObservableInterface *m_observable;
+ Component *m_component;
+ } m_subject;
+
+ enum ObservableType {
+ ObservableType,
+ ComponentType
+ } m_subjectType;
+
+ ChangeFlag m_type;
+
+ // TODO: add timestamp from central clock and priority level
+ // These can be used to resolve any conflicts between events
+ // posted from different aspects
+};
+
+typedef QSharedPointer<QSceneChange> QSceneChangePtr;
+
+class QT3DCORESHARED_EXPORT QScenePropertyChange : public QSceneChange
+{
+public:
+ QScenePropertyChange(ChangeFlag type, QObservableInterface *subject)
+ : QSceneChange(type, subject)
+ {
+ }
+
+ QScenePropertyChange(ChangeFlag type, Component *component)
+ : QSceneChange(type, component)
+ {
+ }
+
+ QByteArray m_propertyName;
+ QVariant m_value;
+};
+
+typedef QSharedPointer<QScenePropertyChange> QScenePropertyChangePtr;
+
+
+class QT3DCORESHARED_EXPORT QObservableInterface
+{
+public:
+ virtual ~QObservableInterface() {}
+
+ virtual void registerObserver(QObserverInterface *observer) = 0;
+ virtual void unregisterObserver(QObserverInterface *observer) = 0;
+
+protected:
+ virtual void notifyObservers(const QSceneChangePtr &e) = 0;
+};
+
+
+class QT3DCORESHARED_EXPORT QObservable : public QObservableInterface
+{
+public:
+ QObservable();
+
+ void registerObserver(QObserverInterface *observer) Q_DECL_OVERRIDE;
+ void unregisterObserver(QObserverInterface *observer) Q_DECL_OVERRIDE;
+
+protected:
+ void notifyObservers(const QSceneChangePtr &e) Q_DECL_OVERRIDE;
+
+ const QList<QObserverInterface *> &observers() const { return m_observers; }
+
+private:
+ QList<QObserverInterface *> m_observers;
+ QReadWriteLock m_lock;
+};
+
+
+class QObserverInterface
+{
+public:
+ virtual ~QObserverInterface() {}
+
+ virtual void sceneChangeEvent(const QSceneChangePtr &e) = 0;
+};
+
+
+class QJobManagerInterface;
+
+class QT3DCORESHARED_EXPORT QChangeArbiter : public QObject,
+ public QObserverInterface
+{
+ Q_OBJECT
+public:
+ explicit QChangeArbiter(QObject *parent = 0);
+
+ void initialize(Qt3D::QJobManagerInterface *jobManager);
+
+ void syncChanges();
+
+ void registerObserver(QObserverInterface *observer,
+ QObservableInterface *subject,
+ ChangeFlags changeFlags = AllChanges);
+
+ void registerObserver(QObserverInterface *observer,
+ Component *component,
+ ChangeFlags changeFlags = AllChanges);
+
+ void unregisterObserver(QObserverInterface *observer,
+ QObservableInterface *subject);
+
+ void sceneChangeEvent(const QSceneChangePtr &e) Q_DECL_OVERRIDE; // QObserverInterface impl
+ void sceneChangeEventWithLock(const QSceneChangePtr &e);
+
+ static void createUnmanagedThreadLocalChangeQueue(void *changeArbiter);
+ static void destroyUnmanagedThreadLocalChangeQueue(void *changeArbiter);
+ static void createThreadLocalChangeQueue(void *changeArbiter);
+ static void destroyThreadLocalChangeQueue(void *changeArbiter);
+
+private:
+ typedef QVector<QSceneChangePtr> ChangeQueue;
+
+ void distributeQueueChanges(ChangeQueue *queue);
+
+ QMutex m_mutex;
+ QJobManagerInterface *m_jobManager;
+
+ typedef QList<QObserverInterface *> QObserverList;
+ QHash<QObservableInterface *, QObserverList> m_observations;
+ QHash<Component *, QObserverList> m_componentObservations;
+
+ // Each thread has a TLS ChangeQueue so we never need to lock whilst
+ // receiving a QSceneChange.
+ QThreadStorage<ChangeQueue *> m_tlsChangeQueue;
+
+ // We store a list of the ChangeQueue's from each thread. This will only
+ // be accesses from the aspect thread during the syncChanges() phase.
+ QList<ChangeQueue *> m_changeQueues;
+ QList<ChangeQueue *> m_lockingChangeQueues;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_QCHANGEARBITER_H
diff --git a/src/core/qjob.cpp b/src/core/qjob.cpp
new file mode 100644
index 000000000..73dfabfe2
--- /dev/null
+++ b/src/core/qjob.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qjob.h"
+
+namespace Qt3D {
+
+QJob::QJob()
+{
+}
+
+QJob::~QJob()
+{
+}
+
+void QJob::addDependency(QWeakPointer<QJob> dependency)
+{
+ m_dependencies.append(dependency);
+}
+
+} // namespace Qt3D
diff --git a/src/core/qjob.h b/src/core/qjob.h
new file mode 100644
index 000000000..c49907538
--- /dev/null
+++ b/src/core/qjob.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QJOB_H
+#define QT3D_QJOB_H
+
+#include "qt3dcore_global.h"
+
+#include <QSharedPointer>
+#include <QVector>
+
+namespace Qt3D {
+
+class QJob
+{
+public:
+ QJob();
+ virtual ~QJob();
+
+ void addDependency(QWeakPointer<QJob> dependency);
+ const QVector<QWeakPointer<QJob> > &dependencies() const { return m_dependencies; }
+
+ virtual void run() = 0;
+
+private:
+ QVector<QWeakPointer<QJob> > m_dependencies;
+};
+
+typedef QSharedPointer<QJob> QJobPtr;
+
+} // namespace Qt3D
+
+#endif // QT3D_QJOB_H
diff --git a/src/core/qjobmanagerinterface.h b/src/core/qjobmanagerinterface.h
new file mode 100644
index 000000000..a003d1198
--- /dev/null
+++ b/src/core/qjobmanagerinterface.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJOBMANAGERINTERFACE_H
+#define QJOBMANAGERINTERFACE_H
+
+#include <QObject>
+
+#include "qjob.h"
+
+namespace Qt3D {
+
+class QJobManagerInterface : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QJobManagerInterface(QObject *parent = 0)
+ : QObject(parent)
+ {}
+
+ virtual void initialize() {}
+ virtual void enqueueJobs(const QVector<QJobPtr> &jobQueue) = 0;
+ virtual void waitForAllJobs() = 0;
+
+ // Callback signature for running SynchronizedJobs
+ typedef void (*JobFunction)(void *);
+ virtual void waitForPerThreadFunction(JobFunction func, void *arg) = 0;
+};
+
+} // namespace Qt3D
+
+#endif // QJOBMANAGERINTERFACE_H
diff --git a/src/core/qjobproviderinterface.h b/src/core/qjobproviderinterface.h
new file mode 100644
index 000000000..891e44fff
--- /dev/null
+++ b/src/core/qjobproviderinterface.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QJOBPROVIDERINTERFACE_H
+#define QT3D_QJOBPROVIDERINTERFACE_H
+
+#include "qt3dcore_global.h"
+#include "qjob.h"
+
+#include <QVector>
+
+namespace Qt3D {
+
+class QJobProviderInterface
+{
+public:
+ virtual QVector<QJobPtr> jobsToExecute() = 0;
+};
+
+}
+
+#endif // QT3D_QJOBPROVIDERINTERFACE_H
diff --git a/src/core/qscheduler.cpp b/src/core/qscheduler.cpp
new file mode 100644
index 000000000..af175210c
--- /dev/null
+++ b/src/core/qscheduler.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscheduler.h"
+
+#include "abstractaspect.h"
+#include "qaspectmanager.h"
+#include "qjobmanagerinterface.h"
+
+namespace Qt3D {
+
+QScheduler::QScheduler(QObject *parent)
+ : QObject(parent)
+{
+}
+
+void QScheduler::setAspectManager(QAspectManager *aspectManager)
+{
+ m_aspectManager = aspectManager;
+}
+
+QAspectManager *QScheduler::aspectManager() const
+{
+ return m_aspectManager;
+}
+
+void QScheduler::update(qint64 time)
+{
+ // Get tasks for this frame from each aspect
+ const QList<AbstractAspect *> &aspects = m_aspectManager->aspects();
+ QHash<AbstractAspect::AspectType, QVector<QJobPtr> > jobs;
+ Q_FOREACH (AbstractAspect *aspect, aspects) {
+ QVector<QJobPtr> aspectJobs = aspect->jobsToExecute();
+ jobs.insert(aspect->aspectType(), aspectJobs);
+ }
+
+ // TODO: Set up dependencies between jobs as needed
+ // For now just queue them up as they are with render tasks first
+ QVector<QJobPtr> jobQueue;
+ for (int i = AbstractAspect::AspectRenderer; i <= AbstractAspect::AspectOther; ++i) {
+ AbstractAspect::AspectType aspectType = static_cast<AbstractAspect::AspectType>(i);
+ if (jobs.contains(aspectType))
+ jobQueue += jobs.value(aspectType);
+ }
+
+ m_aspectManager->jobManager()->enqueueJobs(jobQueue);
+
+ // Do any other work here that the aspect thread can usefully be doing
+ // whilst the threadpool works its way through the jobs
+
+ m_aspectManager->jobManager()->waitForAllJobs();
+}
+
+} // namespace Qt3D
diff --git a/src/core/qscheduler.h b/src/core/qscheduler.h
new file mode 100644
index 000000000..24e86ec4a
--- /dev/null
+++ b/src/core/qscheduler.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QSCHEDULER_H
+#define QT3D_QSCHEDULER_H
+
+#include <QObject>
+#include "qt3dcore_global.h"
+
+namespace Qt3D {
+
+class QAspectManager;
+
+class QScheduler : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QScheduler(QObject *parent = 0);
+
+ void setAspectManager(QAspectManager *aspectManager);
+ QAspectManager *aspectManager() const;
+
+ virtual void update(qint64 time);
+
+private:
+ QAspectManager *m_aspectManager;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_QSCHEDULER_H
diff --git a/src/core/qt3dcore_global.h b/src/core/qt3dcore_global.h
new file mode 100644
index 000000000..cb4d67321
--- /dev/null
+++ b/src/core/qt3dcore_global.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_GLOBAL_H
+#define QT3DCORE_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(QT3DCORE_LIBRARY)
+# define QT3DCORESHARED_EXPORT Q_DECL_EXPORT
+#else
+# define QT3DCORESHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // QT3DCORE_GLOBAL_H
diff --git a/src/core/qtickclock.cpp b/src/core/qtickclock.cpp
new file mode 100644
index 000000000..fbb9f7d68
--- /dev/null
+++ b/src/core/qtickclock.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtickclock.h"
+
+#include <QDebug>
+#include <QThread>
+
+namespace Qt3D {
+
+QTickClock::QTickClock(QObject *parent)
+ : QObject(parent)
+ , m_tickInterval(1000000000 / 60) // Nanoseconds
+ , m_time(0)
+{
+}
+
+void QTickClock::setTickFrequency(float frequency)
+{
+ Q_ASSERT(frequency > 0.0f);
+ m_tickInterval = static_cast<qint64>(1000000000 / frequency);
+}
+
+void QTickClock::start()
+{
+ m_timer.start();
+ m_time = m_timer.nsecsElapsed();
+ qDebug() << "tickInterval =" << m_tickInterval << "ns";
+}
+
+void QTickClock::reset()
+{
+ m_time = 0;
+}
+
+qint64 QTickClock::waitForNextTick()
+{
+ qint64 t = m_timer.nsecsElapsed();
+ qint64 dt = t - m_time;
+ qint64 timeToSleep = m_tickInterval - dt;
+
+ // If we are lagging behind don't delay
+ // TODO: Do we want a mode where if we are lagging we instead wait
+ // for the next tick instead?
+ if (timeToSleep < 0) {
+ qDebug() << "Lagging behind desired tick interval";
+ m_time = t;
+ return m_time;
+ }
+
+ unsigned long sleepTimeMicroSeconds = static_cast<unsigned long>(timeToSleep / 1000);
+ //qDebug() << "sleeping for" << sleepTimeMicroSeconds << "us";
+ QThread::usleep(sleepTimeMicroSeconds);
+
+#if defined(QT3D_DEBUG_TICKCLOCK)
+ qint64 expectedWakeTime = t + sleepTimeMicroSeconds * 1000;
+ qint64 wakeTime = m_timer.nsecsElapsed();
+ qDebug() << "t =" << t / 1000000 << "timeToSleep =" << timeToSleep / 1000000
+ << "due to wake at =" << expectedWakeTime / 1000000
+ << "actually woke at" << wakeTime / 1000000
+ << "delta =" << (expectedWakeTime - wakeTime) / 1000000;
+#endif
+
+ m_time = m_timer.nsecsElapsed();
+ return m_time;
+}
+
+}
diff --git a/src/core/qtickclock.h b/src/core/qtickclock.h
new file mode 100644
index 000000000..a82cf3f01
--- /dev/null
+++ b/src/core/qtickclock.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTICKCLOCK_H
+#define QTICKCLOCK_H
+
+#include <QObject>
+#include "qt3dcore_global.h"
+
+#include <QElapsedTimer>
+
+namespace Qt3D {
+
+class QTickClock : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QTickClock(QObject *parent = 0);
+
+ void setTickFrequency(float frequency);
+
+ void start();
+ void reset();
+
+ qint64 waitForNextTick();
+
+private:
+ QElapsedTimer m_timer;
+ qint64 m_tickInterval;
+ qint64 m_time;
+};
+
+} // namespace Qt3D
+
+#endif // QTICKCLOCK_H
diff --git a/src/core/rotatetransform.cpp b/src/core/rotatetransform.cpp
new file mode 100644
index 000000000..410e482fb
--- /dev/null
+++ b/src/core/rotatetransform.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define _USE_MATH_DEFINES // For MSVC
+#include "rotatetransform.h"
+
+#include <cmath>
+
+namespace Qt3D {
+
+RotateTransform::RotateTransform(Node *parent)
+ : AbstractTransform(parent)
+{
+}
+
+float RotateTransform::angleDeg() const
+{
+ return m_angleDeg;
+}
+
+float Qt3D::RotateTransform::angleRad() const
+{
+ return (m_angleDeg / 180.0) * M_PI;
+}
+
+QVector3D RotateTransform::axis() const
+{
+ return m_axis;
+}
+
+QMatrix4x4 RotateTransform::matrix() const
+{
+ QMatrix4x4 m;
+ m.rotate(m_angleDeg, m_axis);
+ return m;
+}
+
+void RotateTransform::setAngleDeg(float arg)
+{
+ if (m_angleDeg != arg) {
+ m_angleDeg = arg;
+ emit angleChanged();
+ }
+}
+
+void RotateTransform::setAngleRad(float arg)
+{
+ float angleDeg = (arg * M_PI) / 180.0f;
+ setAngleDeg(angleDeg);
+}
+
+void RotateTransform::setAxis(const QVector3D& arg)
+{
+ if (m_axis != arg) {
+ m_axis = arg;
+ emit axisChanged();
+ }
+}
+
+} // namespace Qt3D
diff --git a/src/core/rotatetransform.h b/src/core/rotatetransform.h
new file mode 100644
index 000000000..9921c82c4
--- /dev/null
+++ b/src/core/rotatetransform.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_ROTATETRANSFORM_H
+#define QT3D_ROTATETRANSFORM_H
+
+#include "abstracttransform.h"
+#include "qt3dcore_global.h"
+
+#include <QVector3D>
+
+namespace Qt3D {
+
+class RotateTransform : public AbstractTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(float angle READ angleDeg WRITE setAngleDeg NOTIFY angleChanged)
+ Q_PROPERTY(float angleRad READ angleRad WRITE setAngleRad NOTIFY angleChanged)
+
+ Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged)
+
+public:
+ explicit RotateTransform(Node *parent = 0);
+
+ float angleDeg() const;
+
+ float angleRad() const;
+
+ QVector3D axis() const;
+
+ virtual QMatrix4x4 matrix() const;
+
+public slots:
+ void setAngleDeg(float arg);
+
+ void setAngleRad(float arg);
+
+ void setAxis(const QVector3D& arg);
+
+signals:
+
+ void axisChanged();
+ void angleChanged();
+
+private:
+ float m_angleDeg;
+ QVector3D m_axis;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_ROTATETRANSFORM_H
diff --git a/src/core/scene.cpp b/src/core/scene.cpp
new file mode 100644
index 000000000..f8a1a15cc
--- /dev/null
+++ b/src/core/scene.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scene.h"
+
+#include <QDebug>
+
+#include <gltfparser.h>
+
+namespace Qt3D
+{
+
+Scene::Scene(Node* parent) :
+ Entity(parent)
+{
+}
+
+QString Scene::source() const
+{
+ return m_source;
+}
+
+QString Scene::sceneId() const
+{
+ return m_sceneId;
+}
+
+Scene *Scene::findInTree(Node *root)
+{
+ if (!root)
+ return NULL;
+
+ Scene* s = qobject_cast<Scene*>(root);
+ if (s)
+ return s;
+
+ // recursive walk down the tree
+ foreach (Node* nd, root->children()) {
+ s = findInTree(nd);
+ if (s)
+ return s;
+ }
+
+ return NULL;
+}
+
+void Scene::clear()
+{
+ removeAllChildren();
+}
+
+void Scene::setSource(QString arg)
+{
+ if (m_source != arg) {
+ m_source = arg;
+ rebuild();
+ emit sourceChanged(arg);
+ }
+}
+
+void Qt3D::Scene::setSceneId(QString arg)
+{
+ if (m_sceneId != arg) {
+ m_sceneId = arg;
+ rebuild();
+ emit sceneIdChanged(arg);
+ }
+}
+
+void Scene::rebuild()
+{
+ if (m_sceneChild) {
+ removeChild(m_sceneChild);
+ m_sceneChild->deleteLater();
+ }
+
+ if (GLTFParser::isGLTFPath(m_source)) {
+ qDebug() << Q_FUNC_INFO << "will load GLTF scene";
+
+ GLTFParser parser;
+ parser.setFilePath(m_source);
+
+ if (!m_sceneId.isEmpty())
+ m_sceneChild = parser.scene(m_sceneId);
+ else
+ m_sceneChild = parser.defaultScene();
+
+ if (m_sceneChild) {
+ addChild(m_sceneChild);
+ }
+ } else {
+
+ }
+}
+
+} // of namespace
diff --git a/src/core/scene.h b/src/core/scene.h
new file mode 100644
index 000000000..2fd67bb6c
--- /dev/null
+++ b/src/core/scene.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SCENE_H
+#define SCENE_H
+
+#include "entity.h"
+#include "qt3dcore_global.h"
+
+namespace Qt3D
+{
+
+class Scene : public Entity
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QString sceneId READ sceneId WRITE setSceneId NOTIFY sceneIdChanged)
+public:
+ explicit Scene(Node *parent = 0);
+
+ QString source() const;
+
+ QString sceneId() const;
+
+ /**
+ * @brief findInTree - given a Node* object rooting a tree, find
+ * the top-most Scene entity within.
+ * @param root - the found Scene or NULL if no Scene was found
+ * @return
+ */
+ static Scene* findInTree(Node* root);
+signals:
+
+ void sourceChanged(QString arg);
+
+ void sceneIdChanged(QString arg);
+
+public slots:
+ void clear();
+
+ void setSource(QString arg);
+
+ void setSceneId(QString arg);
+
+private:
+ void rebuild();
+
+ QString m_source;
+ QString m_sceneId;
+
+ Node* m_sceneChild;
+
+};
+
+} // of namespace
+
+#endif // SCENE_H
diff --git a/src/core/sphere.cpp b/src/core/sphere.cpp
new file mode 100644
index 000000000..3daf3804b
--- /dev/null
+++ b/src/core/sphere.cpp
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "sphere.h"
+
+#include <QPair>
+
+#include <math.h>
+
+namespace {
+
+inline QPair<int, int> findExtremePoints(const QVector<QVector3D> &points)
+{
+ // Find indices of extreme points along x, y, and z axes
+ int xMin = 0, xMax = 0, yMin = 0, yMax = 0, zMin = 0, zMax = 0;
+ for (int i = 1; i < points.size(); ++i) {
+ const QVector3D &p = points.at(i);
+ if (p.x() < points[xMin].x())
+ xMin = i;
+ if (p.x() > points[xMax].x())
+ xMax = i;
+ if (p.y() < points[yMin].y())
+ yMin = i;
+ if (p.y() > points[yMax].y())
+ yMax = i;
+ if (p.z() < points[zMin].z())
+ zMin = i;
+ if (p.z() > points[zMax].z())
+ zMax = i;
+ }
+
+ // Calculate squared distance for the pairs of points
+ const float xDist2 = (points.at(xMax) - points.at(xMin)).lengthSquared();
+ const float yDist2 = (points.at(yMax) - points.at(yMin)).lengthSquared();
+ const float zDist2 = (points.at(zMax) - points.at(zMin)).lengthSquared();
+
+ // Select most distant pair
+ QPair<int, int> extremeIndices(xMin, xMax);
+ if (yDist2 > xDist2 && yDist2 > zDist2)
+ extremeIndices = qMakePair(yMin, yMax);
+ if (zDist2 > xDist2 && zDist2 > yDist2)
+ extremeIndices = qMakePair(zMin, zMax);
+
+ return extremeIndices;
+}
+
+inline void sphereFromExtremePoints(Qt3D::Sphere &s, const QVector<QVector3D> &points)
+{
+ // Find two most separated points on any of the basis vectors
+ QPair<int, int> extremeIndices = findExtremePoints(points);
+
+ // Construct sphere to contain these two points
+ const QVector3D &p = points.at(extremeIndices.first);
+ const QVector3D &q = points.at(extremeIndices.second);
+ const QVector3D c = 0.5f * (p + q);
+ s.setCenter(c);
+ s.setRadius((q - c).length());
+}
+
+inline void constructRitterSphere(Qt3D::Sphere &s, const QVector<QVector3D> &points)
+{
+ // Calculate the sphere encompassing two axially extreme points
+ sphereFromExtremePoints(s, points);
+
+ // Now make sure the sphere bounds all points by growing if needed
+ s.expandToContain(points);
+}
+
+} // anonymous namespace
+
+namespace Qt3D {
+
+const float Sphere::ms_epsilon = 1.0e-7;
+
+Sphere Sphere::fromPoints(const QVector<QVector3D> &points)
+{
+ Sphere s;
+ s.initializeFromPoints(points);
+ return s;
+}
+
+void Sphere::initializeFromPoints(const QVector<QVector3D> &points)
+{
+ constructRitterSphere(*this, points);
+}
+
+void Sphere::expandToContain(const QVector3D &p)
+{
+ const QVector3D d = p - m_center;
+ const float dist2 = d.lengthSquared();
+
+ if (dist2 > m_radius * m_radius) {
+ // Expand radius so sphere also contains p
+ const float dist = sqrt(dist2);
+ const float newRadius = 0.5f * (m_radius + dist);
+ const float k = (newRadius - m_radius) / dist;
+ m_radius = newRadius;
+ m_center += k * d;
+ }
+}
+
+void Sphere::expandToContain(const Sphere &sphere)
+{
+ const QVector3D d(sphere.m_center - m_center);
+ const float dist2 = d.lengthSquared();
+
+ const float dr = sphere.m_radius - m_radius;
+ if (dr * dr >= dist2) {
+ // Larger sphere encloses the smaller. Set our size to the larger
+ if (m_radius > sphere.m_radius)
+ return;
+ else
+ *this = sphere;
+ } else {
+ // The spheres are overlapping or disjoint
+ const float dist = sqrt(dist2);
+ const float newRadius = 0.5f * (dist + m_radius + sphere.m_radius);
+ if (dist > ms_epsilon)
+ m_center += d * (newRadius - m_radius) / dist;
+ }
+}
+
+Sphere Sphere::transformed(const QMatrix4x4 &mat)
+{
+ // Transform extremities in x, y, and z directions to find extremities
+ // of the resulting ellipsoid
+ QVector3D x = mat.mapVector(m_center + QVector3D(m_radius, 0.0f, 0.0f));
+ QVector3D y = mat.mapVector(m_center + QVector3D(0.0f, m_radius, 0.0f));
+ QVector3D z = mat.mapVector(m_center + QVector3D(0.0f, 0.0f, m_radius));
+
+ // Transform center and find maximum radius of ellipsoid
+ QVector3D c = mat.mapVector(m_center);
+ float rSquared = qMax(qMax((x - c).lengthSquared(), (y - c).lengthSquared()), (z - c).lengthSquared());
+ return Sphere(c, sqrt(rSquared));
+}
+
+}
diff --git a/src/core/sphere.h b/src/core/sphere.h
new file mode 100644
index 000000000..6a46fce04
--- /dev/null
+++ b/src/core/sphere.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SPHERE_H
+#define SPHERE_H
+
+#include "qt3dcore_global.h"
+
+#include <QMatrix4x4>
+#include <QVector3D>
+
+namespace Qt3D {
+
+class QT3DCORESHARED_EXPORT Sphere
+{
+public:
+ inline Sphere()
+ : m_center(),
+ m_radius(0.0f)
+ {}
+
+ inline Sphere(const QVector3D &c, float r)
+ : m_center(c),
+ m_radius(r)
+ {}
+
+ void setCenter(const QVector3D &center);
+ QVector3D center() const;
+
+ void setRadius(float radius);
+ float radius() const;
+
+ void clear();
+ void initializeFromPoints(const QVector<QVector3D> &points);
+ void expandToContain(const QVector3D &point);
+ inline void expandToContain(const QVector<QVector3D> &points)
+ {
+ Q_FOREACH (const QVector3D &p, points)
+ expandToContain(p);
+ }
+
+ void expandToContain(const Sphere &sphere);
+
+ Sphere transformed(const QMatrix4x4 &mat);
+ inline Sphere &transform(const QMatrix4x4 &mat)
+ {
+ *this = transformed(mat);
+ return *this;
+ }
+
+ static Sphere fromPoints(const QVector<QVector3D> &points);
+
+private:
+ QVector3D m_center;
+ float m_radius;
+
+ static const float ms_epsilon;
+};
+
+inline void Sphere::setCenter(const QVector3D &center)
+{
+ m_center = center;
+}
+
+inline QVector3D Sphere::center() const
+{
+ return m_center;
+}
+
+inline void Sphere::setRadius(float radius)
+{
+ m_radius = radius;
+}
+
+inline float Sphere::radius() const
+{
+ return m_radius;
+}
+
+inline void Sphere::clear()
+{
+ m_center = QVector3D();
+ m_radius = 0.0f;
+}
+
+inline bool intersects(const Sphere &a, const Sphere &b)
+{
+ // Calculate squared distance between sphere centers
+ const QVector3D d = a.center() - b.center();
+ const float distSq = QVector3D::dotProduct(d, d);
+
+ // Spheres intersect if squared distance is less than squared
+ // sum of radii
+ const float sumRadii = a.radius() + b.radius();
+ return distSq <= sumRadii * sumRadii;
+}
+
+}
+
+#endif // SPHERE_H
diff --git a/src/core/translatetransform.cpp b/src/core/translatetransform.cpp
new file mode 100644
index 000000000..faf65ca9f
--- /dev/null
+++ b/src/core/translatetransform.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translatetransform.h"
+
+namespace Qt3D {
+
+TranslateTransform::TranslateTransform(Node *parent)
+ : AbstractTransform(parent)
+{
+}
+
+float TranslateTransform::dx() const
+{
+ return m_translation.x();
+}
+
+float TranslateTransform::dy() const
+{
+ return m_translation.y();
+}
+
+float TranslateTransform::dz() const
+{
+ return m_translation.z();
+}
+
+QVector3D TranslateTransform::translation() const
+{
+ return m_translation;
+}
+
+QMatrix4x4 TranslateTransform::matrix() const
+{
+ QMatrix4x4 r;
+ r.translate(m_translation);
+ return r;
+}
+
+void TranslateTransform::setDx(float arg)
+{
+ if (arg != m_translation.x()) {
+ m_translation.setX(arg);
+ emit translateChanged();
+ }
+}
+
+void TranslateTransform::setDy(float arg)
+{
+ if (arg != m_translation.y()) {
+ m_translation.setY(arg);
+ emit translateChanged();
+ }
+}
+
+void TranslateTransform::setDz(float arg)
+{
+ if (arg != m_translation.z()) {
+ m_translation.setZ(arg);
+ emit translateChanged();
+ }
+}
+
+void TranslateTransform::setTranslation(QVector3D arg)
+{
+ if (m_translation != arg) {
+ m_translation = arg;
+ emit translateChanged();
+ }
+}
+
+} // namespace Qt3D
diff --git a/src/core/translatetransform.h b/src/core/translatetransform.h
new file mode 100644
index 000000000..9dd1fb7cb
--- /dev/null
+++ b/src/core/translatetransform.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_TRANSLATETRANSFORM_H
+#define QT3D_TRANSLATETRANSFORM_H
+
+#include "abstracttransform.h"
+#include "qt3dcore_global.h"
+
+#include <QVector3D>
+
+namespace Qt3D {
+
+class TranslateTransform : public AbstractTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(float dx READ dx WRITE setDx NOTIFY translateChanged)
+ Q_PROPERTY(float dy READ dy WRITE setDy NOTIFY translateChanged)
+ Q_PROPERTY(float dz READ dz WRITE setDz NOTIFY translateChanged)
+ Q_PROPERTY(QVector3D t READ translation WRITE setTranslation NOTIFY translateChanged)
+
+public:
+ explicit TranslateTransform(Node *parent = 0);
+
+ float dx() const;
+ float dy() const;
+ float dz() const;
+
+ QVector3D translation() const;
+
+ virtual QMatrix4x4 matrix() const;
+
+public slots:
+ void setDx(float arg);
+ void setDy(float arg);
+ void setDz(float arg);
+
+ void setTranslation(QVector3D arg);
+
+signals:
+ void translateChanged();
+
+private:
+ QVector3D m_translation;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_TRANSLATETRANSFORM_H
diff --git a/src/core/window.cpp b/src/core/window.cpp
new file mode 100644
index 000000000..7aee2b7cb
--- /dev/null
+++ b/src/core/window.cpp
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "window.h"
+
+#include <QDebug>
+#include <QQmlComponent>
+#include <QTimer>
+#include <QKeyEvent>
+#include <QMouseEvent>
+#include <QGuiApplication>
+
+#include "node.h"
+#include "camera.h"
+#include "entity.h"
+#include <qaspectengine.h>
+
+#include "cameracontroller.h"
+
+namespace Qt3D {
+
+Window::Window(QScreen *screen)
+ : QWindow(screen)
+ , m_engine(new QQmlEngine)
+ , m_aspectEngine(new QAspectEngine(this))
+ , m_camera(NULL)
+ , m_controller(NULL)
+
+{
+ setSurfaceType(QSurface::OpenGLSurface);
+
+ resize(1024, 768);
+
+ QSurfaceFormat format;
+ format.setVersion(4, 3);
+ format.setDepthBufferSize( 24 );
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ setFormat(format);
+
+ m_aspectEngine->initialize();
+ m_aspectEngine->setWindow(this);
+
+ m_controller = new CameraController;
+
+ m_updateTimer = new QTimer(this);
+ m_updateTimer->setInterval(16);
+ connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(onUpdate()));
+}
+
+Window::~Window()
+{
+ m_aspectEngine->shutdown();
+ delete m_aspectEngine;
+}
+
+Window::Status Window::status() const
+{
+ if (!m_engine)
+ return Error;
+
+ if (!m_component)
+ return Null;
+
+ return Status(m_component->status());
+}
+
+void Window::setSource( const QUrl& source )
+{
+ if (!m_engine) {
+ qWarning() << "Window: invalid qml engine.";
+ return;
+ }
+
+ if (m_root) {
+ m_aspectEngine->shutdown();
+ m_aspectEngine->setRoot(0);
+ m_root = QSharedPointer<QObject>();
+ }
+
+ if (m_component)
+ m_component = QSharedPointer<QQmlComponent>();
+
+ if (!source.isEmpty()) {
+ m_component = QSharedPointer<QQmlComponent>(new QQmlComponent(m_engine.data(), source, this));
+ if (!m_component->isLoading()) {
+ continueExecute();
+ } else {
+ QObject::connect(m_component.data(), SIGNAL(statusChanged(QQmlComponent::Status)),
+ this, SLOT(continueExecute()));
+ }
+ }
+}
+
+void Window::continueExecute()
+{
+ qDebug() << Q_FUNC_INFO;
+
+ disconnect(m_component.data(), SIGNAL(statusChanged(QQmlComponent::Status)),
+ this, SLOT(continueExecute()));
+
+ if (m_component->isError()) {
+ QList<QQmlError> errorList = m_component->errors();
+ Q_FOREACH ( const QQmlError& error, errorList ) {
+ QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
+ << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ QObject* obj = m_component->create();
+
+ if (m_component->isError()) {
+ QList<QQmlError> errorList = m_component->errors();
+ Q_FOREACH ( const QQmlError& error, errorList ) {
+ QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
+ << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ setRootObject(obj);
+ emit statusChanged(status());
+}
+
+void Window::onUpdate()
+{
+ m_controller->update(1.0 / 60.0);
+}
+
+void Window::setRootObject( QObject* obj )
+{
+ if (m_root == obj)
+ return;
+
+ if (obj) {
+ obj->setParent( this );
+ m_root = QSharedPointer<QObject>(obj);
+ }
+
+ m_aspectEngine->setRoot(obj);
+
+ // Hook up controller input to camera
+ // TODO: Do this more generically as we may want keyboard ot control an Entity etc
+ m_camera = Entity::findComponentInTree<Camera>(qobject_cast<Node *>(m_root.data()));
+ if (m_camera) {
+ qDebug() << "found a camera in the scene";
+ m_controller->setCamera(m_camera);
+ m_updateTimer->start();
+ }
+
+//
+// Entity *ball = node->findChild<Entity *>(QStringLiteral("ball"));
+// if (ball) {
+// QList<Component *> components = ball->components();
+// qDebug() << components;
+// }
+
+ //Node *node = qobject_cast<Node *>(m_root.data());
+ //if (node)
+ //node->dump();
+}
+
+void Window::resizeEvent( QResizeEvent* e )
+{
+ Q_UNUSED( e );
+
+}
+
+void Window::keyPressEvent( QKeyEvent* e )
+{
+ if (m_controller->keyPressEvent(e))
+ return;
+
+ switch ( e->key() )
+ {
+ case Qt::Key_Escape:
+ QGuiApplication::quit();
+ break;
+
+ default:
+ QWindow::keyPressEvent( e );
+ }
+}
+
+void Window::keyReleaseEvent( QKeyEvent* e )
+{
+ if (m_controller->keyReleaseEvent(e))
+ return;
+
+ QWindow::keyReleaseEvent(e);
+}
+
+void Window::mousePressEvent( QMouseEvent* e )
+{
+ m_controller->mousePressEvent(e);
+}
+
+void Window::mouseReleaseEvent( QMouseEvent* e )
+{
+ m_controller->mouseReleaseEvent(e);
+}
+
+void Window::mouseMoveEvent( QMouseEvent* e )
+{
+ m_controller->mouseMoveEvent(e);
+}
+
+
+} // namespace Qt3D
diff --git a/src/core/window.h b/src/core/window.h
new file mode 100644
index 000000000..7ded46973
--- /dev/null
+++ b/src/core/window.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_WINDOW_H
+#define QT3D_WINDOW_H
+
+#include <QWindow>
+#include "qt3dcore_global.h"
+
+#include <QQmlEngine>
+
+class QTimer;
+
+namespace Qt3D {
+
+class AbstractAspect;
+class QAspectEngine;
+class Camera;
+
+// temporary solution to get control over camera
+class CameraController;
+
+class Window : public QWindow
+{
+ Q_OBJECT
+public:
+ explicit Window(QScreen *screen = 0);
+ ~Window();
+
+ void setSource( const QUrl& url );
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+
+ QSharedPointer<QObject> rootObject() { return m_root; }
+
+signals:
+ void statusChanged( Qt3D::Window::Status );
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void keyReleaseEvent( QKeyEvent* e );
+
+ virtual void mousePressEvent( QMouseEvent* e );
+ virtual void mouseReleaseEvent( QMouseEvent* e );
+ virtual void mouseMoveEvent( QMouseEvent* e );
+ virtual void resizeEvent(QResizeEvent *e);
+
+private slots:
+ void continueExecute();
+
+ void onUpdate();
+
+private:
+ void setRootObject( QObject* obj );
+
+ QScopedPointer<QQmlEngine> m_engine;
+ QSharedPointer<QObject> m_root;
+ QSharedPointer<QQmlComponent> m_component;
+
+ // The various aspects (subsystems) that will be interested in (parts)
+ // of the objects in the object tree.
+ QAspectEngine *m_aspectEngine;
+
+ QList<Qt3D::AbstractAspect*> m_aspects;
+
+ Camera* m_camera;
+
+ // temporary, borrowed from training material
+ CameraController* m_controller;
+
+ QTimer* m_updateTimer;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_WINDOW_H
diff --git a/src/render/backend/drawable.cpp b/src/render/backend/drawable.cpp
new file mode 100644
index 000000000..4690a6b78
--- /dev/null
+++ b/src/render/backend/drawable.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "drawable.h"
+
+namespace Qt3D {
+
+Drawable::Drawable()
+{
+
+}
+
+Drawable::~Drawable()
+{
+
+}
+
+DrawStateSet *Drawable::stateSet()
+{
+ return NULL;
+}
+
+void Drawable::initializeGL(QGraphicsContext* dc)
+{
+ Q_UNUSED(dc);
+}
+
+void Drawable::releaseGL()
+{
+
+}
+
+#if 0
+RenderNode *Drawable::node() const
+{
+ return m_node;
+}
+#endif
+
+} // of namespace
+
diff --git a/src/render/backend/drawable.h b/src/render/backend/drawable.h
new file mode 100644
index 000000000..980891b91
--- /dev/null
+++ b/src/render/backend/drawable.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_DRAWABLE_H
+#define QT3D_DRAWABLE_H
+
+#include <QObject>
+
+#include <axisalignedboundingbox.h>
+
+namespace Qt3D {
+
+class QGraphicsContext;
+class RenderShader;
+class DrawStateSet;
+
+class Drawable
+{
+public:
+ Drawable();
+
+ virtual ~Drawable();
+
+ // RenderNode* node() const;
+
+ /**
+ * @brief make OpenGL drawing commands for this drawable.
+ *
+ * The correct context and shader will already be defined,
+ * along with the transformation state. This method will
+ * be run from the rendering thread, and hence should take
+ * care if using mutable buffer data.
+ *
+ */
+ virtual void sendDrawingCommands( QGraphicsContext* gc ) = 0;
+
+ /**
+ * @brief shader
+ * @return
+ */
+ virtual RenderShader* shader() = 0;
+
+
+ virtual DrawStateSet* stateSet();
+
+ /**
+ * @brief Called by render thread to initialize resources
+ *
+ * This will be called in the context of the renderer thread
+ * once it has a fully created OpenGL context. The shader program for
+ * this drawable will be active (so attribute data can be bound)
+ */
+ virtual void initializeGL(QGraphicsContext* dc);
+
+ virtual void releaseGL();
+
+ virtual AxisAlignedBoundingBox boundingBox() const = 0;
+
+protected:
+
+};
+
+}
+
+#endif // of QT3D_DRAWABLE_H
diff --git a/src/render/backend/drawstate.cpp b/src/render/backend/drawstate.cpp
new file mode 100644
index 000000000..08b87f961
--- /dev/null
+++ b/src/render/backend/drawstate.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "drawstate.h"
+
+#include <bitset>
+
+#include <QDebug>
+#include <QOpenGLContext>
+
+#include "qgraphicscontext.h"
+
+#include "states/blendstate.h"
+
+namespace Qt3D {
+
+DrawStateSet::DrawStateSet()
+{
+
+}
+
+void DrawStateSet::addState(DrawState *ds)
+{
+ Q_ASSERT(ds);
+ m_states.insert(ds);
+ m_stateMask |= ds->mask();
+}
+
+int DrawStateSet::changeCost(DrawStateSet *previousState)
+{
+ if (previousState == this)
+ return 0;
+
+ int cost = 0;
+
+// first, find cost of any resets
+ StateMaskSet invOurState = ~stateMask();
+ StateMaskSet stateToReset = previousState->stateMask() & invOurState;
+
+ std::bitset<64> bs(stateToReset);
+ cost += bs.count();
+
+// now, find out how many states we're changing
+ foreach (DrawState* ds, m_states) {
+ // if the other state contains matching, then doesn't
+ // contribute to cost at all
+ if (previousState->contains(ds)) {
+ continue;
+ }
+
+ // flat cost for now; could be replaced with a cost() method on
+ // DrawState
+ cost += 2;
+ }
+
+ return cost;
+}
+
+void DrawStateSet::apply(QGraphicsContext *gc)
+{
+ DrawStateSet* previousStates = gc->currentStateSet();
+
+ StateMaskSet invOurState = ~stateMask();
+ // generate a mask for each set bit in previous, where we do not have
+ // the corresponding bit set.
+ StateMaskSet stateToReset = 0;
+ if (previousStates)
+ stateToReset = previousStates->stateMask() & invOurState;
+
+ resetMasked(stateToReset, gc);
+
+ if (previousStates == m_cachedPrevious) {
+ // state-change cache hit
+ foreach (DrawState* ds, m_cachedDeltaStates) {
+ ds->apply(gc);
+ }
+ } else {
+ // compute deltas and cache for next frame
+ m_cachedDeltaStates.clear();
+ m_cachedPrevious = previousStates;
+
+ foreach (DrawState* ds, m_states) {
+ if (previousStates && previousStates->contains(ds)) {
+ continue;
+ }
+
+ m_cachedDeltaStates.append(ds);
+ ds->apply(gc);
+ }
+ }
+}
+
+StateMaskSet DrawStateSet::stateMask() const
+{
+ return m_stateMask;
+}
+
+void DrawStateSet::resetMasked(StateMaskSet maskOfStatesToReset, QGraphicsContext *gc)
+{
+ Q_UNUSED(gc);
+
+ if (maskOfStatesToReset & ScissorStateMask) {
+ glDisable(GL_SCISSOR_TEST);
+ }
+
+ if (maskOfStatesToReset & BlendStateMask) {
+ glDisable(GL_BLEND);
+ }
+
+ if (maskOfStatesToReset & StencilWriteStateMask) {
+ glStencilMask(0);
+ }
+
+ if (maskOfStatesToReset & StencilTestStateMask) {
+ glDisable(GL_STENCIL_TEST);
+ }
+
+ if (maskOfStatesToReset & DepthTestStateMask) {
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ if (maskOfStatesToReset & DepthWriteStateMask) {
+ glDepthMask(GL_TRUE); // reset to default
+ }
+
+ if (maskOfStatesToReset & FrontFaceStateMask) {
+ glFrontFace(GL_CCW); // reset to default
+ }
+
+ if (maskOfStatesToReset & CullFaceStateMask) {
+ glDisable(GL_CULL_FACE);
+ }
+}
+
+bool DrawStateSet::contains(DrawState *ds) const
+{
+ // trivial reject using the state mask bits
+ if (!(ds->mask() & stateMask()))
+ return false;
+
+ return m_states.contains(ds);
+}
+
+} // namespace Qt3D
diff --git a/src/render/backend/drawstate.h b/src/render/backend/drawstate.h
new file mode 100644
index 000000000..bd7bc26ca
--- /dev/null
+++ b/src/render/backend/drawstate.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_DRAWSTATE_H
+#define QT3D_DRAWSTATE_H
+
+#include <QList>
+#include <QSet>
+
+namespace Qt3D {
+
+class QGraphicsContext;
+
+enum StateMask
+{
+ BlendStateMask = 1 << 0,
+ StencilWriteStateMask = 1 << 1,
+ StencilTestStateMask = 1 << 2,
+ ScissorStateMask = 1 << 3,
+ DepthTestStateMask = 1 << 4,
+ DepthWriteStateMask = 1 << 5,
+ CullFaceStateMask = 1 << 6,
+ AlphaTestMask = 1 << 7,
+ FrontFaceStateMask = 1 << 8
+};
+
+typedef quint64 StateMaskSet;
+
+// winuser.h has a #define called DrawState. Let's get rid of it
+#if defined(DrawState)
+#undef DrawState
+#endif
+
+class DrawState
+{
+public:
+ virtual void apply(QGraphicsContext* gc) const = 0;
+
+ virtual StateMaskSet mask() const = 0;
+
+protected:
+};
+
+class DrawStateSet
+{
+public:
+ DrawStateSet();
+
+ void addState(DrawState* ds);
+
+ /**
+ * @brief changeCost - metric of cost to change to this state-set from
+ * a candidate previous state-set. This is used to find an optimal
+ * ordering of state-sets when sending draw commands.
+ * @param previousState
+ * @return
+ */
+ int changeCost(DrawStateSet* previousState);
+
+ void apply(QGraphicsContext* gc);
+
+ StateMaskSet stateMask() const;
+
+ void resetMasked(StateMaskSet maskOfStatesToReset, QGraphicsContext* gc);
+private:
+ /**
+ * @brief contains - check if this set contains a matching piece of state
+ * @param ds
+ * @return
+ */
+ bool contains(DrawState* ds) const;
+
+ QSet<DrawState*> m_states;
+
+ StateMaskSet m_stateMask;
+
+ DrawStateSet* m_cachedPrevious;
+ QList<DrawState*> m_cachedDeltaStates;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_DRAWSTATE_H
diff --git a/src/render/backend/framegraph/cameraselectornode.cpp b/src/render/backend/framegraph/cameraselectornode.cpp
new file mode 100644
index 000000000..d1d1bfac0
--- /dev/null
+++ b/src/render/backend/framegraph/cameraselectornode.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "cameraselectornode.h"
+
+#include <QDebug>
+
+namespace Qt3D {
+namespace Render {
+
+CameraSelector::CameraSelector(FrameGraphNode *parent)
+ : FrameGraphNode(parent)
+{
+}
+
+void CameraSelector::apply()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+void CameraSelector::revert()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+}
+}
diff --git a/src/render/backend/framegraph/cameraselectornode.h b/src/render/backend/framegraph/cameraselectornode.h
new file mode 100644
index 000000000..326ba600b
--- /dev/null
+++ b/src/render/backend/framegraph/cameraselectornode.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CAMERASELECTOR_H
+#define CAMERASELECTOR_H
+
+#include "framegraphnode.h"
+
+namespace Qt3D {
+
+class Camera;
+
+namespace Render {
+
+class CameraSelector : public FrameGraphNode
+{
+public:
+ CameraSelector(FrameGraphNode *parent = 0);
+
+ void apply() Q_DECL_OVERRIDE;
+ void revert() Q_DECL_OVERRIDE;
+
+//private:
+ Camera *m_camera;
+};
+
+}
+}
+
+#endif // CAMERASELECTOR_H
diff --git a/src/render/backend/framegraph/framegraph.pri b/src/render/backend/framegraph/framegraph.pri
new file mode 100644
index 000000000..c04191dc5
--- /dev/null
+++ b/src/render/backend/framegraph/framegraph.pri
@@ -0,0 +1,15 @@
+HEADERS += \
+ $$PWD/cameraselectornode.h \
+ $$PWD/framegraphnode.h \
+ $$PWD/framegraphvisitor.h \
+ $$PWD/renderpassfilternode.h \
+ $$PWD/techniquefilternode.h \
+ $$PWD/viewportnode.h
+
+SOURCES += \
+ $$PWD/cameraselectornode.cpp \
+ $$PWD/framegraphnode.cpp \
+ $$PWD/framegraphvisitor.cpp \
+ $$PWD/renderpassfilternode.cpp \
+ $$PWD/techniquefilternode.cpp \
+ $$PWD/viewportnode.cpp
diff --git a/src/render/backend/framegraph/framegraphnode.cpp b/src/render/backend/framegraph/framegraphnode.cpp
new file mode 100644
index 000000000..b6b80afce
--- /dev/null
+++ b/src/render/backend/framegraph/framegraphnode.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "framegraphnode.h"
+
+#include <QDebug>
+
+namespace Qt3D {
+namespace Render {
+
+FrameGraphNode::FrameGraphNode(FrameGraphNode *parent)
+ : m_parent(parent)
+ , m_enabled(true)
+{
+ if (parent)
+ parent->m_children.append(this);
+}
+
+FrameGraphNode::~FrameGraphNode()
+{
+}
+
+void FrameGraphNode::apply()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+void FrameGraphNode::revert()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/framegraph/framegraphnode.h b/src/render/backend/framegraph/framegraphnode.h
new file mode 100644
index 000000000..0fd0a2e3f
--- /dev/null
+++ b/src/render/backend/framegraph/framegraphnode.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_FRAMEGRAPHNODE_H
+#define QT3D_RENDER_FRAMEGRAPHNODE_H
+
+#include <QVector>
+
+namespace Qt3D {
+namespace Render {
+
+class FrameGraphNode
+{
+public:
+ FrameGraphNode(FrameGraphNode *parent = 0);
+ virtual ~FrameGraphNode();
+
+ FrameGraphNode *parent() const { return m_parent; }
+
+ int childCount() const { return m_children.count(); }
+ FrameGraphNode * child(int index) const { return m_children.at(index); }
+
+ void setEnabled(bool enabled) { m_enabled = enabled; }
+ bool isEnabled() const { return m_enabled; }
+
+protected:
+ virtual void apply();
+ virtual void revert();
+
+private:
+ FrameGraphNode *m_parent;
+ QVector<FrameGraphNode *> m_children;
+
+ bool m_enabled;
+
+ friend class FrameGraphVisitor;
+};
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_FRAMEGRAPHNODE_H
diff --git a/src/render/backend/framegraph/framegraphvisitor.cpp b/src/render/backend/framegraph/framegraphvisitor.cpp
new file mode 100644
index 000000000..b74a77873
--- /dev/null
+++ b/src/render/backend/framegraph/framegraphvisitor.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "framegraphvisitor.h"
+
+#include "framegraphnode.h"
+#include "renderer.h"
+
+namespace Qt3D {
+namespace Render {
+
+FrameGraphVisitor::FrameGraphVisitor()
+{
+}
+
+void FrameGraphVisitor::traverse(FrameGraphNode *root, Renderer *renderer)
+{
+ m_renderer = renderer;
+
+ // Kick off the traversal
+ FrameGraphNode *node = root;
+ visit(node);
+}
+
+void FrameGraphVisitor::visit(FrameGraphNode *node)
+{
+ // Apply the state from this node
+ node->apply();
+
+ // Recurse to children (if we have any), otherwise if this is a leaf node,
+ // initiate a rendering from the current camera
+ if (node->childCount()) {
+ for (int i = 0; i < node->childCount(); ++i) {
+ FrameGraphNode *n = node->child(i);
+ visit(n);
+ }
+ } else {
+ // Leaf node. All state is applied and renderer context configured.
+ // Go render something
+ m_renderer->doRender();
+ }
+
+ // Undo the applied state as we exit this node
+ node->revert();
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/framegraph/framegraphvisitor.h b/src/render/backend/framegraph/framegraphvisitor.h
new file mode 100644
index 000000000..174a90bdf
--- /dev/null
+++ b/src/render/backend/framegraph/framegraphvisitor.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDERER_FRAMEGRAPHVISITOR_H
+#define QT3D_RENDERER_FRAMEGRAPHVISITOR_H
+
+namespace Qt3D {
+namespace Render {
+
+class FrameGraphNode;
+class Renderer;
+
+class FrameGraphVisitor
+{
+public:
+ FrameGraphVisitor();
+
+ void traverse(FrameGraphNode *root, Renderer *renderer);
+
+private:
+ void visit(FrameGraphNode *node);
+
+ Renderer *m_renderer;
+};
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDERER_FRAMEGRAPHVISITOR_H
diff --git a/src/render/backend/framegraph/renderpassfilternode.cpp b/src/render/backend/framegraph/renderpassfilternode.cpp
new file mode 100644
index 000000000..89b3d4e0c
--- /dev/null
+++ b/src/render/backend/framegraph/renderpassfilternode.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderpassfilternode.h"
+
+#include <QDebug>
+
+namespace Qt3D {
+namespace Render {
+
+RenderPassFilter::RenderPassFilter(FrameGraphNode *parent)
+ : FrameGraphNode(parent)
+{
+}
+
+void RenderPassFilter::apply()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+void RenderPassFilter::revert()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+}
+}
diff --git a/src/render/backend/framegraph/renderpassfilternode.h b/src/render/backend/framegraph/renderpassfilternode.h
new file mode 100644
index 000000000..ed05e6b5c
--- /dev/null
+++ b/src/render/backend/framegraph/renderpassfilternode.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERPASSFILTER_H
+#define RENDERPASSFILTER_H
+
+#include "framegraphnode.h"
+
+#include <QStringList>
+
+namespace Qt3D {
+namespace Render {
+
+class RenderPassFilter : public FrameGraphNode
+{
+public:
+ RenderPassFilter(FrameGraphNode *parent = 0);
+
+ void apply() Q_DECL_OVERRIDE;
+ void revert() Q_DECL_OVERRIDE;
+
+//private:
+ QStringList m_filters;
+};
+
+}
+
+}
+
+#endif // RENDERPASSFILTER_H
diff --git a/src/render/backend/framegraph/techniquefilternode.cpp b/src/render/backend/framegraph/techniquefilternode.cpp
new file mode 100644
index 000000000..3c021c77c
--- /dev/null
+++ b/src/render/backend/framegraph/techniquefilternode.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "techniquefilternode.h"
+
+#include <QDebug>
+
+namespace Qt3D {
+namespace Render {
+
+TechniqueFilter::TechniqueFilter(FrameGraphNode *parent)
+ : FrameGraphNode(parent)
+{
+}
+
+void TechniqueFilter::apply()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+void TechniqueFilter::revert()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+}
+}
diff --git a/src/render/backend/framegraph/techniquefilternode.h b/src/render/backend/framegraph/techniquefilternode.h
new file mode 100644
index 000000000..f6c801019
--- /dev/null
+++ b/src/render/backend/framegraph/techniquefilternode.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TECHNIQUEFILTER_H
+#define TECHNIQUEFILTER_H
+
+#include "framegraphnode.h"
+
+#include <QHash>
+#include <QString>
+#include <QVariant>
+
+namespace Qt3D {
+namespace Render {
+
+class TechniqueFilter : public FrameGraphNode
+{
+public:
+ TechniqueFilter(FrameGraphNode *parent = 0);
+
+ void apply() Q_DECL_OVERRIDE;
+ void revert() Q_DECL_OVERRIDE;
+
+//private:
+ QHash<QString, QVariant> m_filters;
+};
+
+}
+}
+
+#endif // TECHNIQUEFILTER_H
diff --git a/src/render/backend/framegraph/viewportnode.cpp b/src/render/backend/framegraph/viewportnode.cpp
new file mode 100644
index 000000000..bac967975
--- /dev/null
+++ b/src/render/backend/framegraph/viewportnode.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "viewportnode.h"
+
+#include <QDebug>
+
+namespace Qt3D {
+namespace Render {
+
+ViewportNode::ViewportNode(FrameGraphNode *parent)
+ : FrameGraphNode(parent)
+ , m_xMin(0.0f)
+ , m_yMin(0.0f)
+ , m_xMax(1.0f)
+ , m_yMax(1.0f)
+{
+}
+
+void ViewportNode::apply()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+void ViewportNode::revert()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+}
+}
diff --git a/src/render/backend/framegraph/viewportnode.h b/src/render/backend/framegraph/viewportnode.h
new file mode 100644
index 000000000..6d1b643a5
--- /dev/null
+++ b/src/render/backend/framegraph/viewportnode.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIEWPORT_H
+#define VIEWPORT_H
+
+#include "framegraphnode.h"
+
+namespace Qt3D {
+namespace Render {
+
+class ViewportNode : public FrameGraphNode
+{
+public:
+ ViewportNode(FrameGraphNode *parent = 0);
+
+ void apply() Q_DECL_OVERRIDE;
+ void revert() Q_DECL_OVERRIDE;
+
+//private:
+ float m_xMin;
+ float m_yMin;
+ float m_xMax;
+ float m_yMax;
+};
+
+}
+}
+
+#endif // VIEWPORT_H
diff --git a/src/render/backend/genericstate.h b/src/render/backend/genericstate.h
new file mode 100644
index 000000000..c95a6af4d
--- /dev/null
+++ b/src/render/backend/genericstate.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef STATE_IMPLS_H
+#define STATE_IMPLS_H
+
+#include <QList>
+
+#include "drawstate.h"
+
+// winuser.h has a #define called DrawState. Let's get rid of it
+#if defined(DrawState)
+#undef DrawState
+#endif
+
+namespace Qt3D
+{
+
+template <typename Derived, typename T>
+class GenericState1 : public DrawState
+{
+public:
+
+ bool isEqual(const Derived& i) const
+ { return (m_1 == i.m_1); }
+
+
+protected:
+ GenericState1(T t) :
+ m_1(t)
+ {}
+
+ T m_1;
+
+};
+
+template <typename Derived, typename T, typename S>
+class GenericState2 : public DrawState
+{
+public:
+ bool isEqual(const Derived& i) const
+ { return (m_1 == i.m_1) && (m_2 == i.m_2); }
+protected:
+ GenericState2(T t, S s) :
+ m_1(t),
+ m_2(s)
+ {}
+
+
+ T m_1;
+ S m_2;
+};
+
+template <typename Derived, typename T, typename S, typename U>
+class GenericState3
+{
+public:
+ bool isEqual(const Derived& i) const
+ { return (m_1 == i.m_1) && (m_2 == i.m_2) && (m_3 == i.m_3); }
+
+protected:
+ GenericState3(T t, S s, U u) :
+ m_1(t),
+ m_2(s),
+ m_3(u)
+ {}
+
+ T m_1;
+ S m_2;
+ U m_3;
+
+};
+
+} // of namespace
+
+#endif // STATE_IMPLS_H
diff --git a/src/render/backend/jobs/jobs.pri b/src/render/backend/jobs/jobs.pri
new file mode 100644
index 000000000..85e350fdd
--- /dev/null
+++ b/src/render/backend/jobs/jobs.pri
@@ -0,0 +1,11 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/updateworldtransformjob.h \
+ $$PWD/updateboundingvolumejob.h \
+ $$PWD/loadmeshdatajob.h
+
+SOURCES += \
+ $$PWD/updateworldtransformjob.cpp \
+ $$PWD/updateboundingvolumejob.cpp \
+ $$PWD/loadmeshdatajob.cpp \ No newline at end of file
diff --git a/src/render/backend/jobs/loadmeshdatajob.cpp b/src/render/backend/jobs/loadmeshdatajob.cpp
new file mode 100644
index 000000000..29a6047c7
--- /dev/null
+++ b/src/render/backend/jobs/loadmeshdatajob.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "loadmeshdatajob.h"
+
+#include <objloader.h>
+#include <sphere.h>
+
+#include <QDebug>
+#include <QThread>
+
+namespace Qt3D {
+namespace Render {
+
+LoadMeshDataJob::LoadMeshDataJob(const QString &source, const MeshDataPtr &meshData)
+ : QJob()
+ , m_source(source)
+ , m_meshData(meshData)
+{
+}
+
+void LoadMeshDataJob::run()
+{
+ qDebug() << "Entering" << Q_FUNC_INFO << QThread::currentThread();
+
+ // Load the mesh from disk (or wherever)
+ qDebug() << "Loading mesh from" << m_source;
+
+ ObjLoader loader;
+ loader.setLoadTextureCoordinatesEnabled(true);
+
+ if (loader.load(m_source)) {
+ qDebug() << "Loaded OBJ ok";
+ *m_meshData = *(loader.mesh());
+ } else {
+ qWarning() << Q_FUNC_INFO << "OBJ load failure for:" << m_source;
+ }
+
+ AttributePtr attr = m_meshData->attributeByName("position");
+ if (!attr) {
+ qWarning() << Q_FUNC_INFO << "unknown attribute: position";
+ return;
+ }
+
+ Qt3D::Sphere sphere = Qt3D::Sphere::fromPoints(loader.vertices());
+
+ qDebug() << "Exiting" << Q_FUNC_INFO << QThread::currentThread();
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/jobs/loadmeshdatajob.h b/src/render/backend/jobs/loadmeshdatajob.h
new file mode 100644
index 000000000..e9f155e35
--- /dev/null
+++ b/src/render/backend/jobs/loadmeshdatajob.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_LOADMESHDATAJOB_H
+#define QT3D_RENDER_LOADMESHDATAJOB_H
+
+#include <qjob.h>
+
+#include <meshdata.h>
+
+#include <QSharedPointer>
+
+namespace Qt3D {
+namespace Render {
+
+class LoadMeshDataJob : public Qt3D::QJob
+{
+public:
+ LoadMeshDataJob(const QString &source,
+ const Qt3D::MeshDataPtr &meshData);
+
+protected:
+ void run() Q_DECL_OVERRIDE;
+
+private:
+ QString m_source;
+ Qt3D::MeshDataPtr m_meshData;
+};
+
+typedef QSharedPointer<LoadMeshDataJob> LoadMeshDataJobPtr;
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_LOADMESHDATAJOB_H
diff --git a/src/render/backend/jobs/updateboundingvolumejob.cpp b/src/render/backend/jobs/updateboundingvolumejob.cpp
new file mode 100644
index 000000000..0d5752ff1
--- /dev/null
+++ b/src/render/backend/jobs/updateboundingvolumejob.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "updateboundingvolumejob.h"
+
+#include <rendernode.h>
+#include <sphere.h>
+
+#include <QDebug>
+#include <QElapsedTimer>
+#include <QStack>
+#include <QThread>
+
+static void expandWorldBoundingVolume(Qt3D::Render::RenderNode *node)
+{
+ Qt3D::Render::RenderNode *currentNode = node;
+ QStack<int> childIndexStack;
+ forever {
+ // Find left most leaf node of currentNode
+ while (!currentNode->m_children.isEmpty()) {
+ childIndexStack.push(1);
+ currentNode = node->m_children.first();
+ }
+
+ if (!currentNode->m_parent)
+ return;
+
+ // Initialize parent bounding volume to be equal to that of the first child
+ Qt3D::Render::RenderNode *parentNode = currentNode->m_parent;
+ Qt3D::Sphere *parentBoundingVolume = parentNode->m_worldBoundingVolume;
+ *(parentBoundingVolume) = *(currentNode->m_worldBoundingVolume);
+
+ // Expand the parent bounding volume by each of remaining the siblings
+ const int siblingCount = parentNode->m_children.count();
+ for (int i = 1; i < siblingCount; ++i) {
+ Qt3D::Sphere *siblingBoundingVolume = parentNode->m_children.at(i)->m_worldBoundingVolume;
+ parentBoundingVolume->expandToContain(*siblingBoundingVolume);
+ }
+
+ // Move to parent's next sibling
+ childIndexStack.pop();
+ const int nextSiblingIndex = childIndexStack.top()++;
+ currentNode = parentNode->m_parent->m_children.at(nextSiblingIndex);
+ }
+}
+
+namespace Qt3D {
+namespace Render {
+
+UpdateBoundingVolumeJob::UpdateBoundingVolumeJob(RenderNode *node)
+ : m_node(node)
+{
+}
+
+void UpdateBoundingVolumeJob::run()
+{
+ // Expand the bounding volumes of each node that has children by the
+ // bounding volumes of the children
+
+ // TODO: Implement this using a parallel_for
+ qDebug() << "Entering" << Q_FUNC_INFO << QThread::currentThread();
+ expandWorldBoundingVolume(m_node);
+ qDebug() << "Exiting" << Q_FUNC_INFO << QThread::currentThread();
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/jobs/updateboundingvolumejob.h b/src/render/backend/jobs/updateboundingvolumejob.h
new file mode 100644
index 000000000..81353a6c0
--- /dev/null
+++ b/src/render/backend/jobs/updateboundingvolumejob.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_UPDATEBOUNDINGVOLUMEJOB_H
+#define QT3D_RENDER_UPDATEBOUNDINGVOLUMEJOB_H
+
+#include <qjob.h>
+
+#include <QSharedPointer>
+
+namespace Qt3D {
+namespace Render {
+
+class RenderNode;
+
+class UpdateBoundingVolumeJob : public Qt3D::QJob
+{
+public:
+ explicit UpdateBoundingVolumeJob(RenderNode *m_node);
+
+protected:
+ void run() Q_DECL_OVERRIDE;
+
+private:
+ RenderNode *m_node;
+};
+
+typedef QSharedPointer<UpdateBoundingVolumeJob> UpdateBoundingVolumeJobPtr;
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_UPDATEBOUNDINGVOLUMEJOB_H
diff --git a/src/render/backend/jobs/updateworldtransformjob.cpp b/src/render/backend/jobs/updateworldtransformjob.cpp
new file mode 100644
index 000000000..04f09f9a0
--- /dev/null
+++ b/src/render/backend/jobs/updateworldtransformjob.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "updateworldtransformjob.h"
+
+#include <renderer.h>
+#include <rendernode.h>
+#include <sphere.h>
+
+#include <QDebug>
+#include <QThread>
+
+static void updateWorldTransformAndBounds(Qt3D::Render::RenderNode *node)
+{
+ QMatrix4x4 parentTransform;
+ if (node->m_parent)
+ parentTransform = *(node->m_parent->m_worldTransform);
+
+ *(node->m_worldTransform) = parentTransform * *(node->m_localTransform);
+ *(node->m_worldBoundingVolume) = node->m_localBoundingVolume->transformed(*(node->m_worldTransform));
+
+ Q_FOREACH (Qt3D::Render::RenderNode *child, node->m_children)
+ updateWorldTransformAndBounds(child);
+}
+
+namespace Qt3D {
+namespace Render {
+
+UpdateWorldTransformJob::UpdateWorldTransformJob(RenderNode *node)
+ : Qt3D::QJob()
+ , m_node(node)
+{
+}
+
+void UpdateWorldTransformJob::run()
+{
+ // Iterate over each level of hierarchy in our scene
+ // and update each node's world transform from its
+ // local transform and its parent's world transform
+
+ // TODO: Parallelise this on each level using a parallel_for
+ // implementation.
+
+ qDebug() << "Entering" << Q_FUNC_INFO << QThread::currentThread();
+ updateWorldTransformAndBounds(m_node);
+ qDebug() << "Exiting" << Q_FUNC_INFO << QThread::currentThread();
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/jobs/updateworldtransformjob.h b/src/render/backend/jobs/updateworldtransformjob.h
new file mode 100644
index 000000000..64117e893
--- /dev/null
+++ b/src/render/backend/jobs/updateworldtransformjob.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_UPDATEWORLDTRANSFORMJOB_H
+#define QT3D_RENDER_UPDATEWORLDTRANSFORMJOB_H
+
+#include <qjob.h>
+
+#include <QSharedPointer>
+
+namespace Qt3D {
+namespace Render {
+
+class RenderNode;
+
+class UpdateWorldTransformJob : public QJob
+{
+public:
+ explicit UpdateWorldTransformJob(RenderNode *node);
+
+protected:
+ void run() Q_DECL_OVERRIDE;
+
+private:
+ RenderNode *m_node;
+};
+
+typedef QSharedPointer<UpdateWorldTransformJob> UpdateWorldTransformJobPtr;
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_UPDATEWORLDTRANSFORMJOB_H
diff --git a/src/render/backend/meshmanager.cpp b/src/render/backend/meshmanager.cpp
new file mode 100644
index 000000000..8c8e2f741
--- /dev/null
+++ b/src/render/backend/meshmanager.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "meshmanager.h"
+
+namespace Qt3D {
+namespace Render {
+
+MeshManager::MeshManager(QObject *parent)
+ : QObject(parent)
+{
+}
+
+void MeshManager::addMesh(Qt3D::Mesh *frontEndMesh)
+{
+ MeshDataPtr meshData(new MeshData);
+ m_meshesByPeer.insert(frontEndMesh, meshData);
+
+ // TODO: Protect access to front end data
+ m_meshesBySource.insert(frontEndMesh->source(), meshData);
+
+ m_meshesPending.append(qMakePair(frontEndMesh->source(), meshData));
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/meshmanager.h b/src/render/backend/meshmanager.h
new file mode 100644
index 000000000..93379a18e
--- /dev/null
+++ b/src/render/backend/meshmanager.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_MESHMANAGER_H
+#define QT3D_RENDER_MESHMANAGER_H
+
+#include <QObject>
+
+#include <mesh.h>
+#include <meshdata.h>
+
+#include <QHash>
+#include <QPair>
+#include <QString>
+
+namespace Qt3D {
+namespace Render {
+
+class MeshManager : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MeshManager(QObject *parent = 0);
+
+ void addMesh(Qt3D::Mesh *frontEndMesh);
+
+ QList< QPair<QString, MeshDataPtr> > meshesPending() const { return m_meshesPending; }
+ void clearMeshesPending() { m_meshesPending.clear(); }
+
+private:
+ // TODO What unique id do we want to index by?
+ QHash<QString, Qt3D::MeshDataPtr> m_meshesBySource;
+ QHash<Qt3D::Mesh *, Qt3D::MeshDataPtr> m_meshesByPeer;
+
+ // List of meshes that we need to schedule jobs to load
+ // and calculate bounds for.
+ QList< QPair<QString,MeshDataPtr> > m_meshesPending;
+};
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_MESHMANAGER_H
diff --git a/src/render/backend/qgraphicscontext.cpp b/src/render/backend/qgraphicscontext.cpp
new file mode 100644
index 000000000..03469fe0c
--- /dev/null
+++ b/src/render/backend/qgraphicscontext.cpp
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgraphicscontext.h"
+
+#include "rendercamera.h"
+#include "rendershader.h"
+#include "rendermaterial.h"
+#include "rendertexture.h"
+
+#include <QDebug>
+#include <QOpenGLShaderProgram>
+#include <QOpenGLFunctions_3_3_Core>
+#include <QSurface>
+#include <QOpenGLTexture>
+
+namespace Qt3D
+{
+
+static QHash<unsigned int, QGraphicsContext*> static_contexts;
+
+unsigned int nextFreeContextId()
+{
+ for (unsigned int i=0; i < 0xffff; ++i) {
+ if (!static_contexts.contains(i))
+ return i;
+ }
+
+ qFatal("Couldn't find free context ID");
+ return 0;
+}
+
+QGraphicsContext::QGraphicsContext()
+ : m_initialized(false)
+ , m_id(nextFreeContextId())
+ , m_surface(0)
+ , m_funcs(0)
+ , m_activeShader(0)
+ , m_camera(0)
+ , m_material(0)
+ , m_stateSet(0)
+{
+ static_contexts[m_id] = this;
+}
+
+QGraphicsContext::~QGraphicsContext()
+{
+ releaseOpenGL();
+
+ Q_ASSERT(static_contexts[m_id] == this);
+ static_contexts.remove(m_id);
+}
+
+void QGraphicsContext::setSurface(QSurface *s)
+{
+ m_surface = s;
+}
+
+void QGraphicsContext::initialize()
+{
+ m_initialized = true;
+
+ Q_ASSERT(m_gl);
+
+ GLint numTexUnits;
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTexUnits);
+ qDebug() << "context supports" << numTexUnits << "texture units";
+
+ m_pinnedTextureUnits = QBitArray(numTexUnits);
+ m_activeTextures.resize(numTexUnits);
+ m_textureScopes.resize(numTexUnits);
+}
+
+void QGraphicsContext::beginDrawing()
+{
+ if (!m_gl || !m_surface) {
+ qWarning() << Q_FUNC_INFO << "no content or surface provided";
+ return;
+ }
+
+ bool ok = m_gl->makeCurrent(m_surface);
+ if (!ok) {
+ qWarning() << Q_FUNC_INFO << "make current failed";
+ }
+
+ GLint err = glGetError();
+ if (err != 0) {
+ qWarning() << Q_FUNC_INFO << "glGetError:" << err;
+ }
+
+ if (!m_initialized) {
+ initialize();
+ }
+
+ QVector4D cc = m_camera->clearColor();
+ glClearColor(cc[0], cc[1], cc[2], cc[3]);
+ glClear(m_camera->clearMask());
+
+ QRectF vp(m_camera->viewport());
+ // default to the entire surface
+ if (vp.isEmpty())
+ vp = QRectF(QPointF(0,0), m_surface->size());
+ glViewport(vp.x(), vp.y(), vp.width(), vp.height());
+
+ if (m_activeShader)
+ m_activeShader = NULL;
+}
+
+void QGraphicsContext::endDrawing()
+{
+ m_gl->doneCurrent();
+ m_gl->swapBuffers(m_surface);
+
+ decayTextureScores();
+}
+
+void QGraphicsContext::setCamera(RenderCamera *rcam)
+{
+ m_camera = rcam;
+}
+
+RenderCamera *QGraphicsContext::camera() const
+{
+ return m_camera;
+}
+
+
+QMatrix4x4 QGraphicsContext::projectionMatrix() const
+{
+ return m_camera->projection();
+}
+
+QMatrix4x4 QGraphicsContext::viewMatrix() const
+{
+ return m_camera->view();
+}
+
+void QGraphicsContext::releaseOpenGL()
+{
+ // m_shaderHash.clear
+ m_bufferHash.clear();
+}
+
+void QGraphicsContext::setOpenGLContext(QOpenGLContext* ctx)
+{
+ releaseOpenGL();
+ m_gl = ctx;
+ // m_gl->setParent(this);
+
+ m_funcs = m_gl->versionFunctions<QOpenGLFunctions_3_3_Core>();
+ if (m_funcs)
+ m_funcs->initializeOpenGLFunctions();
+}
+
+void QGraphicsContext::activateShader(RenderShader *shader)
+{
+ if (shader == NULL) {
+ m_activeShader = NULL;
+ m_material = NULL;
+ m_funcs->glUseProgram(0);
+ return;
+ }
+
+ if (!m_shaderHash.contains(shader)) {
+ QOpenGLShaderProgram* prog = shader->getOrCreateProgram();
+ Q_ASSERT(prog);
+ m_shaderHash[shader] = prog;
+ m_activeShader = NULL;
+ }
+
+ if (m_activeShader == shader) {
+ // no op
+ } else {
+ m_activeShader = shader;
+ QOpenGLShaderProgram* prog = m_shaderHash[shader];
+ prog->bind();
+
+ // ensure material uniforms are re-applied
+ m_material = NULL;
+ }
+}
+
+void QGraphicsContext::setActiveMaterial(RenderMaterial *rmat)
+{
+ if (m_material == rmat)
+ return;
+
+ deactivateTexturesWithScope(TextureScopeMaterial);
+ m_material = rmat;
+}
+
+void QGraphicsContext::setModelMatrix(const QMatrix4x4& modelMat)
+{
+ const QVector<int>& locs(m_activeShader->standardUniformLocations());
+ QOpenGLShaderProgram* prog = activeShader();
+
+ GLint progId;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &progId);
+ if (progId != (int) prog->programId()) {
+ qWarning() << "current program mismatch, very bad:" << progId << prog->programId();
+ return;
+ }
+
+ int sz = locs.size();
+ for (int i=0; i<sz; ++i) {
+ Parameter::StandardUniform su = static_cast<Parameter::StandardUniform>(i);
+ int loc = locs.at(i);
+ if (loc == -1)
+ continue;
+
+ switch (su) {
+ case Parameter::None: break;
+
+ case Parameter::ModelMatrix:
+ prog->setUniformValue(loc, modelMat); break;
+
+ case Parameter::ViewMatrix:
+ prog->setUniformValue(loc, viewMatrix()); break;
+
+ case Parameter::ProjectionMatrix:
+ prog->setUniformValue(loc, projectionMatrix()); break;
+
+ case Parameter::ModelView:
+ prog->setUniformValue(loc, viewMatrix() * modelMat); break;
+
+ case Parameter::ModelViewProjection:
+ prog->setUniformValue(loc, projectionMatrix() * viewMatrix() * modelMat); break;
+
+ case Parameter::ModelInverse:
+ prog->setUniformValue(loc, modelMat.inverted()); break;
+
+ case Parameter::ViewInverse:
+ prog->setUniformValue(loc, viewMatrix().inverted()); break;
+
+ case Parameter::ProjectionInverse:
+ prog->setUniformValue(loc, projectionMatrix().inverted()); break;
+
+ case Parameter::ModelViewInverse:
+ prog->setUniformValue(loc, (viewMatrix() * modelMat).inverted()); break;
+
+ case Parameter::ModelViewProjectionInverse:
+ prog->setUniformValue(loc, (projectionMatrix() * viewMatrix() * modelMat).inverted());
+ break;
+
+ case Parameter::ModelNormal:
+ prog->setUniformValue(loc, modelMat.normalMatrix());
+ break;
+
+ case Parameter::ModelViewNormal:
+ prog->setUniformValue(loc, (viewMatrix() * modelMat).normalMatrix());
+ break;
+ }
+
+ int err = glGetError();
+ if (err)
+ qWarning() << "GL error after setting matrix" << QString::number(err, 16) << i << loc;
+
+ } // of standard uniforms
+}
+
+int QGraphicsContext::activateTexture(TextureScope scope, RenderTexture *tex, int onUnit)
+{
+ if (onUnit == -1) {
+ onUnit = assignUnitForTexture(tex);
+
+ // check we didn't overflow the available units
+ if (onUnit == -1)
+ return onUnit;
+ }
+
+ // actually re-bind if required
+ if (m_activeTextures[onUnit] != tex) {
+ QOpenGLTexture* glTex = tex->getOrCreateGLTexture();
+ glTex->bind(onUnit);
+ }
+
+ int err = glGetError();
+ if (err)
+ qWarning() << "GL error after activating texture" << QString::number(err, 16)
+ << tex->textureId() << "on unit" << onUnit;
+
+ m_textureScores[tex] = 200;
+ m_pinnedTextureUnits[onUnit] = true;
+ m_textureScopes[onUnit] = scope;
+
+ return onUnit;
+}
+
+void QGraphicsContext::deactivateTexturesWithScope(TextureScope ts)
+{
+ for (int u=0; u<m_activeTextures.size(); ++u) {
+ if (!m_pinnedTextureUnits[u])
+ continue; // inactive, ignore
+
+ if (m_textureScopes[u] == ts) {
+ m_pinnedTextureUnits[u] = false;
+ }
+ } // of units iteration
+}
+
+void QGraphicsContext::deactivateTexture(RenderTexture* tex)
+{
+ for (int u=0; u<m_activeTextures.size(); ++u) {
+ if (m_activeTextures[u] == tex) {
+ Q_ASSERT(m_pinnedTextureUnits[u]);
+ m_pinnedTextureUnits[u] = false;
+ return;
+ }
+ } // of units iteration
+
+ qWarning() << Q_FUNC_INFO << "texture not active:" << tex;
+}
+
+void QGraphicsContext::setCurrentStateSet(DrawStateSet *ss)
+{
+ if (ss == m_stateSet)
+ return;
+
+ ss->apply(this);
+ m_stateSet = ss;
+}
+
+DrawStateSet *QGraphicsContext::currentStateSet() const
+{
+ return m_stateSet;
+}
+
+GLint QGraphicsContext::assignUnitForTexture(RenderTexture *tex)
+{
+ int lowestScoredUnit = -1;
+ int lowestScore = 0xfffffff;
+
+ for (int u=0; u<m_activeTextures.size(); ++u) {
+ if (m_activeTextures[u] == tex) {
+ return u;
+ }
+
+ if (!m_pinnedTextureUnits[u]) {
+ int score = m_textureScores[tex];
+ if (score < lowestScore) {
+ lowestScore = score;
+ lowestScoredUnit = u;
+ }
+ }
+ } // of units iteration
+
+ if (lowestScoredUnit == -1) {
+ qWarning() << Q_FUNC_INFO << "NO free texture units!";
+ return GL_INVALID_VALUE;
+ }
+
+ return lowestScoredUnit;
+}
+
+void QGraphicsContext::decayTextureScores()
+{
+ // FIXME - very inefficient use of QHash here, both for
+ // traversal coherency and subsequent modification.
+ Q_FOREACH (RenderTexture* t, m_textureScores.keys()) {
+ if ((m_textureScores[t]--) <= 0) {
+ qDebug() << "removing inactive texture" << t;
+ m_textureScores.remove((t));
+ }
+ }
+}
+
+QOpenGLShaderProgram* QGraphicsContext::activeShader()
+{
+ Q_ASSERT(m_activeShader);
+ return m_shaderHash[m_activeShader];
+}
+
+
+void QGraphicsContext::specifyAttribute(QString nm, AttributePtr attr)
+{
+ QOpenGLBuffer buf = glBufferFor(attr->buffer());
+ buf.bind();
+
+ QOpenGLShaderProgram* prog = activeShader();
+ int location = prog->attributeLocation(nm);
+ if (location < 0) {
+ qWarning() << "failed to resolve location for attribute:" << nm;
+ return;
+ }
+
+ prog->enableAttributeArray(location);
+ prog->setAttributeBuffer(location,
+ elementType(attr->type()),
+ attr->byteOffset(),
+ tupleSizeFromType(attr->type()),
+ attr->byteStride());
+
+ if (attr->divisor() != 0) {
+ // TODO - only if supported!
+ m_funcs->glVertexAttribDivisor(location, attr->divisor());
+ }
+
+ buf.release();
+}
+
+void QGraphicsContext::specifyIndices(AttributePtr attr)
+{
+ if (attr->buffer()->type() != QOpenGLBuffer::IndexBuffer) {
+ qWarning() << Q_FUNC_INFO << "provided buffer is not correct type";
+ return;
+ }
+
+ QOpenGLBuffer buf = glBufferFor(attr->buffer());
+ if (!buf.bind())
+ qWarning() << Q_FUNC_INFO << "binding index buffer failed";
+
+ // bind within the current VAO
+}
+
+QOpenGLBuffer QGraphicsContext::glBufferFor(BufferPtr buf)
+{
+ if (m_bufferHash.contains(buf))
+ return m_bufferHash.value(buf);
+
+ QOpenGLBuffer glbuf = buf->createGL();
+ m_bufferHash[buf] = glbuf;
+ buf->upload(glbuf);
+
+ return glbuf;
+}
+
+} // of namespace
+
diff --git a/src/render/backend/qgraphicscontext.h b/src/render/backend/qgraphicscontext.h
new file mode 100644
index 000000000..f79695d7b
--- /dev/null
+++ b/src/render/backend/qgraphicscontext.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSCONTEXT_H
+#define QGRAPHICSCONTEXT_H
+
+#include <QOpenGLContext>
+#include <QOpenGLBuffer>
+#include <QOpenGLVertexArrayObject>
+#include <QHash>
+#include <QMatrix4x4>
+#include <QBitArray>
+
+#include <rendercamera.h>
+#include <meshdata.h>
+
+class QOpenGLShaderProgram;
+class QOpenGLFunctions_3_3_Core;
+
+namespace Qt3D
+{
+
+class RenderShader;
+class RenderCamera;
+class RenderMaterial;
+class RenderTexture;
+class DrawStateSet;
+
+enum TextureScope
+{
+ TextureScopeMaterial = 0,
+ TextureScopeTechnique
+ // per-pass for deferred rendering?
+};
+
+class QGraphicsContext
+{
+public:
+ QGraphicsContext();
+ ~QGraphicsContext();
+
+ void setSurface(QSurface* s);
+
+ int id() const; // unique, small integer ID of this context
+
+ void beginDrawing();
+
+ void endDrawing();
+
+ void setCamera(RenderCamera* rcam);
+ RenderCamera* camera() const;
+
+ QMatrix4x4 projectionMatrix() const;
+ QMatrix4x4 viewMatrix() const;
+
+ /**
+ * @brief releaseGL - release all OpenGL objects associated with
+ * this context
+ */
+ void releaseOpenGL();
+ void setOpenGLContext(QOpenGLContext* ctx);
+ QOpenGLContext *openGLContext() { return m_gl; }
+
+ void activateShader(RenderShader* shader);
+
+ RenderMaterial* activeMaterial() const
+ { return m_material; }
+
+ void setActiveMaterial(RenderMaterial* rmat);
+
+ /**
+ * @brief activeShader
+ * @return
+ */
+ QOpenGLShaderProgram* activeShader();
+
+ void specifyAttribute(QString nm, AttributePtr attr);
+
+ void specifyIndices(AttributePtr attr);
+
+ /**
+ * @brief glBufferFor - given a client-side (CPU) buffer, provide the
+ * context-specific object. Initial call will create the buffer.
+ * @param buf
+ * @return
+ */
+ QOpenGLBuffer glBufferFor(BufferPtr buf);
+
+ void setModelMatrix(const QMatrix4x4 &modelMat);
+
+ /**
+ * @brief activateTexture - make a texture active on a hardware unit
+ * @param tex - the texture to activate
+ * @param onUnit - option, specify the explicit unit to activate on
+ * @return - the unit the texture was activated on
+ */
+ int activateTexture(TextureScope scope, RenderTexture* tex, int onUnit = -1);
+
+ void deactivateTexture(RenderTexture *tex);
+
+ void setCurrentStateSet(DrawStateSet* ss);
+ DrawStateSet* currentStateSet() const;
+private:
+ void initialize();
+
+ void decayTextureScores();
+
+ GLint assignUnitForTexture(RenderTexture* tex);
+ void deactivateTexturesWithScope(TextureScope ts);
+
+
+ bool m_initialized;
+ const unsigned int m_id;
+ QOpenGLContext* m_gl;
+ QSurface* m_surface;
+
+ QOpenGLFunctions_3_3_Core *m_funcs;
+ RenderShader* m_activeShader;
+ QHash<RenderShader*, QOpenGLShaderProgram*> m_shaderHash;
+ QHash<BufferPtr,QOpenGLBuffer> m_bufferHash;
+
+ // active textures, indexed by texture unit
+ QVector<RenderTexture*> m_activeTextures;
+ QBitArray m_pinnedTextureUnits;
+ QVector<TextureScope> m_textureScopes;
+
+ // recency score for all render-textures we've seen. Higher scores
+ // mean more recently used.
+ QHash<RenderTexture*, int> m_textureScores;
+
+ RenderCamera* m_camera;
+ RenderMaterial* m_material;
+
+ DrawStateSet* m_stateSet;
+};
+
+}
+
+#endif // QGRAPHICSCONTEXT_H
diff --git a/src/render/backend/quniformvalue.cpp b/src/render/backend/quniformvalue.cpp
new file mode 100644
index 000000000..8c88b62a6
--- /dev/null
+++ b/src/render/backend/quniformvalue.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quniformvalue.h"
+
+#include "qgraphicscontext.h"
+#include "rendertexture.h"
+
+#include <QOpenGLShaderProgram>
+#include <QDebug>
+#include <QColor>
+#include <QQuaternion>
+
+namespace Qt3D { namespace Render {
+
+QUniformValue::QUniformValue() :
+ m_type(Invalid),
+ m_count(-1),
+ m_tupleSize(0)
+{
+}
+
+QUniformValue::QUniformValue(Type type, QVariant value) :
+ m_type(type),
+ m_count(-1),
+ m_tupleSize(0)
+{
+ fromVariant(value);
+ Q_ASSERT((m_tupleSize >= 1) && (m_tupleSize <= 4));
+}
+
+QUniformValue::QUniformValue(const QVector4D &f) :
+ m_type(Float)
+{
+ m_var = QVariant(f);
+ QVector4D v(f); // need to make a local copy to take the address
+ setRawFromFloats(&v[0], 1, 4);
+}
+
+void QUniformValue::fromVariant(QVariant v)
+{
+ if (!v.isValid())
+ return;
+
+ if (m_var == v)
+ return;
+ m_var = v;
+
+ switch (m_type) {
+ case Int:
+ case UInt:
+ fromVariantToInt(v);
+ break;
+
+ case Float:
+ fromVariantToFloat(v);
+ break;
+
+ // doubles, if the extension is present
+
+ default:
+ qWarning() << Q_FUNC_INFO << "unsupported internal type" << m_type;
+ }
+}
+
+void QUniformValue::fromVariantToInt(QVariant v)
+{
+ switch (v.type()) {
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::Double: {
+ qint32 i = static_cast<qint32>(v.toInt());
+ setRawFromInts(&i, 1, 1);
+ break;
+ }
+
+ default:
+ qWarning() << Q_FUNC_INFO << "unsupported type" << v;
+ }
+}
+
+void QUniformValue::fromVariantToFloat(QVariant v)
+{
+ float* bufPtr = NULL;
+
+ switch (v.type()) {
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::Double: {
+ float f = static_cast<float>(v.toDouble());
+ setRawFromFloats(&f, 1, 1);
+ break;
+ }
+
+ case QVariant::Vector2D: {
+ QVector2D v2 = v.value<QVector2D>();
+ setRawFromFloats(&v2[0], 1, 2);
+ break;
+ }
+
+ case QVariant::Vector3D: {
+ QVector3D v3 = v.value<QVector3D>();
+ setRawFromFloats(&v3[0], 1, 3);
+ break;
+ }
+
+ case QVariant::Vector4D: {
+ QVector4D v4 = v.value<QVector4D>();
+ setRawFromFloats(&v4[0], 1, 4);
+ break;
+ }
+
+ case QVariant::Matrix4x4: {
+ QMatrix4x4 m = v.value<QMatrix4x4>();
+ setRawFromFloats(m.constData(), 4, 4);
+ break;
+ }
+
+ case QVariant::Color: {
+ qDebug() << "XXXXXXX setting from" << v;
+ m_bytes.resize(sizeof(float) * 4);
+ m_count = 1;
+ m_tupleSize = 4;
+ QColor c = v.value<QColor>();
+ *bufPtr++ = c.redF();
+ *bufPtr++ = c.greenF();
+ *bufPtr++ = c.blueF();
+ *bufPtr++ = c.alphaF();
+ break;
+ }
+
+ case QVariant::Quaternion: {
+ QVector4D qv = v.value<QQuaternion>().toVector4D();
+ setRawFromFloats(&qv[0], 1, 4);
+ break;
+ }
+
+ case QVariant::List: {
+ QVariantList vl = v.toList();
+
+ // implement me ...
+
+ break;
+ }
+
+ default:
+ qWarning() << Q_FUNC_INFO << "unsupported QVariant type";
+ }
+}
+
+void QUniformValue::setRawFromFloats(const float* ptr, unsigned int count, unsigned int tupleSize)
+{
+ m_bytes.resize(sizeof(float) * count * tupleSize);
+ memcpy(m_bytes.data(), ptr, m_bytes.size());
+ m_count = count;
+ m_tupleSize = tupleSize;
+}
+
+void QUniformValue::setRawFromInts(const qint32* ptr, unsigned int count, unsigned int tupleSize)
+{
+ m_bytes.resize(sizeof(qint32) * count * tupleSize);
+ memcpy(m_bytes.data(), ptr, m_bytes.size());
+ m_count = count;
+ m_tupleSize = tupleSize;
+}
+
+void QUniformValue::apply(QGraphicsContext *gc, int location, QString nm) const
+{
+ switch (m_type) {
+#if 0
+ case Int:
+ switch (m_tupleSize) {
+
+ }
+
+ gc->activeShader()->setUniformValueArray(location,
+ reinterpret_cast<const GLint*>(m_bytes.constData()),
+ m_count * m_tupleSize);
+ glUni
+
+ break;
+
+ case UInt:
+ gc->activeShader()->setUniformValueArray(location,
+ reinterpret_cast<const GLuint*>(m_bytes.constData()),
+ m_count * m_tupleSize);
+ break;
+#endif
+
+ case Float:
+ gc->activeShader()->setUniformValueArray(location,
+ reinterpret_cast<const GLfloat*>(m_bytes.constData()),
+ m_count, m_tupleSize);
+ break;
+
+ default:
+ qWarning() << Q_FUNC_INFO << "unsupported type:" << m_type;
+ }
+
+ int err = glGetError();
+ if (err) {
+ qWarning() << "error after setting uniform" << m_count << location << m_tupleSize << nm;
+ }
+}
+
+void QUniformValue::convertToBytes() const
+{
+ if (!m_bytes.isEmpty())
+ return; // use cahced conversion
+}
+
+void QUniformPack::setUniform(QString glslName, QUniformValue val)
+{
+ for (int u=0; u<m_uniforms.size(); ++u) {
+ if (m_uniforms[u].glslName != glslName) {
+ continue;
+ }
+
+ m_uniforms[u].uval = val;
+ return;
+ }
+
+ NamedUniform nu;
+ nu.glslName = glslName;
+ nu.uval = val;
+ m_uniforms.append(nu);
+}
+
+void QUniformPack::setTexture(QString glslName, RenderTexturePtr tex)
+{
+ for (int t=0; t<m_textures.size(); ++t) {
+ if (m_textures[t].glslName != glslName) {
+ continue;
+ }
+
+ m_textures[t].tex = tex;
+ return;
+ }
+
+ m_textures.append(NamedTexture(glslName, tex));
+}
+
+void QUniformPack::apply(QGraphicsContext *gc)
+{
+ for (int u=0; u<m_uniforms.size(); ++u) {
+ int loc = m_uniforms[u].location;
+ if (loc == -1) {
+ loc = gc->activeShader()->uniformLocation(m_uniforms[u].glslName);
+ m_uniforms[u].location = loc;
+ }
+
+ m_uniforms[u].uval.apply(gc, loc, m_uniforms[u].glslName);
+ } // of uniforms iteration
+
+ for (int t=0; t<m_textures.size(); ++t) {
+ int loc = m_textures[t].location;
+ if (loc == -1) {
+ loc = gc->activeShader()->uniformLocation(m_textures[t].glslName);
+ m_textures[t].location = loc;
+ }
+
+ int unit = gc->activateTexture(TextureScopeMaterial, m_textures[t].tex.data());
+ gc->activeShader()->setUniformValue(loc, unit);
+ } // of textures iteration
+}
+
+} } // of namespace Qt3D::Render
+
diff --git a/src/render/backend/quniformvalue.h b/src/render/backend/quniformvalue.h
new file mode 100644
index 000000000..eb642e950
--- /dev/null
+++ b/src/render/backend/quniformvalue.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUNIFORMVALUE_H
+#define QUNIFORMVALUE_H
+
+#include <QVariant>
+#include <QByteArray>
+#include <QVector>
+
+// for RenderTexturePtr
+#include <rendertextureprovider.h>
+
+namespace Qt3D {
+
+class QGraphicsContext;
+
+namespace Render {
+
+/**
+ * @brief The QUniformValue class - immutable storage of uniform value
+ * in the rendering backend.
+ */
+class QUniformValue
+{
+public:
+ enum Type {
+ Invalid = 0,
+ Int = 1,
+ UInt = 2,
+ Float = 3,
+ Double = 4,
+ Bool
+ };
+
+ QUniformValue();
+
+ QUniformValue(Type type, QVariant value);
+
+ // explicit construction from various types without going through
+ // QVariant boxing + unboxing. Add as needed if this proves useful
+ explicit QUniformValue(const QVector4D& foo);
+
+ void apply(QGraphicsContext* gc, int location, QString nm) const;
+
+private:
+ void convertToBytes() const;
+
+ Type m_type;
+ int m_count;
+ unsigned int m_tupleSize;
+
+ QVariant m_var;
+ // value as data suitable for passing to glUniformfv/iv
+ mutable QByteArray m_bytes;
+
+ void fromVariant(QVariant v);
+ void fromVariantToInt(QVariant v);
+ void fromVariantToFloat(QVariant v);
+
+ void setRawFromFloats(const float *ptr, unsigned int count, unsigned int tupleSize);
+ void setRawFromInts(const qint32 *ptr, unsigned int count, unsigned int tupleSize);
+};
+
+class QUniformPack
+{
+public:
+ void setUniform(QString glslName, QUniformValue val);
+
+ void setTexture(QString glslName, RenderTexturePtr tex);
+
+ void apply(QGraphicsContext* gc);
+private:
+
+ struct NamedUniform {
+ NamedUniform() : location(-1) { }
+
+ QString glslName;
+ int location;
+ QUniformValue uval;
+ };
+
+ QVector<NamedUniform> m_uniforms;
+
+ struct NamedTexture {
+ NamedTexture() : location(-1) {}
+
+ NamedTexture(QString nm, RenderTexturePtr t) :
+ glslName(nm),
+ location(-1),
+ tex(t)
+ { }
+
+ QString glslName;
+ int location;
+ RenderTexturePtr tex;
+ };
+
+ QVector<NamedTexture> m_textures;
+};
+
+}} // of namespace Qt3D::Render
+
+#endif // QUNIFORMVALUE_H
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
new file mode 100644
index 000000000..468f03c9d
--- /dev/null
+++ b/src/render/backend/render-backend.pri
@@ -0,0 +1,52 @@
+INCLUDEPATH += $$PWD
+
+include("framegraph/framegraph.pri")
+include("jobs/jobs.pri")
+
+HEADERS += \
+ $$PWD/rendereraspect.h \
+ $$PWD/renderthread.h \
+ $$PWD/renderconfiguration.h \
+ $$PWD/renderdevice.h \
+ $$PWD/renderer.h \
+ $$PWD/rendermaterial.h \
+ $$PWD/drawable.h \
+ $$PWD/rendermesh.h \
+ $$PWD/qgraphicscontext.h \
+ $$PWD/renderbin.h \
+ $$PWD/rendershader.h \
+ $$PWD/rendertechnique.h \
+ $$PWD/rendercamera.h \
+ $$PWD/quniformvalue.h \
+ $$PWD/rendernode.h \
+ $$PWD/renderscenebuilder.h \
+ $$PWD/rendertexture.h \
+ $$PWD/rendertextureprovider.h \
+ $$PWD/meshmanager.h \
+ $$PWD/drawstate.h \
+ $$PWD/states/blendstate.h \
+ $$PWD/genericstate.h
+
+
+SOURCES += \
+ $$PWD/rendereraspect.cpp \
+ $$PWD/renderthread.cpp \
+ $$PWD/renderconfiguration.cpp \
+ $$PWD/renderdevice.cpp \
+ $$PWD/renderer.cpp \
+ $$PWD/rendermaterial.cpp \
+ $$PWD/drawable.cpp \
+ $$PWD/rendermesh.cpp \
+ $$PWD/qgraphicscontext.cpp \
+ $$PWD/renderbin.cpp \
+ $$PWD/rendershader.cpp \
+ $$PWD/rendertechnique.cpp \
+ $$PWD/rendercamera.cpp \
+ $$PWD/quniformvalue.cpp \
+ $$PWD/rendernode.cpp \
+ $$PWD/renderscenebuilder.cpp \
+ $$PWD/rendertexture.cpp \
+ $$PWD/rendertextureprovider.cpp \
+ $$PWD/meshmanager.cpp \
+ $$PWD/drawstate.cpp \
+ $$PWD/states/blendstate.cpp
diff --git a/src/render/backend/renderbin.cpp b/src/render/backend/renderbin.cpp
new file mode 100644
index 000000000..62adede68
--- /dev/null
+++ b/src/render/backend/renderbin.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderbin.h"
+
+#include "drawable.h"
+#include "qgraphicscontext.h"
+#include "rendershader.h"
+#include "drawstate.h"
+
+//#define QT3D_STATE_CHANGE_DEBUG
+
+namespace Qt3D
+{
+
+
+void OpaqueBin::sendDrawingCommands(QGraphicsContext *gc)
+{
+ int shaderChangeCount = 0,
+ stateSetChangeCount = 0,
+ batchSize = 0;
+ bool resetBatch = false;
+
+ RenderShader* sh = NULL;
+ DrawStateSet* ss = NULL;
+
+ foreach (Drawable* d, m_drawables) {
+ resetBatch = false;
+
+ if (sh != d->shader()) {
+ sh = d->shader();
+ gc->activateShader(sh);
+ ++shaderChangeCount;
+ #if defined(QT3D_STATE_CHANGE_DEBUG)
+ qDebug() << "did shader change to" << sh->name();
+ #endif
+ resetBatch = true;
+ }
+
+ if (ss != d->stateSet()) {
+ ss = d->stateSet();
+ gc->setCurrentStateSet(ss);
+ ++stateSetChangeCount;
+ #if defined(QT3D_STATE_CHANGE_DEBUG)
+ qDebug() << "did state change";
+ #endif
+ resetBatch = true;
+ }
+
+ if (resetBatch && (batchSize > 0)) {
+ #if defined(QT3D_STATE_CHANGE_DEBUG)
+ qDebug() << "previous batch was " << batchSize;
+ #endif
+ batchSize = 1;
+ } else {
+ ++batchSize;
+ }
+
+ d->sendDrawingCommands(gc);
+ }
+
+#if defined(QT3D_STATE_CHANGE_DEBUG)
+ qDebug() << "final batch:" << batchSize;
+#endif
+}
+
+void OpaqueBin::addDrawable(Drawable *dr)
+{
+ Q_CHECK_PTR(dr);
+ RenderShader* sh = dr->shader();
+ DrawStateSet* ss = dr->stateSet();
+
+ int shaderStartIndex = 0;
+ for (; shaderStartIndex <m_drawables.size(); ++ shaderStartIndex) {
+ if (m_drawables.at(shaderStartIndex)->shader() == sh) {
+ break;
+ }
+ }
+
+ if (shaderStartIndex >= m_drawables.size()) {
+ // no matching shader found, simply append
+ m_drawables.append(dr);
+ return;
+ }
+
+// find last drawable using the shader. Also check for a matching
+// DrawStateSet in case it exists (then we just insert beside)
+ int shaderEndIndex = shaderStartIndex;
+ QVector<DrawStateSet*> ssList;
+
+ for (; shaderEndIndex < m_drawables.size(); ++shaderEndIndex) {
+ if (m_drawables.at(shaderEndIndex)->shader() != sh)
+ break; // found first drawable with different shader
+
+ DrawStateSet* currentSS = m_drawables.at(shaderEndIndex)->stateSet();
+ // record each distinct state-set applicable to this shader.
+ if (ssList.empty() || ssList.back() != currentSS) {
+ ssList.append(currentSS);
+
+ // check cost delta is non-zero; if it is, the state-sets are
+ // equivalent and we can simply merge
+ if (ss->changeCost(currentSS) == 0) {
+ m_drawables.insert(shaderEndIndex, dr);
+ return;
+ }
+ }
+ } // of same-shader range-iteration
+
+ insertDrawableInRange(dr, shaderStartIndex, shaderEndIndex, ssList);
+}
+
+// select position in the (shaderStartIndex .. shaderEndIndex]
+// range based on lowest cost StateSet transition. We already know the state-sets
+// are distinct since we checked for changeCost() == 0 in the loop above
+
+void OpaqueBin::insertDrawableInRange(Drawable *dr,
+ int startIndex, int endIndex,
+ const QVector<DrawStateSet*> ssList)
+{
+ qDebug() << "inserting drawable with different state-set";
+
+// special case where there is only one existing state set
+ if (ssList.size() == 1) {
+ m_drawables.insert(endIndex, dr);
+ return;
+ }
+
+ DrawStateSet* ss = dr->stateSet();
+ DrawStateSet* prevSS = ssList.front();
+ // default to appending
+ int lowestCostIncrease = ss->changeCost(ssList.back());
+ DrawStateSet* insertBeforeSS = NULL;
+
+ // see if we can do better than appending
+ for (int i=1; i<ssList.size(); ++i) {
+ int oldCost = ssList.at(i)->changeCost(prevSS);
+ int newCost = ss->changeCost(prevSS) + ssList.at(i)->changeCost(ss);
+ int costIncrease = newCost - oldCost;
+
+ if (costIncrease < lowestCostIncrease) {
+ lowestCostIncrease = costIncrease;
+ insertBeforeSS = ssList.at(i);
+ }
+ } // of distinct state-sets iteration
+
+ if (insertBeforeSS) {
+ for (int i=startIndex; i<endIndex; ++i) {
+ if (m_drawables.at(i)->stateSet() == insertBeforeSS) {
+ m_drawables.insert(i, dr);
+ break;
+ }
+ }
+ } else {
+ // simply append
+ m_drawables.insert(endIndex, dr);
+ }
+}
+
+void OpaqueBin::removeDrawable(Drawable *dr)
+{
+ Q_CHECK_PTR(dr);
+ m_drawables.removeOne(dr);
+}
+
+
+} // of namespace
diff --git a/src/render/backend/renderbin.h b/src/render/backend/renderbin.h
new file mode 100644
index 000000000..b21c5adf0
--- /dev/null
+++ b/src/render/backend/renderbin.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERBIN_H
+#define RENDERBIN_H
+
+#include <QList>
+#include <QMap>
+
+namespace Qt3D
+{
+
+class Drawable;
+class QGraphicsContext;
+class RenderShader;
+class DrawStateSet;
+
+class RenderBin
+{
+public:
+
+ virtual void sendDrawingCommands(QGraphicsContext* gc) = 0;
+ virtual void addDrawable(Drawable* dr) = 0;
+ virtual void removeDrawable(Drawable* dr) = 0;
+
+private:
+
+};
+
+class OpaqueBin : public RenderBin
+{
+public:
+
+ virtual void sendDrawingCommands(QGraphicsContext* gc);
+
+ virtual void addDrawable(Drawable* dr);
+ virtual void removeDrawable(Drawable* dr);
+
+private:
+ QList<Drawable*> m_drawables;
+
+ void insertDrawableInRange(Drawable *dr,
+ int startIndex, int endIndex,
+ const QVector<DrawStateSet *> ssList);
+};
+
+class DepthSortedBin : public RenderBin
+{
+public:
+
+private:
+};
+
+} // of namespace
+
+#endif // RENDERBIN_H
diff --git a/src/render/backend/rendercamera.cpp b/src/render/backend/rendercamera.cpp
new file mode 100644
index 000000000..20126b9bc
--- /dev/null
+++ b/src/render/backend/rendercamera.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rendercamera.h"
+#include "rendereraspect.h"
+
+#include <camera.h>
+
+#include <entity.h>
+#include <qaspectmanager.h>
+
+#include <QOpenGLContext>
+
+namespace Qt3D
+{
+
+RenderCamera::RenderCamera(RendererAspect *rendererAspect)
+ : m_rendererAspect(rendererAspect)
+ , m_peer(0)
+{
+ m_clearColor = QVector4D(0.5, 0.5, 1.0, 1.0);
+}
+
+void RenderCamera::setPeer(Camera *peer)
+{
+ m_peer = peer;
+
+ // Register for changes
+ QChangeArbiter *arbiter = m_rendererAspect->aspectManager()->changeArbiter();
+ arbiter->registerObserver(this, m_peer, MaterialParameter);
+}
+
+void RenderCamera::sync()
+{
+ // TODO Move the view matrix out of Camera and instead
+ // use the Entity's transformation (and later the Transform component).
+ Entity* e = m_peer->parentNode()->asEntity();
+
+ // HACK - in absence of an update pass
+ e->update();
+
+ // transform from world -> eye, so invert
+ m_view = e->sceneMatrix().inverted();
+}
+
+unsigned int RenderCamera::clearMask() const
+{
+ return GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
+}
+
+void RenderCamera::setProjection(const QMatrix4x4 &projection)
+{
+ m_projection = projection;
+}
+
+QMatrix4x4 RenderCamera::projection() const
+{
+ return m_projection;
+}
+
+QMatrix4x4 RenderCamera::view() const
+{
+ return m_view;
+}
+
+void RenderCamera::sceneChangeEvent(const QSceneChangePtr &e)
+{
+ switch (e->m_type) {
+ case CameraProjectionMatrix: {
+ QScenePropertyChangePtr propertyChange = qSharedPointerCast<QScenePropertyChange>(e);
+ QVariant propertyValue = propertyChange->m_value;
+ QMatrix4x4 viewMatrix = propertyValue.value<QMatrix4x4>();
+ m_projection = viewMatrix;
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+} // of namespace
+
diff --git a/src/render/backend/rendercamera.h b/src/render/backend/rendercamera.h
new file mode 100644
index 000000000..937076597
--- /dev/null
+++ b/src/render/backend/rendercamera.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERCAMERA_H
+#define RENDERCAMERA_H
+
+#include <qchangearbiter.h>
+
+#include <QMatrix4x4>
+#include <QRectF>
+
+namespace Qt3D
+{
+
+class Camera;
+class RendererAspect;
+
+class RenderCamera : public QObserverInterface
+{
+public:
+ RenderCamera(RendererAspect *rendererAspect);
+
+ void setPeer(Camera *peer);
+
+ // manually sync state with the peer, for the moment
+ void sync();
+
+ QVector4D clearColor() const { return m_clearColor; }
+
+ unsigned int clearMask() const;
+
+ QRectF viewport() const { return m_viewport; }
+
+ void setProjection(const QMatrix4x4 &projection);
+ QMatrix4x4 projection() const;
+
+ QMatrix4x4 view() const;
+
+ void sceneChangeEvent(const QSceneChangePtr &e) Q_DECL_OVERRIDE;
+
+private:
+ RendererAspect *m_rendererAspect;
+ Camera *m_peer;
+
+ // clip plane data
+ // ? m_zNear, m_zFar;
+
+
+ QVector4D m_clearColor;
+
+ QMatrix4x4 m_projection;
+ QMatrix4x4 m_view;
+ QRectF m_viewport;
+};
+
+}
+
+#endif // RENDERCAMERA_H
diff --git a/src/render/backend/renderconfiguration.cpp b/src/render/backend/renderconfiguration.cpp
new file mode 100644
index 000000000..ae2437461
--- /dev/null
+++ b/src/render/backend/renderconfiguration.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderconfiguration.h"
+
+namespace Qt3D {
+namespace Render {
+
+RenderConfiguration::RenderConfiguration()
+{
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/renderconfiguration.h b/src/render/backend/renderconfiguration.h
new file mode 100644
index 000000000..76a47f760
--- /dev/null
+++ b/src/render/backend/renderconfiguration.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_RENDERCONFIGURATION_H
+#define QT3D_RENDER_RENDERCONFIGURATION_H
+
+namespace Qt3D {
+namespace Render {
+
+class RenderConfiguration
+{
+public:
+ RenderConfiguration();
+};
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_RENDERCONFIGURATION_H
diff --git a/src/render/backend/renderdevice.cpp b/src/render/backend/renderdevice.cpp
new file mode 100644
index 000000000..4648932e7
--- /dev/null
+++ b/src/render/backend/renderdevice.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderdevice.h"
+
+namespace Qt3D {
+namespace Render {
+
+RenderDevice::RenderDevice()
+{
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/renderdevice.h b/src/render/backend/renderdevice.h
new file mode 100644
index 000000000..c854eee29
--- /dev/null
+++ b/src/render/backend/renderdevice.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_RENDERDEVICE_H
+#define QT3D_RENDER_RENDERDEVICE_H
+
+namespace Qt3D {
+namespace Render {
+
+class RenderDevice
+{
+public:
+ RenderDevice();
+};
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_RENDERDEVICE_H
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
new file mode 100644
index 000000000..84ded8ebb
--- /dev/null
+++ b/src/render/backend/renderer.cpp
@@ -0,0 +1,524 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderer.h"
+
+#include <nodevisitor.h>
+#include <entity.h>
+#include <scene.h>
+
+#include "framegraph/framegraphnode.h"
+#include "framegraph/framegraphvisitor.h"
+
+#include <material.h>
+#include <mesh.h>
+#include <effect.h>
+#include <technique.h>
+#include <shaderprogram.h>
+#include <renderpass.h>
+#include <camera.h>
+#include <shape.h>
+
+#include <meshmanager.h>
+#include <rendermesh.h>
+#include <renderbin.h>
+#include <rendermaterial.h>
+#include <rendernode.h>
+#include <rendertechnique.h>
+#include <renderscenebuilder.h>
+#include <rendershader.h>
+#include <qgraphicscontext.h>
+#include <rendercamera.h>
+#include <rendertextureprovider.h>
+#include <drawstate.h>
+#include <states/blendstate.h>
+
+#include <QStack>
+#include <QDebug>
+#include <QSurface>
+
+namespace Qt3D {
+
+namespace {
+
+class TemporaryBackendBuilder : public NodeVisitor
+{
+public:
+ TemporaryBackendBuilder(Render::Renderer* r) :
+ m_renderer(r)
+ {
+
+ }
+
+protected:
+ virtual void visitEntity(Entity* ent)
+ {
+ ent->update();
+
+ bool haveMaterial = false;
+ QList<Material*> mats = ent->componentsOfType<Material>();
+ if (!mats.empty()) {
+ haveMaterial = true;
+ m_materialStack.push(mats.front());
+ }
+
+
+ foreach (Mesh* mesh, ent->componentsOfType<Mesh>()) {
+ Material* mat = m_materialStack.empty() ? NULL : m_materialStack.top();
+ m_renderer->buildMeshes(mesh, mat, ent->sceneMatrix());
+ }
+
+ foreach (Shape* shape, ent->componentsOfType<Shape>()) {
+ Material* mat = m_materialStack.empty() ? NULL : m_materialStack.top();
+ m_renderer->buildShape(shape, mat, ent->sceneMatrix());
+ }
+
+ foreach (Camera* cam, ent->componentsOfType<Camera>()) {
+ m_renderer->foundCamera(cam, ent->sceneMatrix());
+ }
+
+ NodeVisitor::visitEntity(ent);
+
+ if (haveMaterial)
+ m_materialStack.pop();
+ }
+
+private:
+ QStack<Material*> m_materialStack;
+ Render::Renderer* m_renderer;
+};
+
+} // anonymous namespace
+
+namespace Render {
+
+Renderer::Renderer()
+ : m_rendererAspect(0)
+ , m_frameGraphRoot(0)
+ , m_camera(0)
+ , m_renderCamera(0)
+ , m_meshManager(new MeshManager(this))
+{
+ m_temporaryAllBin = NULL;
+ m_graphicsContext = new QGraphicsContext;
+ m_graphicsContext->setOpenGLContext(new QOpenGLContext);
+
+ m_frameTimer = new QTimer(this);
+ connect(m_frameTimer, SIGNAL(timeout()), this, SLOT(onFrame()));
+ m_frameTimer->setInterval(16);
+
+ m_textureProvider = new RenderTextureProvider;
+
+ buildDefaultTechnique();
+ buildDefaultMaterial();
+}
+
+void Renderer::buildDefaultTechnique()
+{
+ m_defaultTechnique = new Technique;
+ m_defaultTechnique->setObjectName("default-technique");
+
+ ShaderProgram* defaultShader = new ShaderProgram;
+ defaultShader->setVertexSourceFile(":/shaders/diffuse.vert");
+ defaultShader->setFragmentSourceFile(":/shaders/diffuse.frag");
+ defaultShader->setObjectName("DefaultShader");
+
+ RenderPass* basicPass = new RenderPass;
+ basicPass->setShaderProgram(defaultShader);
+
+ DrawStateSet* ss = new DrawStateSet;
+ ss->addState(DepthTest::getOrCreate(GL_LESS));
+ ss->addState(CullFace::getOrCreate(GL_BACK));
+ basicPass->setStateSet(ss);
+
+ m_defaultTechnique->addPass(basicPass);
+
+ Parameter* vp = new Parameter(m_defaultTechnique, "position", GL_FLOAT_VEC3);
+ vp->setMeshAttributeName("position");
+ m_defaultTechnique->addParameter(vp);
+ basicPass->addAttributeBinding(vp, "vertexPosition");
+
+ Parameter* np = new Parameter(m_defaultTechnique, "normal", GL_FLOAT_VEC3);
+ np->setMeshAttributeName("normal");
+ m_defaultTechnique->addParameter(np);
+ basicPass->addAttributeBinding(np, "vertexNormal");
+
+// matrix uniforms from standard
+ Parameter* mvMat = new Parameter(m_defaultTechnique, "modelView", GL_FLOAT_MAT4);
+ mvMat->setStandardUniform(Parameter::ModelView);
+ m_defaultTechnique->addParameter(mvMat);
+ basicPass->addUniformBinding(mvMat, "modelViewMatrix");
+
+ Parameter* nMat = new Parameter(m_defaultTechnique, "normalMat", GL_FLOAT_MAT3);
+ nMat->setStandardUniform(Parameter::ModelViewNormal);
+ m_defaultTechnique->addParameter(nMat);
+ basicPass->addUniformBinding(nMat, "normalMatrix");
+
+ Parameter* mvpMat = new Parameter(m_defaultTechnique, "mvp", GL_FLOAT_MAT4);
+ mvpMat->setStandardUniform(Parameter::ModelViewProjection);
+ m_defaultTechnique->addParameter(mvpMat);
+ basicPass->addUniformBinding(mvpMat, "mvp");
+
+// diffuse lighting uniforms
+ Parameter* lightPos = new Parameter(m_defaultTechnique, "lightPos", GL_FLOAT_VEC4);
+ m_defaultTechnique->addParameter(lightPos);
+ basicPass->addUniformBinding(lightPos, "lightPosition");
+
+ Parameter* lightIntensity = new Parameter(m_defaultTechnique, "lightIntensity", GL_FLOAT_VEC3);
+ m_defaultTechnique->addParameter(lightIntensity);
+ basicPass->addUniformBinding(lightIntensity, "lightIntensity");
+
+ Parameter* kd = new Parameter(m_defaultTechnique, "kd", GL_FLOAT_VEC3);
+ m_defaultTechnique->addParameter(kd);
+ basicPass->addUniformBinding(kd, "kd");
+
+ Parameter* ka = new Parameter(m_defaultTechnique, "ka", GL_FLOAT_VEC3);
+ m_defaultTechnique->addParameter(ka);
+ basicPass->addUniformBinding(ka, "ka");
+}
+
+void Renderer::buildDefaultMaterial()
+{
+ m_defaultMaterial = new Material;
+ m_defaultMaterial->setObjectName("DefaultMaterial");
+ m_defaultMaterial->setParameter("lightPos", QVector4D(10.0f, 10.0f, 0.0f, 1.0f));
+ m_defaultMaterial->setParameter("lightIntensity", QVector3D(0.5f, 0.5f, 0.5f));
+ m_defaultMaterial->setParameter("ka", QVector3D(0.2f, 0.2f, 0.2f));
+ m_defaultMaterial->setParameter("kd", QVector3D(1.0f, 0.5f, 0.0f));
+
+ Effect* defEff = new Effect;
+ defEff->addTechnique(m_defaultTechnique);
+ m_defaultMaterial->setEffect(defEff);
+}
+
+Renderer::~Renderer()
+{
+ delete m_graphicsContext;
+ delete m_textureProvider;
+}
+
+void Renderer::initialize()
+{
+
+}
+
+void Renderer::setFrameGraphRoot(FrameGraphNode *fgRoot)
+{
+ qDebug() << Q_FUNC_INFO;
+ m_frameGraphRoot = fgRoot;
+}
+
+FrameGraphNode *Renderer::frameGraphRoot() const
+{
+ return m_frameGraphRoot;
+}
+
+void Renderer::setSceneObject(Qt3D::Node *obj)
+{
+ Scene* sc = Scene::findInTree(obj);
+ if (sc) {
+ setSceneGraphRoot(sc);
+ } else
+ qWarning() << Q_FUNC_INFO << "couldn't find Scene object";
+}
+
+void Renderer::onFrame()
+{
+ render();
+}
+
+void Renderer::setSceneGraphRoot(Node *sgRoot)
+{
+ Q_ASSERT(sgRoot);
+
+ // TODO: Unify this to one root node and scene builder
+ Scene *scene = Scene::findInTree(sgRoot);
+ if (scene) {
+ qDebug() << "building temporary backend";
+ m_sceneGraphRoot = scene;
+ TemporaryBackendBuilder tbb(this);
+ tbb.traverse(m_sceneGraphRoot);
+ qDebug() << "done building backend";
+
+ QMetaObject::invokeMethod(m_frameTimer, "start");
+ } else {
+ // Test new scene builder
+ m_sceneGraphRoot = sgRoot;
+
+ RenderSceneBuilder builder(this);
+ builder.traverse(m_sceneGraphRoot);
+ RenderNode *root = builder.rootNode();
+ if (!root)
+ qWarning() << "Failed to build render scene";
+ m_renderSceneRoot = root;
+
+ root->dump();
+
+ // Queue up jobs to do initial full updates of
+ // - Mesh loading + bounding volume calculation
+ // - Local bounding volumes
+ // - World transforms
+ // - World bounding volumes
+ }
+}
+
+Node *Renderer::sceneGraphRoot() const
+{
+ return m_sceneGraphRoot;
+}
+
+void Renderer::setCamera(Camera *cam)
+{
+ m_camera = cam;
+ m_renderCamera = new RenderCamera(m_rendererAspect);
+ m_renderCamera->setPeer(cam);
+ m_renderCamera->setProjection(cam->projectionMatrix());
+
+ m_graphicsContext->setCamera(m_renderCamera);
+}
+
+void Renderer::setSurface(QSurface* s)
+{
+ qDebug() << Q_FUNC_INFO;
+ m_graphicsContext->setSurface(s);
+
+ QSurfaceFormat sf = s->format();
+
+ QOpenGLContext* ctx = new QOpenGLContext;
+ ctx->setFormat(sf);
+ if (!ctx->create()) {
+ qWarning() << Q_FUNC_INFO << "OpenGL context creation failed";
+ }
+
+ m_graphicsContext->setOpenGLContext(ctx);
+}
+
+void Renderer::setDefaultTechnique(Technique *t)
+{
+ Effect* defEff = m_defaultMaterial->effect();
+ bool materialWasUsing = (defEff->techniques().front() ==
+ m_defaultTechnique);
+
+ m_defaultTechnique = t;
+ if (materialWasUsing) {
+ defEff->clearTechniques();
+ defEff->addTechnique(t);
+ }
+}
+
+void Renderer::setDefaultMaterial(Material *mat)
+{
+ m_defaultMaterial = mat;
+}
+
+void Renderer::render()
+{
+ // Traverse the framegraph
+ // FrameGraphVisitor visitor;
+ // visitor.traverse(m_frameGraphRoot, this);
+
+ // begin hack renderer
+
+ if (!m_renderCamera)
+ return;
+
+ m_renderCamera->sync();
+
+ m_graphicsContext->beginDrawing();
+
+ foreach (Drawable* dr, m_initList)
+ dr->initializeGL(m_graphicsContext);
+ m_initList.clear();
+
+ int err = glGetError();
+ if (err)
+ qWarning() << "GL error before submitting bins:" << err;
+
+ m_temporaryAllBin->sendDrawingCommands(m_graphicsContext);
+
+ m_graphicsContext->endDrawing();
+
+ // end hack renderer
+}
+
+void Renderer::doRender()
+{
+ // Render using current device state and renderer configuration
+ qDebug() << Q_FUNC_INFO;
+}
+
+RenderTechnique* Renderer::techniqueForMaterial(Material* mat)
+{
+ Effect* eff = mat->effect();
+ Technique *tech;
+ if (eff) {
+ Q_ASSERT(!eff->techniques().empty());
+
+ // FIXME - technique selection happens in here, now we know
+ // the renderer characteristics
+ tech = eff->techniques().front();
+ } else {
+ tech = m_defaultTechnique;
+ }
+
+ if (!m_techniqueHash.contains(tech)) {
+ RenderTechnique* rtech = createTechnique(tech);
+ m_techniqueHash[tech] = rtech;
+ }
+
+ return m_techniqueHash.value(tech);
+}
+
+RenderShader* Renderer::getOrCreateShader(ShaderProgram* sp)
+{
+ if (!m_shaderHash.contains(sp)) {
+ RenderShader* rs = new RenderShader(sp);
+ m_shaderHash[sp] = rs;
+ }
+
+ return m_shaderHash.value(sp);
+}
+
+RenderBin* Renderer::getOrCreateBinForPass(Technique* t, RenderPass* p)
+{
+ Q_UNUSED(t);
+ Q_UNUSED(p);
+
+ // TODO - select bins by priority
+
+ if (!m_temporaryAllBin)
+ m_temporaryAllBin = new OpaqueBin;
+
+ return m_temporaryAllBin;
+}
+
+RenderTechnique* Renderer::createTechnique(Technique* tech)
+{
+ RenderTechnique* rt = new RenderTechnique(tech);
+ for (unsigned int p=0; p<rt->passCount(); ++p) {
+ RenderPass* frontendPass = tech->renderPasses().at(p);
+ RenderShader* rshader = getOrCreateShader(frontendPass->shaderProgram());
+ rt->setShaderForPass(p, rshader);
+
+ RenderBin* bin = getOrCreateBinForPass(tech, frontendPass);
+ rt->setBinForPass(p, bin);
+ }
+
+ return rt;
+}
+
+RenderMaterial* Renderer::getOrCreateMaterial(Material* mat)
+{
+ if (!m_materialHash.contains(mat)) {
+ qDebug() << "creating render material for mat:" << mat->objectName();
+
+ RenderMaterial* rmat = new RenderMaterial(m_rendererAspect);
+ rmat->setPeer(mat);
+ rmat->setTextureProvider(m_textureProvider);
+ m_materialHash[mat] = rmat;
+
+ // specifying technique will make the material sync parameter
+ // state from its peeer material.
+ rmat->setTechnique(techniqueForMaterial(mat));
+ }
+
+ return m_materialHash.value(mat);
+}
+
+void Renderer::buildMeshes(Mesh* mesh, Material* mat, const QMatrix4x4& mm)
+{
+ if (mat == NULL) {
+ mat = m_defaultMaterial;
+ }
+
+ RenderMaterial* rmat = getOrCreateMaterial(mat);
+ RenderTechnique* t = rmat->technique();
+
+ for (unsigned int p=0; p<t->passCount(); ++p) {
+ RenderBin* bin = t->binForPass(p);
+
+ RenderMesh* rmesh = new RenderMesh(mesh);
+ rmesh->setData(mesh->data());
+ rmesh->setTechniqueAndPass(t, p);
+ rmesh->setModelMatrix(mm);
+ rmesh->setMaterial(rmat);
+
+ m_initList.push_back(rmesh);
+ bin->addDrawable(rmesh);
+
+ } // of technique pass iteration
+}
+
+void Renderer::buildShape(Shape* shape, Material* mat, const QMatrix4x4& mm)
+{
+ if (mat == NULL) {
+ mat = m_defaultMaterial;
+ }
+
+ MeshDataPtr shapeMeshData = shape->data();
+ RenderMaterial* rmat = getOrCreateMaterial(mat);
+ RenderTechnique* t = rmat->technique();
+
+ for (unsigned int p=0; p<t->passCount(); ++p) {
+ RenderBin* bin = t->binForPass(p);
+
+ RenderMesh* rmesh = new RenderMesh(NULL);
+ rmesh->setData(shapeMeshData);
+ rmesh->setTechniqueAndPass(t, p);
+ rmesh->setModelMatrix(mm);
+ rmesh->setMaterial(rmat);
+
+ m_initList.push_back(rmesh);
+ bin->addDrawable(rmesh);
+
+ } // of technique pass iteration
+}
+
+
+void Renderer::foundCamera(Camera *cam, const QMatrix4x4 &mm)
+{
+ Q_UNUSED(mm);
+ cam->setViewMatrix(mm.inverted());
+ setCamera(cam);
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/renderer.h b/src/render/backend/renderer.h
new file mode 100644
index 000000000..40bc3eefa
--- /dev/null
+++ b/src/render/backend/renderer.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_RENDERER_H
+#define QT3D_RENDER_RENDERER_H
+
+#include <technique.h>
+
+#include <QHash>
+#include <QMatrix4x4>
+#include <QObject>
+#include <QTimer>
+
+#include <QOpenGLShaderProgram>
+#include <QOpenGLVertexArrayObject>
+#include <QOpenGLBuffer>
+
+class QSurface;
+
+namespace Qt3D {
+
+class Camera;
+class Entity;
+class RenderBin;
+class Material;
+class RenderMaterial;
+class RenderTechnique;
+class ShaderProgram;
+class RenderShader;
+class Mesh;
+class RenderPass;
+class QGraphicsContext;
+class RenderCamera;
+class Drawable;
+class RenderTextureProvider;
+class Shape;
+class RendererAspect;
+
+namespace Render {
+
+class FrameGraphNode;
+class RenderNode;
+class MeshManager;
+
+class Renderer : public QObject
+{
+ Q_OBJECT
+public:
+ Renderer();
+ ~Renderer();
+
+ void setRendererAspect(RendererAspect *rendererAspect) { m_rendererAspect = rendererAspect; }
+ RendererAspect *rendererAspect() const { return m_rendererAspect; }
+
+ void setFrameGraphRoot(FrameGraphNode *fgRoot);
+ FrameGraphNode *frameGraphRoot() const;
+
+ void setSceneObject(Qt3D::Node *obj);
+ void setSceneGraphRoot(Qt3D::Node *sgRoot);
+ Qt3D::Node *sceneGraphRoot() const;
+
+ RenderNode *renderSceneRoot() const { return m_renderSceneRoot; }
+
+ void setCamera(Camera* cam);
+
+ void render();
+ void doRender();
+
+ MeshManager *meshManager() const { return m_meshManager; }
+
+ // temporary!
+
+ RenderTechnique* techniqueForMaterial(Material* mat);
+
+ void buildMeshes(Mesh *mesh, Material *mat, const QMatrix4x4& mm);
+ void buildShape(Shape *shape, Material *mat, const QMatrix4x4 &mm);
+
+ void foundCamera(Camera* cam, const QMatrix4x4& mm);
+
+ Q_INVOKABLE void setSurface(QSurface *s);
+
+ void setDefaultTechnique(Technique* t);
+ void setDefaultMaterial(Material* mat);
+
+protected:
+ Q_INVOKABLE void initialize();
+
+private slots:
+ void onFrame();
+
+private:
+ RendererAspect *m_rendererAspect;
+
+ // Frame graph root
+ FrameGraphNode *m_frameGraphRoot;
+
+ Qt3D::Node *m_sceneGraphRoot;
+ RenderNode *m_renderSceneRoot;
+
+ Camera *m_camera;
+ RenderCamera* m_renderCamera;
+
+ QHash<Material*, RenderMaterial*> m_materialHash;
+ QHash<Technique *, RenderTechnique*> m_techniqueHash;
+ QHash<ShaderProgram*, RenderShader*> m_shaderHash;
+
+ RenderBin *getOrCreateBinForPass(Technique *t, RenderPass *p);
+
+ RenderTechnique *createTechnique(Technique *tech);
+ RenderShader *getOrCreateShader(ShaderProgram *sp);
+ RenderMaterial *getOrCreateMaterial(Material *mat);
+
+ Material* m_defaultMaterial;
+ Technique* m_defaultTechnique;
+
+ QGraphicsContext* m_graphicsContext;
+ RenderBin* m_temporaryAllBin;
+ RenderTextureProvider* m_textureProvider;
+ MeshManager *m_meshManager;
+
+ QTimer* m_frameTimer;
+
+ /// list of drawables to be initialized next frame
+ QList<Drawable*> m_initList;
+
+ void buildDefaultMaterial();
+ void buildDefaultTechnique();
+};
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_RENDERER_H
diff --git a/src/render/backend/rendereraspect.cpp b/src/render/backend/rendereraspect.cpp
new file mode 100644
index 000000000..0d63a7c0f
--- /dev/null
+++ b/src/render/backend/rendereraspect.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rendereraspect.h"
+
+#include "meshmanager.h"
+#include "renderer.h"
+#include "renderthread.h"
+
+#include <jobs/loadmeshdatajob.h>
+#include <jobs/updateworldtransformjob.h>
+#include <jobs/updateboundingvolumejob.h>
+
+#include <node.h>
+
+#include <QDebug>
+#include <QThread>
+#include <QWindow>
+
+namespace Qt3D {
+
+RendererAspect::RendererAspect(QObject *parent)
+ : AbstractAspect(AbstractAspect::AspectRenderer, parent)
+ , m_renderThread(new RenderThread)
+{
+ qRegisterMetaType<QSurface*>("QSurface*");
+ qRegisterMetaType< QSharedPointer<QObject> >("QObjectPtr");
+ m_renderThread->waitForStart();
+ m_renderThread->renderer()->setRendererAspect(this);
+}
+
+void RendererAspect::setWindow(QWindow *window)
+{
+ Q_ASSERT(window);
+ QSurface* surface = window;
+
+ Render::Renderer *renderer = m_renderThread->renderer();
+ QMetaObject::invokeMethod(renderer, "setSurface", Q_ARG(QSurface*, surface));
+}
+
+QVector<QJobPtr> RendererAspect::jobsToExecute()
+{
+ // Create jobs that will get exectued by the threadpool
+ QVector<QJobPtr> jobs;
+
+// Render::UpdateWorldTransformJobPtr worldTransformJob(new Render::UpdateWorldTransformJob(m_renderThread->renderer()->renderSceneRoot()));
+// Render::UpdateBoundingVolumeJobPtr boundingVolumeJob(new Render::UpdateBoundingVolumeJob(m_renderThread->renderer()));
+
+// // We can only update bounding volumes once all world transforms are known
+// boundingVolumeJob->addDependency(worldTransformJob);
+
+// // Add all jobs to queue
+// jobs.append(worldTransformJob);
+// jobs.append(boundingVolumeJob);
+
+ // Create jobs to load in any meshes that are pending
+ QList< QPair<QString,MeshDataPtr> > meshes = m_renderThread->renderer()->meshManager()->meshesPending();
+ for (int i = 0; i < meshes.size(); ++i ) {
+ const QPair<QString, MeshDataPtr> &meshDataInfo = meshes.at(i);
+ Render::LoadMeshDataJobPtr loadMeshJob(new Render::LoadMeshDataJob(meshDataInfo.first, meshDataInfo.second));
+ jobs.append(loadMeshJob);
+ }
+ m_renderThread->renderer()->meshManager()->clearMeshesPending();
+
+ return jobs;
+}
+
+void RendererAspect::registerAspectHelper(Node *rootObject)
+{
+ Render::Renderer *renderer = m_renderThread->renderer();
+ renderer->setSceneGraphRoot(rootObject);
+}
+
+void RendererAspect::unregisterAspectHelper(Node *rootObject)
+{
+}
+
+void RendererAspect::initializeHelper(QAspectManager *aspectManager)
+{
+ Q_UNUSED(aspectManager);
+ Render::Renderer *renderer = m_renderThread->renderer();
+ QMetaObject::invokeMethod(renderer, "initialize");
+}
+
+void RendererAspect::cleanupHelper()
+{
+ Render::Renderer *renderer = m_renderThread->renderer();
+ //QMetaObject::invokeMethod(renderer, "cleanup");
+}
+
+}
diff --git a/src/render/backend/rendereraspect.h b/src/render/backend/rendereraspect.h
new file mode 100644
index 000000000..3fd04744f
--- /dev/null
+++ b/src/render/backend/rendereraspect.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERERASPECT_H
+#define RENDERERASPECT_H
+
+#include "abstractaspect.h"
+
+namespace Qt3D {
+class RenderThread;
+}
+
+class QWindow;
+
+namespace Qt3D {
+
+class RendererAspect : public AbstractAspect
+{
+ Q_OBJECT
+public:
+ explicit RendererAspect(QObject *parent = 0);
+
+ virtual void setWindow(QWindow *window);
+
+ QVector<QJobPtr> jobsToExecute() Q_DECL_OVERRIDE;
+
+protected:
+ void registerAspectHelper(Node *rootObject) Q_DECL_OVERRIDE;
+ void unregisterAspectHelper(Node *rootObject) Q_DECL_OVERRIDE;
+
+ void initializeHelper(QAspectManager *aspectManager);
+ void cleanupHelper();
+
+private:
+ RenderThread* m_renderThread;
+};
+
+}
+
+#endif // RENDERERASPECT_H
diff --git a/src/render/backend/rendermaterial.cpp b/src/render/backend/rendermaterial.cpp
new file mode 100644
index 000000000..b74bf5954
--- /dev/null
+++ b/src/render/backend/rendermaterial.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rendermaterial.h"
+
+#include "rendereraspect.h"
+#include "qgraphicscontext.h"
+#include "rendertechnique.h"
+#include "rendertextureprovider.h"
+
+#include <technique.h> // for Parameter
+#include <material.h>
+
+#include <qaspectmanager.h>
+
+#include <QOpenGLShaderProgram>
+
+namespace Qt3D
+{
+
+RenderMaterial::RenderMaterial(RendererAspect *rendererAspect)
+ : m_rendererAspect(rendererAspect)
+ , m_textureProvider(NULL)
+{
+}
+
+RenderMaterial::~RenderMaterial()
+{
+ qDeleteAll(m_packs);
+ m_packs.clear();
+}
+
+void RenderMaterial::setTextureProvider(RenderTextureProvider* rtp)
+{
+ m_textureProvider = rtp;
+}
+
+void RenderMaterial::setPeer(Material *mat)
+{
+ m_peer = mat;
+
+ // Register for changes
+ QChangeArbiter *arbiter = m_rendererAspect->aspectManager()->changeArbiter();
+ arbiter->registerObserver(this, m_peer, MaterialParameter);
+}
+
+void RenderMaterial::setEffectName(QString nm)
+{
+ Q_UNUSED(nm);
+}
+
+void RenderMaterial::setParameter(QString paramName, QVariant varVal)
+{
+ Parameter* param = m_technique->parameterByName(paramName);
+ if (!param) {
+ return;
+ }
+
+ if (param->isTextureType()) {
+ // handle samplers separately
+ return;
+ }
+
+ if (param->isStandardUniform()) {
+ qWarning() << Q_FUNC_INFO << "setting standard uniform explicit for" << paramName;
+ return;
+ }
+
+ Render::QUniformValue uval(param->uniformType(), varVal);
+
+ QStringList names(m_technique->glslNamesForUniformParameter(paramName));
+ Q_ASSERT(names.count() == (int) m_technique->passCount());
+
+ for (unsigned int p=0; p<m_technique->passCount(); ++p) {
+ if (names.at(p).isEmpty())
+ continue; // not set in this pass
+
+ m_packs.at(p)->setUniform(names.at(p), uval);
+ } // of pass iteration
+}
+
+void RenderMaterial::setTextureParameter(QString paramName, RenderTexturePtr tex)
+{
+ Q_ASSERT(tex);
+ Parameter* param = m_technique->parameterByName(paramName);
+ if (!param)
+ return;
+
+ Q_ASSERT(param->isTextureType());
+
+ QStringList names(m_technique->glslNamesForUniformParameter(paramName));
+ Q_ASSERT(names.count() == (int) m_technique->passCount());
+
+ for (unsigned int p=0; p<m_technique->passCount(); ++p) {
+ if (names.at(p).isEmpty())
+ continue; // not set in this pass
+
+ m_packs.at(p)->setTexture(names.at(p), tex);
+ } // of pass iteration
+}
+
+void RenderMaterial::syncParametersFromPeer()
+{
+ Q_ASSERT(m_peer);
+ foreach (QString nm, m_peer->parameterValues().keys()) {
+ QVariant val = m_peer->parameterValues().value(nm);
+ if (!val.isValid()) {
+ qWarning() << Q_FUNC_INFO << "bad value:" << val << "for parameter" << nm;
+ continue;
+ }
+ setParameter(nm, val);
+ }
+
+ // FIXME - should do this on demand, otherwise we're re-uploading
+ // for no good reason
+ foreach (QString nm, m_peer->textureValues().keys()) {
+ Texture* t = m_peer->textureValues().value(nm);
+ setTextureParameter(nm, m_textureProvider->get(t));
+ }
+}
+
+void RenderMaterial::setTechnique(RenderTechnique *rt)
+{
+ m_technique = rt;
+
+ // could re-use packs, but techniques don't change often
+ qDeleteAll(m_packs);
+ m_packs.clear();
+
+ // allocate pack per pass - or should we do this lazily?
+ for (unsigned int p=0; p<rt->passCount(); ++p)
+ m_packs.append(new Render::QUniformPack);
+
+ if (m_peer)
+ syncParametersFromPeer();
+}
+
+RenderTechnique *RenderMaterial::technique() const
+{
+ return m_technique;
+}
+
+void RenderMaterial::setUniformsForPass(unsigned int pass, QGraphicsContext *gc)
+{
+ Q_ASSERT((int) pass < m_packs.size());
+ m_packs.at(pass)->apply(gc);
+}
+
+void RenderMaterial::sceneChangeEvent(const QSceneChangePtr &e)
+{
+ switch (e->m_type) {
+ case MaterialParameter: {
+ QScenePropertyChangePtr propertyChange = qSharedPointerCast<QScenePropertyChange>(e);
+ QString propertyName = propertyChange->m_propertyName;
+ QVariant propertyValue = propertyChange->m_value;
+ setParameter(propertyName, propertyValue);
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+} // of namespace Qt3D
+
diff --git a/src/render/backend/rendermaterial.h b/src/render/backend/rendermaterial.h
new file mode 100644
index 000000000..d216bdec1
--- /dev/null
+++ b/src/render/backend/rendermaterial.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERMATERIAL_H
+#define RENDERMATERIAL_H
+
+#include <QVariant>
+
+#include <qchangearbiter.h>
+
+#include <quniformvalue.h>
+#include <rendertextureprovider.h>
+
+namespace Qt3D
+{
+
+class Material;
+class RenderTechnique;
+class QGraphicsContext;
+class RendererAspect;
+
+class RenderMaterial : public QObserverInterface
+{
+public:
+ RenderMaterial(RendererAspect *rendererAspect);
+ ~RenderMaterial();
+
+ void setPeer(Material* mat);
+
+ void setEffectName(QString nm);
+
+ void setParameter(QString paramName, QVariant value);
+
+ void setTextureParameter(QString paramName, RenderTexturePtr tex);
+
+ void syncParametersFromPeer();
+
+ /**
+ * @brief setTechnique - specify the effect technique to use for
+ * rendering this material.
+ * @param rt
+ */
+ void setTechnique(RenderTechnique* rt);
+ RenderTechnique* technique() const;
+
+ void setUniformsForPass(unsigned int pass, QGraphicsContext* gc);
+
+ void setTextureProvider(RenderTextureProvider *rtp);
+
+ void sceneChangeEvent(const QSceneChangePtr &e) Q_DECL_OVERRIDE;
+
+private:
+ RendererAspect *m_rendererAspect;
+ Material* m_peer;
+ QString m_effectName;
+ RenderTechnique* m_technique;
+ RenderTextureProvider* m_textureProvider;
+
+ QVector<Render::QUniformPack*> m_packs;
+};
+
+}
+
+#endif // RENDERMATERIAL_H
diff --git a/src/render/backend/rendermesh.cpp b/src/render/backend/rendermesh.cpp
new file mode 100644
index 000000000..b7e3252c6
--- /dev/null
+++ b/src/render/backend/rendermesh.cpp
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rendermesh.h"
+
+#include "rendertechnique.h"
+#include "rendermaterial.h"
+
+#include "qgraphicscontext.h"
+#include <meshdata.h>
+#include <technique.h>
+
+#include <QOpenGLContext>
+#include <QOpenGLFunctions_3_3_Core>
+#include <QOpenGLShaderProgram>
+
+namespace Qt3D {
+
+RenderMesh::RenderMesh(Mesh* peer)
+ : Drawable( ),
+ m_peer(peer),
+ m_technique(0),
+ m_pass(0),
+ m_material(0),
+ m_instanceCount( 0 ),
+ m_funcs(0)
+{
+}
+
+void RenderMesh::setData(MeshDataPtr mesh)
+{
+ m_meshData = mesh;
+ m_meshDirty = true;
+ // clear bounding box?
+}
+
+void RenderMesh::setTechniqueAndPass(RenderTechnique* tech, unsigned int pass)
+{
+ m_technique = tech;
+ m_pass = pass;
+}
+
+void RenderMesh::setMaterial(RenderMaterial *rmat)
+{
+ m_material = rmat;
+}
+
+void RenderMesh::setInstanceCount(unsigned int count)
+{
+ m_instanceCount = count;
+}
+
+void RenderMesh::setModelMatrix(const QMatrix4x4 &mm)
+{
+ m_modelMatrix = mm;
+}
+
+DrawStateSet *RenderMesh::stateSet()
+{
+ return m_technique->stateSetForPass(m_pass);
+}
+
+
+void RenderMesh::initializeGL(QGraphicsContext* gc)
+{
+ m_vao.create();
+ m_vao.bind();
+
+ gc->activateShader(m_technique->shaderForPass(m_pass));
+
+ foreach (QString nm, m_meshData->attributeNames()) {
+ AttributePtr attr(m_meshData->attributeByName(nm));
+ QString glsl = m_technique->glslNameForMeshAttribute(m_pass, nm);
+ if (glsl.isEmpty())
+ continue; // not used in this pass
+ gc->specifyAttribute(glsl, attr);
+ }
+
+ m_drawIndexed = (m_meshData->indexAttr() != NULL);
+ if (m_drawIndexed) {
+ gc->specifyIndices(m_meshData->indexAttr());
+ }
+
+ m_vao.release();
+
+ // TODO Be careful about where we do this OpenGL work
+ QOpenGLContext* ctx = QOpenGLContext::currentContext();
+ m_funcs = ctx->versionFunctions<QOpenGLFunctions_3_3_Core>();
+ if ( m_funcs )
+ m_funcs->initializeOpenGLFunctions();
+ else
+ qWarning() << Q_FUNC_INFO << "couldn't resolve 3.3 core functions";
+};
+
+void RenderMesh::releaseGL()
+{
+ m_vao.destroy();
+}
+
+void RenderMesh::sendDrawingCommands(QGraphicsContext* gc)
+{
+ if (gc->activeMaterial() != m_material) {
+ gc->setActiveMaterial(m_material);
+ m_material->setUniformsForPass(m_pass, gc);
+ }
+
+ gc->setModelMatrix(m_modelMatrix);
+
+ m_vao.bind();
+ GLint primType = m_meshData->primitiveType();
+ GLint primCount = m_meshData->primitiveCount();
+ GLint indexType = m_drawIndexed ? m_meshData->indexAttr()->type() : 0;
+
+ if (m_instanceCount > 0) {
+ if ( m_drawIndexed ) {
+ m_funcs->glDrawElementsInstanced(primType, primType, indexType, 0, m_instanceCount);
+ } else {
+ m_funcs->glDrawArraysInstanced(primType, 0, primCount, m_instanceCount);
+ }
+ } else {
+ if ( m_drawIndexed ) {
+ m_funcs->glDrawElements(primType, primCount, indexType,
+ reinterpret_cast<void*>(m_meshData->indexAttr()->byteOffset()));
+ } else {
+ m_funcs->glDrawArrays(primType, 0, primCount);
+ }
+ } // non-instanced drawing
+
+ int err = glGetError();
+ if (err)
+ qWarning() << "GL error after drawing mesh:" << QString::number(err, 16);
+
+
+ m_vao.release();
+}
+
+RenderShader *RenderMesh::shader()
+{
+ return m_technique->shaderForPass(m_pass);
+}
+
+AxisAlignedBoundingBox RenderMesh::boundingBox() const
+{
+ if (!m_meshData)
+ return AxisAlignedBoundingBox();
+
+ return m_meshData->boundingBox();
+}
+
+#if 0
+static bool areIndicesShort( const QVector<unsigned int>& indices )
+{
+ // optimization; check the last index first, since it is often
+ // (but not always) going to be the larger index values
+ if (indices.back() > 0xffff) {
+ return false;
+ }
+
+ for (int i=0; i<indices.size(); ++i) {
+ if (indices.at(i) > 0xffff) {
+ return false;
+ }
+ } // of indices iteration
+
+ return true;
+}
+
+void RenderMesh::setMeshData( DrawContext& dc )
+{
+ // Construct buffers for the vertices, normals, texCoord, tangents and indices
+ QVector<QVector3D> points = m_loader->vertices();
+ QVector<QVector3D> normals = m_loader->normals();
+ QVector<QVector2D> texCoords = m_loader->textureCoordinates();
+ QVector<QVector4D> tangents = m_loader->tangents();
+
+ int vertexCount = points.size();
+ QVector<unsigned int> elements = m_loader->indices();
+ m_drawCount = elements.size();
+ int faces = elements.size() / 3;
+
+ bool shortIndices = areIndicesShort(elements);
+
+ /** \todo Use QScopedPointers or try reinterpret_cast on the
+ * QVector<> objects.
+ */
+ float* v = new float[3 * vertexCount];
+ float* n = new float[3 * vertexCount];
+ float* tc = 0;
+ float* tang = 0;
+
+ if ( !texCoords.isEmpty() )
+ {
+ tc = new float[ 2 * vertexCount ];
+ if ( !tangents.isEmpty() )
+ tang = new float[ 4 * vertexCount ];
+ }
+
+ int idx = 0, tcIdx = 0, tangIdx = 0;
+ for ( int i = 0; i < vertexCount; ++i )
+ {
+ v[idx] = points[i].x();
+ v[idx+1] = points[i].y();
+ v[idx+2] = points[i].z();
+ n[idx] = normals[i].x();
+ n[idx+1] = normals[i].y();
+ n[idx+2] = normals[i].z();
+ idx += 3;
+ if ( tc != 0 )
+ {
+ tc[tcIdx] = texCoords[i].x();
+ tc[tcIdx+1] = texCoords[i].y();
+ tcIdx += 2;
+ }
+ if ( tang != 0 )
+ {
+ tang[tangIdx] = tangents[i].x();
+ tang[tangIdx+1] = tangents[i].y();
+ tang[tangIdx+2] = tangents[i].z();
+ tang[tangIdx+3] = tangents[i].w();
+ tangIdx += 4;
+ }
+ }
+
+ m_mode = GL_TRIANGLES;
+
+ // Create and populate the buffer objects
+ m_positionBuffer.create();
+ m_positionBuffer.setUsagePattern( QOpenGLBuffer::StaticDraw );
+ m_positionBuffer.bind();
+ m_positionBuffer.allocate( v, 3 * vertexCount * sizeof( float ) );
+
+ m_normalBuffer.create();
+ m_normalBuffer.setUsagePattern( QOpenGLBuffer::StaticDraw );
+ m_normalBuffer.bind();
+ m_normalBuffer.allocate( n, 3 * vertexCount * sizeof( float ) );
+
+ if ( tc )
+ {
+ m_textureCoordBuffer.create();
+ m_textureCoordBuffer.setUsagePattern( QOpenGLBuffer::StaticDraw );
+ m_textureCoordBuffer.bind();
+ m_textureCoordBuffer.allocate( tc, 2 * vertexCount * sizeof( float ) );
+ }
+
+ if ( tang )
+ {
+ m_tangentBuffer.create();
+ m_tangentBuffer.setUsagePattern( QOpenGLBuffer::StaticDraw );
+ m_tangentBuffer.bind();
+ m_tangentBuffer.allocate( tang, 4 * vertexCount * sizeof( float ) );
+ }
+
+ if ( shortIndices ) {
+ unsigned short* el = new unsigned short[elements.size()];
+ for ( int i = 0; i < elements.size(); ++i )
+ el[i] = static_cast<unsigned short>(elements[i]);
+
+ m_indexBuffer.create();
+ m_indexBuffer.setUsagePattern( QOpenGLBuffer::StaticDraw );
+ m_indexBuffer.bind();
+ m_indexBuffer.allocate( el, 3 * faces * sizeof( unsigned short ) );
+ m_indexType = GL_UNSIGNED_SHORT;
+ delete[] el;
+ } else {
+ unsigned int* el = new unsigned int[elements.size()];
+ for ( int i = 0; i < elements.size(); ++i )
+ el[i] = elements[i];
+
+ m_indexBuffer.create();
+ m_indexBuffer.setUsagePattern( QOpenGLBuffer::StaticDraw );
+ m_indexBuffer.bind();
+ m_indexBuffer.allocate( el, 3 * faces * sizeof( unsigned int ) );
+ m_indexType = GL_UNSIGNED_INT;
+
+ delete[] el;
+ }
+
+ // Calculate the bounding volume
+ // m_boundingVolume->update( points );
+
+ // Clean up
+ delete[] v;
+ delete[] n;
+ if ( tc != NULL )
+ delete[] tc;
+ if ( tang != NULL )
+ delete[] tang;
+
+ m_loader.reset();
+
+ setupVertexArrayObject( dc );
+}
+#endif
+
+}
diff --git a/src/render/backend/rendermesh.h b/src/render/backend/rendermesh.h
new file mode 100644
index 000000000..5f2c0cdf8
--- /dev/null
+++ b/src/render/backend/rendermesh.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERMESH_H
+#define RENDERMESH_H
+
+#include "drawable.h"
+
+#include <meshdata.h>
+#include <axisalignedboundingbox.h>
+
+#include <QOpenGLVertexArrayObject>
+#include <QMatrix4x4>
+
+class QOpenGLFunctions_3_3_Core;
+
+namespace Qt3D {
+
+class Mesh;
+class RenderNode;
+class RenderPass;
+class RenderMaterial;
+class RenderTechnique;
+
+class RenderMesh : public Drawable
+{
+public:
+ explicit RenderMesh(Mesh* peer);
+
+ void setPeer(Mesh* peer);
+
+ void setData(MeshDataPtr mesh);
+
+ void setTechniqueAndPass(RenderTechnique* tech, unsigned int pass);
+
+ void setMaterial(RenderMaterial* rmat);
+
+ void setInstanceCount(unsigned int count);
+
+ void setModelMatrix(const QMatrix4x4& mm);
+
+ virtual DrawStateSet* stateSet();
+
+ /**
+ * @brief mapAttributeNames - resolve mapping of mesh-data attribute
+ * names to parameters.
+ * @param t
+ */
+ void mapAttributeNames();
+
+ virtual void initializeGL(QGraphicsContext* dc);
+
+ virtual void releaseGL();
+
+protected:
+ virtual void sendDrawingCommands( QGraphicsContext* dc );
+
+ virtual RenderShader* shader();
+
+ virtual AxisAlignedBoundingBox boundingBox() const;
+
+private:
+
+
+ Mesh* m_peer;
+
+ MeshDataPtr m_meshData;
+
+ RenderTechnique* m_technique;
+ unsigned int m_pass;
+
+ RenderMaterial* m_material;
+
+ bool m_drawIndexed;
+ bool m_meshDirty;
+ unsigned int m_instanceCount;
+
+ QOpenGLVertexArrayObject m_vao;
+
+ QOpenGLFunctions_3_3_Core *m_funcs;
+
+ QMatrix4x4 m_modelMatrix;
+};
+
+}
+
+#endif // RENDERMESH_H
diff --git a/src/render/backend/rendernode.cpp b/src/render/backend/rendernode.cpp
new file mode 100644
index 000000000..d9feb14f0
--- /dev/null
+++ b/src/render/backend/rendernode.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rendernode.h"
+#include "rendereraspect.h"
+
+#include <transform.h>
+
+#include <qaspectmanager.h>
+#include <sphere.h>
+#include <entity.h>
+
+#include <QMatrix4x4>
+#include <QString>
+#include <QDebug>
+
+namespace Qt3D {
+namespace Render {
+
+// TODO: Create custom allocators for each of the matrices and
+// bounding volumes to that they end up in contiguous arrays.
+
+RenderNode::RenderNode(RendererAspect *rendererAspect, RenderNode *parent)
+ : m_rendererAspect(rendererAspect)
+ , m_parent(parent)
+ , m_localTransform(new QMatrix4x4)
+ , m_worldTransform(new QMatrix4x4)
+ , m_localBoundingVolume(new Qt3D::Sphere)
+ , m_worldBoundingVolume(new Qt3D::Sphere)
+ , m_frontEndPeer(0)
+{
+ if (parent)
+ parent->m_children.append(this);
+}
+
+void RenderNode::setPeer(Transform *transform)
+{
+ m_peer = transform;
+
+ // Register for changes
+ QChangeArbiter *arbiter = m_rendererAspect->aspectManager()->changeArbiter();
+ arbiter->registerObserver(this, m_peer, LocalTransform);
+}
+
+void RenderNode::sceneChangeEvent(const QSceneChangePtr &e)
+{
+ switch (e->m_type) {
+ case LocalTransform: {
+ QScenePropertyChangePtr propertyChange = qSharedPointerCast<QScenePropertyChange>(e);
+ *m_localTransform = propertyChange->m_value.value<QMatrix4x4>();
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+void RenderNode::dump() const
+{
+ static int depth = 0;
+ QString indent(2 * depth++, QChar::fromLatin1(' '));
+ qDebug() << indent + m_frontEndPeer->objectName();
+ foreach (const RenderNode *child, m_children)
+ child->dump();
+ --depth;
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/rendernode.h b/src/render/backend/rendernode.h
new file mode 100644
index 000000000..480c8b3ed
--- /dev/null
+++ b/src/render/backend/rendernode.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_RENDERNODE_H
+#define QT3D_RENDER_RENDERNODE_H
+
+#include <qchangearbiter.h>
+
+#include <QVector>
+
+class QMatrix4x4;
+
+namespace Qt3D {
+
+class RendererAspect;
+class Sphere;
+class Node;
+class Transform;
+
+namespace Render {
+
+class RenderNode : public QObserverInterface
+{
+public:
+ explicit RenderNode(RendererAspect *rendererAspect, RenderNode *parent = 0);
+
+ void setPeer(Transform *transform);
+ void sceneChangeEvent(const QSceneChangePtr &e) Q_DECL_OVERRIDE;
+
+ void dump() const;
+
+//private:
+ RendererAspect *m_rendererAspect;
+ Transform *m_peer;
+ RenderNode *m_parent;
+ QVector<RenderNode *> m_children;
+ QMatrix4x4 *m_localTransform;
+ QMatrix4x4 *m_worldTransform;
+ Sphere *m_localBoundingVolume;
+ Sphere *m_worldBoundingVolume;
+
+ // TODO: Do we want to force this to be an Entity?
+ // That would mean forcing an Entity for the root on the main thread's scene
+ Node *m_frontEndPeer;
+
+ // TODO: Add pointer to Drawable or references to VBO's and other info needed to draw
+};
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_RENDERNODE_H
diff --git a/src/render/backend/renderscenebuilder.cpp b/src/render/backend/renderscenebuilder.cpp
new file mode 100644
index 000000000..9e861d65f
--- /dev/null
+++ b/src/render/backend/renderscenebuilder.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderscenebuilder.h"
+
+#include "meshmanager.h"
+#include "renderer.h"
+#include "rendernode.h"
+
+#include <camera.h>
+#include <material.h>
+#include <mesh.h>
+#include <transform.h>
+
+#include <entity.h>
+
+namespace Qt3D {
+namespace Render {
+
+RenderSceneBuilder::RenderSceneBuilder(Renderer *renderer)
+ : Qt3D::NodeVisitor()
+ , m_renderer(renderer)
+ , m_rootNode(0)
+{
+}
+
+void RenderSceneBuilder::visitNode(Qt3D::Node *node)
+{
+ if (!m_rootNode) {
+ m_rootNode = new RenderNode(m_renderer->rendererAspect());
+ m_rootNode->m_frontEndPeer = node;
+ m_nodeStack.push(m_rootNode);
+ }
+
+ Qt3D::NodeVisitor::visitNode(node);
+}
+
+void RenderSceneBuilder::visitEntity(Qt3D::Entity *entity)
+{
+ // Create a RenderNode corresponding to the Entity. Most data will
+ // be calculated later by jobs
+ RenderNode *renderNode = new RenderNode(m_renderer->rendererAspect(), m_nodeStack.top());
+ renderNode->m_frontEndPeer = entity;
+ *(renderNode->m_localTransform) = entity->matrix();
+ m_nodeStack.push(renderNode);
+
+ // Look for a transform component
+ QList<Transform *> transforms = entity->componentsOfType<Transform>();
+ if (!transforms.isEmpty())
+ renderNode->setPeer(transforms.first());
+
+// QList<Material *> materials = entity->componentsOfType<Material>();
+// Material *material = 0;
+// if (!materials.isEmpty())
+// material = materials.first();
+
+ // We'll update matrices in a job later. In fact should the matrix be decoupled from the mesh?
+ foreach (Mesh *mesh, entity->componentsOfType<Mesh>()) {
+ m_renderer->meshManager()->addMesh(mesh);
+ //m_renderer->buildMeshes(mesh, material, QMatrix4x4());
+ }
+
+ //foreach (Camera *camera, entity->componentsOfType<Camera>())
+ // m_renderer->foundCamera(camera, entity->sceneMatrix());
+
+ NodeVisitor::visitEntity(entity);
+
+ // Coming back up the tree
+ m_nodeStack.pop();
+}
+
+} // namespace Render
+} // namespace Qt3D
diff --git a/src/render/backend/renderscenebuilder.h b/src/render/backend/renderscenebuilder.h
new file mode 100644
index 000000000..2f3812f26
--- /dev/null
+++ b/src/render/backend/renderscenebuilder.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_RENDERSCENEBUILDER_H
+#define QT3D_RENDER_RENDERSCENEBUILDER_H
+
+#include <nodevisitor.h>
+
+#include <QStack>
+
+namespace Qt3D {
+namespace Render {
+
+class Renderer;
+class RenderNode;
+
+class RenderSceneBuilder : public Qt3D::NodeVisitor
+{
+public:
+ explicit RenderSceneBuilder(Renderer *renderer);
+
+ RenderNode *rootNode() const { return m_rootNode; }
+
+protected:
+ void visitNode(Qt3D::Node *node) Q_DECL_OVERRIDE;
+ void visitEntity(Qt3D::Entity *entity) Q_DECL_OVERRIDE;
+
+private:
+ Renderer *m_renderer;
+ RenderNode *m_rootNode;
+ QStack<RenderNode *> m_nodeStack;
+};
+
+} // namespace Render
+} // namespace Qt3D
+
+#endif // QT3D_RENDER_RENDERSCENEBUILDER_H
diff --git a/src/render/backend/rendershader.cpp b/src/render/backend/rendershader.cpp
new file mode 100644
index 000000000..243cf4ffa
--- /dev/null
+++ b/src/render/backend/rendershader.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rendershader.h"
+
+#include <QDebug>
+#include <QOpenGLContext>
+#include <QOpenGLShaderProgram>
+
+#include <shaderprogram.h>
+
+namespace Qt3D
+{
+
+RenderShader::RenderShader(ShaderProgram *peer) :
+ m_program(NULL),
+ m_peer(peer)
+{
+ Q_ASSERT(peer);
+}
+
+QOpenGLShaderProgram *RenderShader::getOrCreateProgram()
+{
+ if (!m_program) {
+ // waiting for shader source to be loaded
+ if (!m_peer->isLoaded()) {
+
+ // FIXME - should not be done in the backend!
+ m_peer->load();
+ //return NULL;
+ }
+
+ m_program = createProgram();
+ if (!m_program)
+ m_program = createDefaultProgram();
+ }
+
+ return m_program;
+}
+
+void RenderShader::setStandardUniform(Parameter::StandardUniform su, QString name)
+{
+ Q_ASSERT(su != Parameter::None);
+ Q_ASSERT(!name.isEmpty());
+ int index = static_cast<int>(su);
+ if (index >= m_standardUniformNames.size())
+ m_standardUniformNames.resize(index + 1);
+ m_standardUniformNames[index] = name;
+}
+
+QString RenderShader::name() const
+{
+ return m_peer->objectName();
+}
+
+QOpenGLShaderProgram* RenderShader::createProgram()
+{
+ Q_ASSERT(QOpenGLContext::currentContext());
+ // scoped pointer so early-returns delete automatically
+ QScopedPointer<QOpenGLShaderProgram> p(new QOpenGLShaderProgram);
+ bool ok = p->addShaderFromSourceCode(QOpenGLShader::Vertex,
+ m_peer->vertexSourceCode());
+ if (!ok) {
+ qWarning() << "bad vertex source:" << m_program->log();
+ return NULL;
+ }
+
+ ok = p->addShaderFromSourceCode(QOpenGLShader::Fragment,
+ m_peer->fragmentSourceCode());
+ if (!ok) {
+ qWarning() << "bad fragment source:" << m_program->log();
+ return NULL;
+ }
+
+ ok = p->link();
+ if (!ok) {
+ qWarning() << "program failed to link:" << m_program->log();
+ return NULL;
+ }
+
+ m_standardUniformLocations.resize(m_standardUniformNames.size());
+ for (int i=0; i<m_standardUniformNames.size(); ++i) {
+ QString n = m_standardUniformNames.at(i);
+ if (n.isEmpty()) {
+ m_standardUniformLocations[i] = -1;
+ continue;
+ }
+
+ m_standardUniformLocations[i] = p->uniformLocation(n);
+ // qDebug() << "resolved location" << m_standardUniformLocations[i] <<
+ // "for uniform" << n;
+ }
+
+ // take from scoped-pointer so it doesn't get deleted
+ return p.take();
+}
+
+QOpenGLShaderProgram* RenderShader::createDefaultProgram()
+{
+ QOpenGLShaderProgram* p = new QOpenGLShaderProgram;
+ p->addShaderFromSourceCode(QOpenGLShader::Vertex,
+ "");
+
+ p->addShaderFromSourceCode(QOpenGLShader::Fragment,
+ "");
+
+ p->link();
+
+ return p;
+}
+
+} // of namespace Qt3D
diff --git a/src/render/backend/rendershader.h b/src/render/backend/rendershader.h
new file mode 100644
index 000000000..0b326e02d
--- /dev/null
+++ b/src/render/backend/rendershader.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERSHADER_H
+#define RENDERSHADER_H
+
+#include <QVector>
+
+// for Parameter::StandardUniforms enum - maybe should move to
+// somewhere common to avoid this include?
+#include <technique.h>
+
+class QOpenGLShaderProgram;
+
+namespace Qt3D
+{
+
+class ShaderProgram;
+
+class RenderShader
+{
+public:
+ RenderShader(ShaderProgram* peer);
+
+ /**
+ * @brief getOrCreateProgram
+ * must be called with a valid, current QOpenGLContext
+ * @return
+ */
+ QOpenGLShaderProgram* getOrCreateProgram();
+
+ /**
+ * @brief setStandardUniform - set the program name of a uniform
+ * @param su - the standard uniform
+ * @param loc - the GLSL name corresponding to the uniform
+ */
+ void setStandardUniform(Parameter::StandardUniform su, QString name);
+
+ /**
+ * @brief standardUniformLocations - vecotr of uniform locations
+ * within the compiled program, corresponding to the standard uniforms
+ * [index the vector by the StandardUniform enum]
+ * @return
+ */
+ QVector<int> standardUniformLocations() const
+ {
+ return m_standardUniformLocations;
+ }
+
+ QString name() const;
+private:
+ QOpenGLShaderProgram* m_program;
+ ShaderProgram* m_peer;
+
+ QOpenGLShaderProgram *createProgram();
+ QOpenGLShaderProgram *createDefaultProgram();
+
+ QVector<QString> m_standardUniformNames;
+ QVector<int> m_standardUniformLocations;
+};
+
+}
+
+
+#endif // RENDERSHADER_H
diff --git a/src/render/backend/rendertechnique.cpp b/src/render/backend/rendertechnique.cpp
new file mode 100644
index 000000000..7bac88023
--- /dev/null
+++ b/src/render/backend/rendertechnique.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rendertechnique.h"
+#include "rendershader.h"
+
+#include <renderpass.h>
+#include <technique.h>
+
+#include <QDebug>
+
+namespace Qt3D
+{
+
+RenderTechnique::RenderTechnique(Technique* peer) :
+ m_peer(peer)
+{
+ m_passCount = peer->renderPasses().count();
+ m_passBin.resize(m_passCount);
+ m_passShader.resize(m_passCount);
+}
+
+unsigned int RenderTechnique::passCount() const
+{
+ return m_passCount;
+}
+
+void RenderTechnique::setShaderForPass(unsigned int passIndex, RenderShader *s)
+{
+ Q_ASSERT(passIndex < passCount());
+ m_passShader[passIndex] = s;
+
+ // bind standard uniform names
+
+ RenderPass* pass = m_peer->renderPasses().at(passIndex);
+ foreach (Parameter* p, m_peer->parameters()) {
+ if (!p->isStandardUniform())
+ continue;
+
+ QString glslName = pass->glslNameForParameter(p->name());
+ if (glslName.isEmpty())
+ continue;
+
+ s->setStandardUniform(p->standardUniform(), glslName);
+ } // of parameter iteration
+}
+
+RenderShader *RenderTechnique::shaderForPass(unsigned int pass)
+{
+ Q_ASSERT(pass < passCount());
+ return m_passShader.at(pass);
+}
+
+void RenderTechnique::setBinForPass(unsigned int pass, RenderBin *bin)
+{
+ Q_ASSERT(pass < passCount());
+ m_passBin[pass] = bin;
+}
+
+RenderBin *RenderTechnique::binForPass(unsigned int pass) const
+{
+ return m_passBin.at(pass);
+}
+
+DrawStateSet *RenderTechnique::stateSetForPass(unsigned int pass) const
+{
+ return m_peer->renderPasses().at(pass)->stateSet();
+}
+
+QString RenderTechnique::glslNameForMeshAttribute(unsigned int passIndex, QString meshAttributeName)
+{
+ // find the parameter
+ foreach (Parameter* p, m_peer->parameters()) {
+ if (p->meshAttributeName() != meshAttributeName) {
+ continue;
+ }
+
+ Q_ASSERT((int) passIndex < m_peer->renderPasses().count());
+ RenderPass* pass = m_peer->renderPasses().at(passIndex);
+
+ return pass->glslNameForParameter(p->name());
+ } // of parameter iteration
+
+ // mesh attribute is not referenced in this technique
+ return QString();
+}
+
+Parameter *RenderTechnique::parameterByName(QString name) const
+{
+ foreach (Parameter* p, m_peer->parameters()) {
+ if (p->name() == name)
+ return p;
+ }
+
+ qWarning() << Q_FUNC_INFO << "couldn't find parameter:" << name
+ << "in technique" << m_peer->objectName();
+ return NULL;
+}
+
+QStringList RenderTechnique::glslNamesForUniformParameter(QString pName) const
+{
+ QStringList result;
+ Parameter* param = parameterByName(pName);
+ if (!param)
+ return result;
+
+ for (unsigned int p=0; p<m_passCount;++p) {
+ RenderPass* pass = m_peer->renderPasses().at(p);
+ // will return an empty QString if the pass doesn't use the parameter,
+ // but that's what we want so no probem.
+ QString glslName = pass->glslNameForParameter(pName);
+ result.append(glslName);
+ }
+
+ return result;
+}
+
+} // of namespace Qt3D
diff --git a/src/render/backend/rendertechnique.h b/src/render/backend/rendertechnique.h
new file mode 100644
index 000000000..41aab29bb
--- /dev/null
+++ b/src/render/backend/rendertechnique.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERTECHNIQUE_H
+#define RENDERTECHNIQUE_H
+
+#include <QVector>
+#include <QStringList>
+
+namespace Qt3D
+{
+
+class Technique;
+class RenderShader;
+class RenderBin;
+class Parameter;
+class DrawStateSet;
+
+class RenderTechnique
+{
+public:
+ RenderTechnique(Technique* peer);
+
+ unsigned int passCount() const;
+
+ void setShaderForPass(unsigned int pass, RenderShader* s);
+ RenderShader* shaderForPass(unsigned int pass);
+
+ void setBinForPass(unsigned int pas, RenderBin* bin);
+ RenderBin* binForPass(unsigned int pass) const;
+
+ DrawStateSet* stateSetForPass(unsigned int pass) const;
+
+ QString glslNameForMeshAttribute(unsigned int pass, QString meshAttributeName);
+
+ QStringList glslNamesForUniformParameter(QString pName) const;
+
+ // FIXME using front-end classes here, not ideal
+ Parameter* parameterByName(QString name) const;
+private:
+ Technique* m_peer;
+ unsigned int m_passCount;
+
+ // really need more than just the shader here, i.e other
+ // technique state
+ QVector<RenderShader*> m_passShader;
+ QVector<RenderBin*> m_passBin;
+
+
+
+
+};
+
+} // of namespace Qgt3D
+
+#endif // RENDERTECHNIQUE_H
diff --git a/src/render/backend/rendertexture.cpp b/src/render/backend/rendertexture.cpp
new file mode 100644
index 000000000..dbb796669
--- /dev/null
+++ b/src/render/backend/rendertexture.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rendertexture.h"
+
+#include <QDebug>
+#include <QOpenGLTexture>
+#include <QOpenGLPixelTransferOptions>
+
+#include <texturedata.h>
+
+namespace Qt3D {
+
+RenderTexture::RenderTexture(Texture* peer) :
+ m_peer(peer),
+ m_gl(NULL)
+{
+}
+
+QOpenGLTexture *RenderTexture::getOrCreateGLTexture()
+{
+ if (m_gl)
+ return m_gl;
+
+ m_gl = buildGLTexture();
+
+ m_gl->allocateStorage();
+ if (!m_gl->isStorageAllocated()) {
+ qWarning() << Q_FUNC_INFO << "texture storage allocation failed";
+ return NULL;
+ }
+
+ foreach (TexImageDataPtr imgData, m_peer->imageData()) {
+ setToGLTexture(imgData);
+ } // of image data in texture iteration
+
+ if (m_peer->generateMipMaps()) {
+ m_gl->generateMipMaps();
+ }
+
+ int err = glGetError();
+ if (err)
+ qWarning() << Q_FUNC_INFO <<
+ "GL error after generating mip-maps" << QString::number(err, 16);
+
+
+ return m_gl;
+}
+
+QOpenGLTexture *RenderTexture::buildGLTexture()
+{
+ QOpenGLTexture* glTex = new QOpenGLTexture(m_peer->target());
+ glTex->setFormat(m_peer->format());
+ glTex->setSize(m_peer->width(),
+ m_peer->height(),
+ m_peer->depth());
+
+ if (!glTex->create()) {
+ qWarning() << Q_FUNC_INFO << "creating QOpenGLTexture failed";
+ return NULL;
+ }
+
+ glTex->setWrapMode(m_peer->wrapMode());
+ glTex->setMinMagFilters(m_peer->minificationFilter(),
+ m_peer->magnificationFilter());
+
+ // FIXME : make this conditional on Qt version
+ // work-around issue in QOpenGLTexture DSA emulaation which rasies
+ // an Invalid Enum error
+ glGetError();
+
+ return glTex;
+}
+
+void RenderTexture::setToGLTexture(TexImageDataPtr imgData)
+{
+ Q_ASSERT(m_gl && m_gl->isCreated() && m_gl->isStorageAllocated());
+ // ensure we don't accidently cause a detach / copy of the raw bytes
+ const QByteArray& bytes(imgData->data());
+ char* rawPtr = const_cast<char*>(bytes.constData());
+ if (imgData->isCompressed()) {
+ m_gl->setCompressedData(imgData->mipMapLevel(),
+ imgData->layer(),
+ imgData->cubeFace(),
+ bytes.size(),
+ rawPtr);
+ } else {
+ QOpenGLPixelTransferOptions uploadOptions;
+ uploadOptions.setAlignment(1);
+ m_gl->setData(imgData->mipMapLevel(),
+ imgData->layer(),
+ imgData->cubeFace(),
+ imgData->pixelFormat(),
+ imgData->pixelType(),
+ rawPtr,
+ &uploadOptions);
+ }
+
+ // FIXME : make this conditional on Qt version
+ // work-around issue in QOpenGLTexture DSA emulaation which rasies
+ // an Invalid Enum error
+ glGetError();
+}
+
+
+GLint RenderTexture::textureId()
+{
+ return getOrCreateGLTexture()->textureId();
+}
+
+} // namespace Qt3D
diff --git a/src/render/backend/rendertexture.h b/src/render/backend/rendertexture.h
new file mode 100644
index 000000000..ff418be0b
--- /dev/null
+++ b/src/render/backend/rendertexture.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDERTEXTURE_H
+#define QT3D_RENDERTEXTURE_H
+
+#include <QOpenGLContext>
+
+#include <texturedata.h>
+
+// forward decls
+class QOpenGLTexture;
+
+namespace Qt3D {
+
+class RenderTexture
+{
+public:
+ RenderTexture(Texture* peer);
+
+ QOpenGLTexture* getOrCreateGLTexture() ;
+
+ GLint textureId();
+private:
+ Texture* m_peer;
+ QOpenGLTexture* m_gl;
+
+ QOpenGLTexture *buildGLTexture();
+ void setToGLTexture(TexImageDataPtr imgData);
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_RENDERTEXTURE_H
diff --git a/src/render/backend/rendertextureprovider.cpp b/src/render/backend/rendertextureprovider.cpp
new file mode 100644
index 000000000..0727272f4
--- /dev/null
+++ b/src/render/backend/rendertextureprovider.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rendertextureprovider.h"
+
+#include "rendertexture.h"
+
+namespace Qt3D {
+
+RenderTextureProvider::RenderTextureProvider()
+{
+}
+
+RenderTexturePtr RenderTextureProvider::get(Texture *t)
+{
+ if (m_dict.contains(t))
+ return m_dict.value(t);
+
+ RenderTexturePtr rt(new RenderTexture(t));
+ m_dict[t] = rt;
+
+ return rt;
+}
+
+} // namespace Qt3D
diff --git a/src/render/backend/rendertextureprovider.h b/src/render/backend/rendertextureprovider.h
new file mode 100644
index 000000000..70536dcab
--- /dev/null
+++ b/src/render/backend/rendertextureprovider.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDERTEXTUREPROVIDER_H
+#define QT3D_RENDERTEXTUREPROVIDER_H
+
+#include <QSharedPointer>
+#include <QHash>
+
+namespace Qt3D {
+
+class Texture;
+
+class RenderTexture;
+typedef QSharedPointer<RenderTexture> RenderTexturePtr;
+
+class RenderTextureProvider
+{
+public:
+ RenderTextureProvider();
+
+ RenderTexturePtr get(Texture* t);
+private:
+ QHash<Texture*, RenderTexturePtr> m_dict;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_RENDERTEXTUREPROVIDER_H
diff --git a/src/render/backend/renderthread.cpp b/src/render/backend/renderthread.cpp
new file mode 100644
index 000000000..f679bc2f6
--- /dev/null
+++ b/src/render/backend/renderthread.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderthread.h"
+#include "renderer.h"
+
+#include <QDebug>
+#include <QEventLoop>
+#include <QTime>
+
+namespace Qt3D {
+
+RenderThread::RenderThread( QObject* parent )
+ : QThread( parent ),
+ m_renderer( 0 ),
+ m_eventHandler( 0 )
+{
+}
+
+void RenderThread::waitForStart( Priority priority )
+{
+ qDebug() << "Starting Render thread and then going to sleep until it is ready for us...";
+ m_mutex.lock();
+ start( priority );
+ m_waitCondition.wait( &m_mutex );
+ qDebug() << "Render thread is now ready & calling thread is now awake again";
+}
+
+void RenderThread::run()
+{
+ m_mutex.lock();
+
+// Create worker objects
+ m_renderer = new Render::Renderer;
+ //m_eventHandler = new RenderEventProcessor;
+
+ m_waitCondition.wakeOne();
+ m_mutex.unlock();
+
+ // Enter the render thread event loop
+ exec();
+
+ delete m_renderer;
+}
+
+}
diff --git a/src/render/backend/renderthread.h b/src/render/backend/renderthread.h
new file mode 100644
index 000000000..c1471921e
--- /dev/null
+++ b/src/render/backend/renderthread.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERTHREAD_H
+#define RENDERTHREAD_H
+
+#include <QThread>
+
+#include <QMutex>
+#include <QWaitCondition>
+
+namespace Qt3D {
+namespace Render {
+class Renderer;
+}
+
+class RenderEventProcessor;
+
+class RenderThread : public QThread
+{
+ Q_OBJECT
+public:
+ explicit RenderThread( QObject* parent = 0 );
+
+ void waitForStart( Priority priority = InheritPriority );
+
+ Render::Renderer* renderer() const { return m_renderer; }
+
+ RenderEventProcessor* eventHandler() const { return m_eventHandler; }
+protected:
+ void run();
+
+private:
+ QMutex m_mutex;
+ QWaitCondition m_waitCondition;
+ Render::Renderer* m_renderer;
+ RenderEventProcessor* m_eventHandler;
+};
+
+}
+
+#endif // RENDERTHREAD_H
diff --git a/src/render/backend/states/blendstate.cpp b/src/render/backend/states/blendstate.cpp
new file mode 100644
index 000000000..c15cc56b9
--- /dev/null
+++ b/src/render/backend/states/blendstate.cpp
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "blendstate.h"
+
+#include "qgraphicscontext.h"
+
+#include <QOpenGLFunctions_3_2_Core>
+
+namespace Qt3D {
+
+template <class State>
+State* getOrCreateImpl(const State& data)
+{
+ static QList<State*> static_instances;
+ foreach (State* ext, static_instances) {
+ if (ext->isEqual(data))
+ return ext;
+ }
+
+ State* result = new State(data);
+ static_instances.append(result);
+ return result;
+}
+
+void BlendState::apply(QGraphicsContext* gc) const
+{
+ Q_UNUSED(gc);
+ glEnable(GL_BLEND);
+ glBlendFunc( m_1, m_2 );
+}
+
+StateMaskSet BlendState::mask() const
+{
+ return BlendStateMask;
+}
+
+BlendState *BlendState::getOrCreate(GLenum src, GLenum dst)
+{
+ BlendState bs(src, dst);
+ return getOrCreateImpl(bs);
+}
+
+BlendState::BlendState(GLenum src, GLenum dst) :
+ GenericState2(src, dst)
+{
+}
+
+void BlendEquation::apply(QGraphicsContext *gc) const
+{
+ Q_UNUSED(gc);
+
+ if (!m_funcs) {
+ m_funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
+ m_funcs->initializeOpenGLFunctions();
+ }
+
+ m_funcs->glBlendEquation(m_1);
+}
+
+BlendEquation *BlendEquation::getOrCreate(GLenum func)
+{
+ return getOrCreateImpl(BlendEquation(func));
+}
+
+BlendEquation::BlendEquation(GLenum func) :
+ GenericState1(func),
+ m_funcs(0)
+{
+}
+
+
+void AlphaFunc::apply(QGraphicsContext* gc) const
+{
+ Q_UNUSED(gc);
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc( m_1, m_2 );
+}
+
+AlphaFunc *AlphaFunc::getOrCreate(GLenum func, GLclampf value)
+{
+ AlphaFunc af(func, value);
+ return getOrCreateImpl(af);
+}
+
+AlphaFunc::AlphaFunc(GLenum func, GLclampf value) :
+ GenericState2(func, value)
+{
+}
+
+void DepthTest::apply(QGraphicsContext *gc) const
+{
+ Q_UNUSED(gc);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc( m_1 );
+}
+
+DepthTest *DepthTest::getOrCreate(GLenum func)
+{
+ DepthTest dt(func);
+ return getOrCreateImpl(dt);
+}
+
+DepthTest::DepthTest(GLenum func) :
+ GenericState1(func)
+{
+}
+
+void CullFace::apply(QGraphicsContext *gc) const
+{
+ Q_UNUSED(gc);
+ glEnable(GL_CULL_FACE);
+ glCullFace( m_1 );
+}
+
+CullFace *CullFace::getOrCreate(GLenum func)
+{
+ return getOrCreateImpl(CullFace(func));
+}
+
+CullFace::CullFace(GLenum func) :
+ GenericState1(func)
+{
+}
+
+void FrontFace::apply(QGraphicsContext *gc) const
+{
+ Q_UNUSED(gc);
+ glFrontFace(m_1);
+}
+
+FrontFace *FrontFace::getOrCreate(GLenum func)
+{
+ return getOrCreateImpl(FrontFace(func));
+}
+
+FrontFace::FrontFace(GLenum func) :
+ GenericState1(func)
+{
+}
+
+void DepthMask::apply(QGraphicsContext *gc) const
+{
+ Q_UNUSED(gc)
+ glDepthMask(m_1);
+}
+
+DepthMask *DepthMask::getOrCreate(GLboolean flag)
+{
+ return getOrCreateImpl(DepthMask(flag));
+}
+
+DepthMask::DepthMask(GLboolean flag) :
+ GenericState1(flag)
+{
+}
+
+
+} // of namespace
diff --git a/src/render/backend/states/blendstate.h b/src/render/backend/states/blendstate.h
new file mode 100644
index 000000000..6a294010d
--- /dev/null
+++ b/src/render/backend/states/blendstate.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BLENDSTATE_H
+#define BLENDSTATE_H
+
+#include <drawstate.h>
+#include <genericstate.h>
+
+#include <QOpenGLContext>
+
+class QOpenGLFunctions_3_2_Core;
+
+namespace Qt3D {
+
+class BlendState : public GenericState2<BlendState, GLenum, GLenum>
+{
+public:
+ virtual void apply(QGraphicsContext* gc) const;
+ virtual StateMaskSet mask() const;
+
+ static BlendState* getOrCreate(GLenum src, GLenum dst);
+private:
+ BlendState(GLenum src, GLenum dst);
+};
+
+class BlendEquation : public GenericState1<BlendEquation, GLenum>
+{
+public:
+ virtual void apply(QGraphicsContext* gc) const;
+
+ virtual StateMaskSet mask() const
+ { return BlendStateMask; }
+
+ static BlendEquation* getOrCreate(GLenum func);
+
+private:
+ BlendEquation(GLenum func);
+ mutable QOpenGLFunctions_3_2_Core *m_funcs;
+};
+
+
+class AlphaFunc : public GenericState2<AlphaFunc, GLenum, GLclampf>
+{
+public:
+ virtual void apply(QGraphicsContext* gc) const;
+
+ virtual StateMaskSet mask() const
+ { return AlphaTestMask; }
+
+ static AlphaFunc* getOrCreate(GLenum func, GLclampf value);
+private:
+ AlphaFunc(GLenum func, GLclampf value);
+};
+
+class DepthTest : public GenericState1<DepthTest, GLenum>
+{
+public:
+ virtual void apply(QGraphicsContext* gc) const;
+
+ virtual StateMaskSet mask() const
+ { return DepthTestStateMask; }
+
+ static DepthTest* getOrCreate(GLenum func);
+
+private:
+ DepthTest(GLenum func);
+};
+
+class DepthMask : public GenericState1<DepthMask, GLboolean>
+{
+public:
+ virtual void apply(QGraphicsContext* gc) const;
+
+ virtual StateMaskSet mask() const
+ { return DepthWriteStateMask; }
+
+ static DepthMask* getOrCreate(GLboolean func);
+
+private:
+ DepthMask(GLboolean func);
+};
+
+class CullFace : public GenericState1<CullFace, GLenum>
+{
+public:
+ virtual void apply(QGraphicsContext* gc) const;
+
+ virtual StateMaskSet mask() const
+ { return CullFaceStateMask; }
+
+ static CullFace* getOrCreate(GLenum func);
+
+private:
+ CullFace(GLenum func);
+};
+
+class FrontFace : public GenericState1<FrontFace, GLenum>
+{
+public:
+ virtual void apply(QGraphicsContext* gc) const;
+
+ virtual StateMaskSet mask() const
+ { return FrontFaceStateMask; }
+
+ static FrontFace* getOrCreate(GLenum func);
+
+private:
+ FrontFace(GLenum func);
+};
+
+
+} // of namespace
+
+#endif // BLENDSTATE_H
diff --git a/src/render/frontend/camera.cpp b/src/render/frontend/camera.cpp
new file mode 100644
index 000000000..b408cae8f
--- /dev/null
+++ b/src/render/frontend/camera.cpp
@@ -0,0 +1,483 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "camera.h"
+#include "camera_p.h"
+
+namespace Qt3D {
+
+Camera::Camera(Node *parent)
+ : Component(parent)
+ , d_ptr(new CameraPrivate(this))
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+void Camera::setViewMatrix(const QMatrix4x4 &m)
+{
+ Q_D(Camera);
+
+ // derive the position and up vecotr
+
+ bool ok;
+ QMatrix4x4 iv = m.inverted(&ok);
+ if (!ok) {
+ qWarning() << Q_FUNC_INFO << "passed non-invertible matrix";
+ return;
+ }
+
+ // position in eye-coordinates is simple the origin
+ d->m_position = (iv * QVector4D(0,0,0,1)).toVector3D();
+
+ // up vector, w=0 (no translation), positive Y-axis
+ d->m_upVector = (iv * QVector4D(0,1,0,0)).toVector3D();
+
+ // look vector, w=0, positive Z-axis
+ d->m_cameraToCenter = (iv * QVector4D(0,0,1,0)).toVector3D();
+
+ d->m_viewMatrix = m;
+ d->m_syncNeeded = true;
+}
+
+void Camera::setProjectionType(ProjectionType projectionType)
+{
+ Q_D(Camera);
+ if (d->m_projectionType != projectionType) {
+ d->m_projectionType = projectionType;
+ emit projectionTypeChanged();
+ }
+}
+
+Camera::ProjectionType Camera::projectionType() const
+{
+ Q_D(const Camera);
+ return d->m_projectionType;
+}
+
+QVector3D Camera::position() const
+{
+ Q_D(const Camera);
+ return d->m_position;
+}
+
+void Camera::setPosition( const QVector3D& position )
+{
+ Q_D(Camera);
+ d->m_position = position;
+ d->m_cameraToCenter = d->m_viewCenter - position;
+ d->m_viewMatrixDirty = true;
+ d->m_syncNeeded = true;
+}
+
+void Camera::setUpVector( const QVector3D& upVector )
+{
+ Q_D(Camera);
+ d->m_upVector = upVector;
+ d->m_viewMatrixDirty = true;
+ d->m_syncNeeded = true;
+}
+
+QVector3D Camera::upVector() const
+{
+ Q_D(const Camera);
+ return d->m_upVector;
+}
+
+void Camera::setViewCenter( const QVector3D& viewCenter )
+{
+ Q_D(Camera);
+ d->m_viewCenter = viewCenter;
+ d->m_cameraToCenter = viewCenter - d->m_position;
+ d->m_viewMatrixDirty = true;
+ d->m_syncNeeded = true;
+}
+
+QVector3D Camera::viewCenter() const
+{
+ Q_D(const Camera);
+ return d->m_viewCenter;
+}
+
+QVector3D Camera::viewVector() const
+{
+ Q_D(const Camera);
+ return d->m_cameraToCenter;
+}
+
+void Camera::setOrthographicProjection( float left, float right,
+ float bottom, float top,
+ float nearPlane, float farPlane )
+{
+ Q_D(Camera);
+ d->m_left = left;
+ d->m_right = right;
+ d->m_bottom = bottom;
+ d->m_top = top;
+ d->m_nearPlane = nearPlane;
+ d->m_farPlane = farPlane;
+ d->m_projectionType = OrthogonalProjection;
+ d->updateOrthogonalProjection();
+}
+
+void Camera::setPerspectiveProjection( float fieldOfView, float aspectRatio,
+ float nearPlane, float farPlane )
+{
+ Q_D(Camera);
+ d->m_fieldOfView = fieldOfView;
+ d->m_aspectRatio = aspectRatio;
+ d->m_nearPlane = nearPlane;
+ d->m_farPlane = farPlane;
+ d->m_projectionType = PerspectiveProjection;
+ d->updatePerpectiveProjection();
+}
+
+void Camera::setNearPlane(float nearPlane)
+{
+ Q_D(Camera);
+ if (qFuzzyCompare(d->m_nearPlane, nearPlane))
+ return;
+ d->m_nearPlane = nearPlane;
+ if (d->m_projectionType == PerspectiveProjection)
+ d->updatePerpectiveProjection();
+ emit nearPlaneChanged();
+}
+
+float Camera::nearPlane() const
+{
+ Q_D(const Camera);
+ return d->m_nearPlane;
+}
+
+void Camera::setFarPlane(float farPlane)
+{
+ Q_D(Camera);
+ if (qFuzzyCompare(d->m_farPlane, farPlane))
+ return;
+ d->m_farPlane = farPlane;
+ if (d->m_projectionType == PerspectiveProjection)
+ d->updatePerpectiveProjection();
+ emit farPlaneChanged();
+}
+
+float Camera::farPlane() const
+{
+ Q_D(const Camera);
+ return d->m_farPlane;
+}
+
+void Camera::setFieldOfView(float fieldOfView)
+{
+ Q_D(Camera);
+ if (qFuzzyCompare(d->m_fieldOfView, fieldOfView))
+ return;
+ d->m_fieldOfView = fieldOfView;
+ if (d->m_projectionType == PerspectiveProjection)
+ d->updatePerpectiveProjection();
+ emit fieldOfViewChanged();
+}
+
+float Camera::fieldOfView() const
+{
+ Q_D(const Camera);
+ return d->m_fieldOfView;
+}
+
+void Camera::setAspectRatio(float aspectRatio)
+{
+ Q_D(Camera);
+ if (qFuzzyCompare(d->m_aspectRatio, aspectRatio))
+ return;
+ d->m_aspectRatio = aspectRatio;
+ if (d->m_projectionType == PerspectiveProjection)
+ d->updatePerpectiveProjection();
+ emit aspectRatioChanged();
+}
+
+float Camera::aspectRatio() const
+{
+ Q_D(const Camera);
+ return d->m_aspectRatio;
+}
+
+void Camera::setLeft(float left)
+{
+ Q_D(Camera);
+ if (qFuzzyCompare(d->m_left, left))
+ return;
+ d->m_left = left;
+ if (d->m_projectionType == OrthogonalProjection)
+ d->updateOrthogonalProjection();
+ emit leftChanged();
+}
+
+float Camera::left() const
+{
+ Q_D(const Camera);
+ return d->m_left;
+}
+
+void Camera::setRight(float right)
+{
+ Q_D(Camera);
+ if (qFuzzyCompare(d->m_right, right))
+ return;
+ d->m_right = right;
+ if (d->m_projectionType == OrthogonalProjection)
+ d->updateOrthogonalProjection();
+ emit rightChanged();
+}
+
+float Camera::right() const
+{
+ Q_D(const Camera);
+ return d->m_right;
+}
+
+void Camera::setBottom(float bottom)
+{
+ Q_D(Camera);
+ if (qFuzzyCompare(d->m_bottom, bottom))
+ return;
+ d->m_bottom = bottom;
+ if (d->m_projectionType == OrthogonalProjection)
+ d->updateOrthogonalProjection();
+ emit bottomChanged();
+}
+
+float Camera::bottom() const
+{
+ Q_D(const Camera);
+ return d->m_bottom;
+}
+
+void Camera::setTop(float top)
+{
+ Q_D(Camera);
+ if (qFuzzyCompare(d->m_top, top))
+ return;
+ d->m_top = top;
+ if (d->m_projectionType == OrthogonalProjection)
+ d->updateOrthogonalProjection();
+ emit topChanged();
+}
+
+float Camera::top() const
+{
+ Q_D(const Camera);
+ return d->m_top;
+}
+
+QMatrix4x4 Camera::viewMatrix() const
+{
+ Q_D(const Camera);
+ if ( d->m_viewMatrixDirty )
+ {
+ d->m_viewMatrix.setToIdentity();
+ d->m_viewMatrix.lookAt( d->m_position, d->m_viewCenter, d->m_upVector );
+ d->m_viewMatrixDirty = false;
+ }
+ return d->m_viewMatrix;
+}
+
+QMatrix4x4 Camera::projectionMatrix() const
+{
+ Q_D(const Camera);
+ return d->m_projectionMatrix;
+}
+
+QMatrix4x4 Camera::viewProjectionMatrix() const
+{
+ Q_D(const Camera);
+ if ( d->m_viewMatrixDirty || d->m_viewProjectionMatrixDirty )
+ {
+ d->m_viewProjectionMatrix = d->m_projectionMatrix * viewMatrix();
+ d->m_viewProjectionMatrixDirty = false;
+ }
+ return d->m_viewProjectionMatrix;
+}
+
+void Camera::translate( const QVector3D& vLocal, CameraTranslationOption option )
+{
+ Q_D(Camera);
+
+ // Calculate the amount to move by in world coordinates
+ QVector3D vWorld;
+ if ( !qFuzzyIsNull( vLocal.x() ) )
+ {
+ // Calculate the vector for the local x axis
+ QVector3D x = QVector3D::crossProduct( d->m_cameraToCenter, d->m_upVector ).normalized();
+ vWorld += vLocal.x() * x;
+ }
+
+ if ( !qFuzzyIsNull( vLocal.y() ) )
+ vWorld += vLocal.y() * d->m_upVector;
+
+ if ( !qFuzzyIsNull( vLocal.z() ) )
+ vWorld += vLocal.z() * d->m_cameraToCenter.normalized();
+
+ // Update the camera position using the calculated world vector
+ d->m_position += vWorld;
+
+ // May be also update the view center coordinates
+ if ( option == TranslateViewCenter )
+ d->m_viewCenter += vWorld;
+
+ // Refresh the camera -> view center vector
+ d->m_cameraToCenter = d->m_viewCenter - d->m_position;
+
+ // Calculate a new up vector. We do this by:
+ // 1) Calculate a new local x-direction vector from the cross product of the new
+ // camera to view center vector and the old up vector.
+ // 2) The local x vector is the normal to the plane in which the new up vector
+ // must lay. So we can take the cross product of this normal and the new
+ // x vector. The new normal vector forms the last part of the orthonormal basis
+ QVector3D x = QVector3D::crossProduct( d->m_cameraToCenter, d->m_upVector ).normalized();
+ d->m_upVector = QVector3D::crossProduct( x, d->m_cameraToCenter ).normalized();
+
+ d->m_viewMatrixDirty = true;
+ d->m_viewProjectionMatrixDirty = true;
+}
+
+void Camera::translateWorld(const QVector3D& vWorld , CameraTranslationOption option )
+{
+ Q_D(Camera);
+
+ // Update the camera position using the calculated world vector
+ d->m_position += vWorld;
+
+ // May be also update the view center coordinates
+ if ( option == TranslateViewCenter )
+ d->m_viewCenter += vWorld;
+
+ // Refresh the camera -> view center vector
+ d->m_cameraToCenter = d->m_viewCenter - d->m_position;
+
+ d->m_viewMatrixDirty = true;
+ d->m_viewProjectionMatrixDirty = true;
+}
+
+QQuaternion Camera::tiltRotation(float angle) const
+{
+ Q_D(const Camera);
+ QVector3D xBasis = QVector3D::crossProduct( d->m_upVector, d->m_cameraToCenter.normalized() ).normalized();
+ return QQuaternion::fromAxisAndAngle( xBasis, -angle );
+}
+
+QQuaternion Camera::panRotation(float angle) const
+{
+ Q_D(const Camera);
+ return QQuaternion::fromAxisAndAngle( d->m_upVector, angle );
+}
+
+QQuaternion Camera::rollRotation(float angle) const
+{
+ Q_D(const Camera);
+ return QQuaternion::fromAxisAndAngle( d->m_cameraToCenter, -angle );
+}
+
+void Camera::tilt( const float& angle )
+{
+ QQuaternion q = tiltRotation( angle );
+ rotate( q );
+}
+
+void Camera::pan( const float& angle )
+{
+ QQuaternion q = panRotation( -angle );
+ rotate( q );
+}
+
+void Camera::roll( const float& angle )
+{
+ QQuaternion q = rollRotation( -angle );
+ rotate( q );
+}
+
+void Camera::tiltAboutViewCenter( const float& angle )
+{
+ QQuaternion q = tiltRotation( -angle );
+ rotateAboutViewCenter( q );
+}
+
+void Camera::panAboutViewCenter( const float& angle )
+{
+ QQuaternion q = panRotation( angle );
+ rotateAboutViewCenter( q );
+}
+
+void Camera::rollAboutViewCenter( const float& angle )
+{
+ QQuaternion q = rollRotation( angle );
+ rotateAboutViewCenter( q );
+}
+
+void Camera::rotate( const QQuaternion& q )
+{
+ Q_D(Camera);
+ d->m_upVector = q.rotatedVector( d->m_upVector );
+ d->m_cameraToCenter = q.rotatedVector( d->m_cameraToCenter );
+ d->m_viewCenter = d->m_position + d->m_cameraToCenter;
+ d->m_viewMatrixDirty = true;
+ d->m_viewProjectionMatrixDirty = true;
+ d->m_syncNeeded = true;
+}
+
+void Camera::rotateAboutViewCenter( const QQuaternion& q )
+{
+ Q_D(Camera);
+ d->m_upVector = q.rotatedVector( d->m_upVector );
+ d->m_cameraToCenter = q.rotatedVector( d->m_cameraToCenter );
+ d->m_position = d->m_viewCenter - d->m_cameraToCenter;
+ d->m_viewMatrixDirty = true;
+ d->m_viewProjectionMatrixDirty = true;
+ d->m_syncNeeded = true;
+}
+
+//void Camera::update(UpdateVisitor *)
+//{
+// Q_D(Camera);
+// if (d->m_syncNeeded) {
+// // ...
+// d->m_syncNeeded = false;
+// }
+//}
+
+}
diff --git a/src/render/frontend/camera.h b/src/render/frontend/camera.h
new file mode 100644
index 000000000..7dd91695a
--- /dev/null
+++ b/src/render/frontend/camera.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include "component.h"
+
+#include <QMatrix4x4>
+#include <QQuaternion>
+#include <QVector3D>
+
+namespace Qt3D {
+
+class CameraPrivate;
+
+class Camera : public Component
+{
+ Q_OBJECT
+
+ // TODO Move view matrix out of the camera and use Transform component (once it exists)
+ Q_PROPERTY(QVector3D position READ position WRITE setPosition)
+ Q_PROPERTY(QVector3D upVector READ upVector WRITE setUpVector)
+ Q_PROPERTY(QVector3D viewCenter READ viewCenter WRITE setViewCenter)
+
+ Q_PROPERTY(ProjectionType projectionType READ projectionType WRITE setProjectionType NOTIFY projectionTypeChanged)
+ Q_PROPERTY(float nearPlane READ nearPlane WRITE setNearPlane NOTIFY nearPlaneChanged)
+ Q_PROPERTY(float farPlane READ farPlane WRITE setFarPlane NOTIFY farPlaneChanged)
+
+ Q_PROPERTY(float fieldOfView READ fieldOfView WRITE setFieldOfView NOTIFY fieldOfViewChanged)
+ Q_PROPERTY(float aspectRatio READ aspectRatio WRITE setAspectRatio NOTIFY aspectRatioChanged)
+
+ Q_PROPERTY(float left READ left WRITE setLeft NOTIFY leftChanged)
+ Q_PROPERTY(float right READ right WRITE setRight NOTIFY rightChanged)
+ Q_PROPERTY(float bottom READ bottom WRITE setBottom NOTIFY bottomChanged)
+ Q_PROPERTY(float top READ top WRITE setTop NOTIFY topChanged)
+
+ Q_ENUMS( ProjectionType )
+
+public:
+ explicit Camera(Node *parent = 0);
+
+ enum ProjectionType {
+ OrthogonalProjection,
+ PerspectiveProjection
+ };
+
+ enum CameraTranslationOption {
+ TranslateViewCenter,
+ DontTranslateViewCenter
+ };
+
+ void setViewMatrix(const QMatrix4x4& m);
+
+ QVector3D position() const;
+ QVector3D upVector() const;
+ QVector3D viewCenter() const;
+
+ QVector3D viewVector() const;
+
+ void setProjectionType(ProjectionType projectioType);
+ ProjectionType projectionType() const;
+
+ void setNearPlane(float nearPlane);
+ float nearPlane() const;
+
+ void setFarPlane(float nearPlane);
+ float farPlane() const;
+
+ void setFieldOfView(float fieldOfView);
+ float fieldOfView() const;
+
+ void setAspectRatio(float aspectRatio);
+ float aspectRatio() const;
+
+ void setLeft(float left);
+ float left() const;
+
+ void setRight(float right);
+ float right() const;
+
+ void setBottom(float bottom);
+ float bottom() const;
+
+ void setTop(float top);
+ float top() const;
+
+ QMatrix4x4 viewMatrix() const;
+ QMatrix4x4 projectionMatrix() const;
+ QMatrix4x4 viewProjectionMatrix() const;
+
+ QQuaternion tiltRotation(float angle) const;
+ QQuaternion panRotation(float angle) const;
+ QQuaternion rollRotation(float angle) const;
+
+public slots:
+ void setOrthographicProjection(float left, float right,
+ float bottom, float top,
+ float nearPlane, float farPlane);
+
+ void setPerspectiveProjection(float fieldOfView, float aspect,
+ float nearPlane, float farPlane);
+
+ // TODO These slots should likely be on a modifier one layer up
+ void setPosition( const QVector3D& position );
+ void setUpVector( const QVector3D& upVector );
+ void setViewCenter( const QVector3D& viewCenter );
+
+ // Translate relative to camera orientation axes
+ void translate( const QVector3D& vLocal, CameraTranslationOption option = TranslateViewCenter );
+
+ // Translate relative to world axes
+ void translateWorld( const QVector3D& vWorld, CameraTranslationOption option = TranslateViewCenter );
+
+ void tilt( const float& angle );
+ void pan( const float& angle );
+ void roll( const float& angle );
+
+ void tiltAboutViewCenter( const float& angle );
+ void panAboutViewCenter( const float& angle );
+ void rollAboutViewCenter( const float& angle );
+
+ void rotate( const QQuaternion& q );
+ void rotateAboutViewCenter( const QQuaternion& q );
+
+signals:
+ void projectionTypeChanged();
+ void nearPlaneChanged();
+ void farPlaneChanged();
+ void fieldOfViewChanged();
+ void aspectRatioChanged();
+ void leftChanged();
+ void rightChanged();
+ void bottomChanged();
+ void topChanged();
+
+protected:
+ Q_DECLARE_PRIVATE(Camera)
+
+private:
+ CameraPrivate* d_ptr;
+};
+
+}
+
+#endif // CAMERA_H
diff --git a/src/render/frontend/camera_p.h b/src/render/frontend/camera_p.h
new file mode 100644
index 000000000..7f7015735
--- /dev/null
+++ b/src/render/frontend/camera_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CAMERA_P_H
+#define CAMERA_P_H
+
+#include <QMatrix4x4>
+#include <QVector3D>
+
+namespace Qt3D {
+
+class CameraPrivate
+{
+public:
+ CameraPrivate( Camera *qq )
+ : q_ptr( qq )
+ , m_position( 0.0f, 0.0f, 1.0f )
+ , m_upVector( 0.0f, 1.0f, 0.0f )
+ , m_viewCenter( 0.0f, 0.0f, 0.0f )
+ , m_cameraToCenter( 0.0f, 0.0f, -1.0f )
+ , m_projectionType( Camera::OrthogonalProjection )
+ , m_nearPlane( 0.1f )
+ , m_farPlane( 1024.0f )
+ , m_fieldOfView( 25.0f )
+ , m_aspectRatio( 1.0f )
+ , m_left( -0.5 )
+ , m_right( 0.5f )
+ , m_bottom( -0.5f )
+ , m_top( 0.5f )
+ , m_viewMatrixDirty( true )
+ , m_viewProjectionMatrixDirty( true )
+ , m_syncNeeded( false )
+ {
+ updateOrthogonalProjection();
+ }
+
+ ~CameraPrivate()
+ {
+ }
+
+ inline void updatePerpectiveProjection()
+ {
+ m_projectionMatrix.setToIdentity();
+ m_projectionMatrix.perspective( m_fieldOfView, m_aspectRatio, m_nearPlane, m_farPlane );
+ m_viewProjectionMatrixDirty = true;
+ m_syncNeeded = true;
+ }
+
+ inline void updateOrthogonalProjection()
+ {
+ m_projectionMatrix.setToIdentity();
+ m_projectionMatrix.ortho( m_left, m_right, m_bottom, m_top, m_nearPlane, m_farPlane );
+ m_viewProjectionMatrixDirty = true;
+ m_syncNeeded = true;
+ }
+
+ Q_DECLARE_PUBLIC( Camera )
+
+ Camera *q_ptr;
+
+ QVector3D m_position;
+ QVector3D m_upVector;
+ QVector3D m_viewCenter;
+
+ QVector3D m_cameraToCenter; // The vector from the camera position to the view center
+
+ Camera::ProjectionType m_projectionType;
+
+ float m_nearPlane;
+ float m_farPlane;
+
+ float m_fieldOfView;
+ float m_aspectRatio;
+
+ float m_left;
+ float m_right;
+ float m_bottom;
+ float m_top;
+
+ mutable QMatrix4x4 m_viewMatrix;
+ mutable QMatrix4x4 m_projectionMatrix;
+ mutable QMatrix4x4 m_viewProjectionMatrix;
+
+ mutable bool m_viewMatrixDirty;
+ mutable bool m_viewProjectionMatrixDirty;
+ mutable bool m_syncNeeded;
+};
+
+}
+
+#endif // CAMERA_P_H
diff --git a/src/render/frontend/cameraselector.cpp b/src/render/frontend/cameraselector.cpp
new file mode 100644
index 000000000..091327646
--- /dev/null
+++ b/src/render/frontend/cameraselector.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "cameraselector.h"
+
+namespace Qt3D {
+
+CameraSelector::CameraSelector(Node *parent)
+ : Qt3D::Component(parent)
+ , m_camera(0)
+{
+}
+
+void CameraSelector::setCamera(Qt3D::Camera *camera)
+{
+ if (m_camera != camera) {
+ m_camera = camera;
+ emit cameraChanged();
+ }
+}
+
+Camera *CameraSelector::camera() const
+{
+ return m_camera;
+}
+
+} // namespace Qt3D
diff --git a/src/render/frontend/cameraselector.h b/src/render/frontend/cameraselector.h
new file mode 100644
index 000000000..9da27405c
--- /dev/null
+++ b/src/render/frontend/cameraselector.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_CAMERASELECTOR_H
+#define QT3D_CAMERASELECTOR_H
+
+#include <qt3dcore_global.h>
+#include <component.h>
+
+namespace Qt3D {
+
+class Camera;
+
+class CameraSelector : public Qt3D::Component
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Qt3D::Camera *camera READ camera WRITE setCamera NOTIFY cameraChanged)
+
+public:
+ explicit CameraSelector(Node *parent = 0);
+
+ void setCamera(Qt3D::Camera *camera);
+ Camera *camera() const;
+
+signals:
+ void cameraChanged();
+
+private:
+ Camera *m_camera;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_CAMERASELECTOR_H
diff --git a/src/render/frontend/effect.cpp b/src/render/frontend/effect.cpp
new file mode 100644
index 000000000..e10932fa4
--- /dev/null
+++ b/src/render/frontend/effect.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "effect.h"
+#include "technique.h"
+
+#include <QDebug>
+
+namespace Qt3D {
+
+Effect::Effect(Node *parent)
+ : Node(parent)
+{
+ qRegisterMetaType<Qt3D::Effect*>();
+ qDebug() << Q_FUNC_INFO;
+}
+
+
+QQmlListProperty<Qt3D::Technique> Effect::techniqueList()
+{
+ return QQmlListProperty<Qt3D::Technique>(this, m_techniques);
+}
+
+void Effect::addTechnique(Technique *t)
+{
+ Q_ASSERT(t);
+ t->setParent(this);
+ m_techniques.append(t);
+ emit techniquesChanged();
+}
+
+QList<Technique *> Effect::techniques() const
+{
+ return m_techniques;
+}
+
+void Effect::clearTechniques()
+{
+ qDeleteAll(m_techniques);
+ m_techniques.clear();
+}
+
+} // of namespace
diff --git a/src/render/frontend/effect.h b/src/render/frontend/effect.h
new file mode 100644
index 000000000..f1caf692e
--- /dev/null
+++ b/src/render/frontend/effect.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EFFECT_H
+#define EFFECT_H
+
+#include <qt3dcore_global.h>
+#include <node.h>
+
+#include <QQmlListProperty>
+#include <QVector>
+
+namespace Qt3D {
+
+class Technique;
+
+class QT3DCORESHARED_EXPORT Effect : public Node
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQmlListProperty<Qt3D::Technique> techniques READ techniqueList NOTIFY techniquesChanged)
+
+public:
+ explicit Effect(Node *parent = 0);
+
+ QQmlListProperty<Qt3D::Technique> techniqueList();
+
+ void addTechnique(Technique *t);
+
+ QList<Technique *> techniques() const;
+
+ void clearTechniques();
+signals:
+ void techniquesChanged();
+
+private:
+ QList<Technique *> m_techniques;
+};
+
+}
+
+Q_DECLARE_METATYPE(Qt3D::Effect*)
+
+#endif // EFFECT_H
diff --git a/src/render/frontend/material.cpp b/src/render/frontend/material.cpp
new file mode 100644
index 000000000..16ba6e8fb
--- /dev/null
+++ b/src/render/frontend/material.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "material.h"
+
+#include <qchangearbiter.h>
+#include <texture.h>
+
+#include <QDebug>
+
+namespace Qt3D {
+
+Material::Material(Node *parent)
+ : Component(parent)
+{
+}
+
+Qt3D::Effect *Material::effect() const
+{
+ return m_effect;
+}
+
+void Material::setEffect(Qt3D::Effect *effect)
+{
+ if (effect == m_effect)
+ return;
+
+ m_effect = effect;
+ emit effectChanged();
+}
+
+void Material::setParameter(QString name, QVariant val)
+{
+ m_parameters[name] = val;
+
+ // schedule update to the backend
+ QScenePropertyChangePtr change(new QScenePropertyChange(MaterialParameter, this));
+ change->m_propertyName = name.toLocal8Bit();
+ change->m_value = val;
+ notifySceneChange(change);
+}
+
+QVariantMap Material::parameterValues() const
+{
+ return m_parameters;
+}
+
+Material::TextureDict Material::textureValues() const
+{
+ return m_textures;
+}
+
+void Material::setTextureParameter(QString name, Texture *tex)
+{
+ m_textures[name] = tex;
+}
+
+void Material::onTagValueChanged()
+{
+ Tag* t = qobject_cast<Tag*>(sender());
+ Q_ASSERT(m_tagList.contains(t));
+
+ QVariant v = t->value();
+ QmlTexture* qmlTex = v.value<QmlTexture*>();
+ if (qmlTex) {
+ qDebug() << "got texture parameter" << t->name();
+ setTextureParameter(t->name(), qmlTex->texture());
+ } else {
+ setParameter(t->name(), t->value());
+ }
+}
+
+QQmlListProperty<Tag> Material::qmlParameters()
+{
+ return QQmlListProperty<Tag>(this, 0,
+ &Material::appendTag,
+ &Material::tagCount,
+ &Material::tagAt,
+ &Material::clearTags );
+}
+
+void Material::appendTag(QQmlListProperty<Tag> *list, Tag *tag)
+{
+ Material *mat = qobject_cast<Material *>(list->object);
+ if (mat) {
+ tag->setParent(mat);
+ connect(tag, SIGNAL(valueChanged()), mat, SLOT(onTagValueChanged()));
+ mat->m_tagList.append(tag);
+ emit mat->parametersChanged();
+ }
+}
+
+Tag *Material::tagAt(QQmlListProperty<Tag> *list, int index)
+{
+ Material *mat = qobject_cast<Material *>(list->object);
+ if (mat)
+ return mat->m_tagList.value(index);
+ return 0;
+}
+
+int Material::tagCount(QQmlListProperty<Tag> *list)
+{
+ Material *mat = qobject_cast<Material *>(list->object);
+ if (mat)
+ return mat->m_tagList.size();
+ return 0;
+}
+
+void Material::clearTags(QQmlListProperty<Tag> *list)
+{
+ Material *mat = qobject_cast<Material *>(list->object);
+ if (mat) {
+ mat->m_parameters.clear();
+ mat->m_tagList.clear();
+ emit mat->parametersChanged();
+ }
+}
+
+} // of namespace
diff --git a/src/render/frontend/material.h b/src/render/frontend/material.h
new file mode 100644
index 000000000..b0dea466a
--- /dev/null
+++ b/src/render/frontend/material.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MATERIAL_H
+#define MATERIAL_H
+
+#include <QVariant>
+
+#include <component.h>
+
+// FIXME - write a custom QML parser and stop mis-using Tag
+#include "tag.h"
+
+#include <qt3dcore_global.h>
+
+namespace Qt3D {
+
+class Effect;
+class Texture;
+
+class QT3DCORESHARED_EXPORT Material : public Component
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt3D::Effect* effect READ effect WRITE setEffect NOTIFY effectChanged)
+ Q_PROPERTY(QQmlListProperty<Qt3D::Tag> parameters READ qmlParameters)
+
+public:
+ explicit Material(Node *parent = 0);
+
+ Qt3D::Effect *effect() const;
+ void setEffect(Qt3D::Effect *effect);
+
+ void setParameter(QString name, QVariant val);
+
+ QVariantMap parameterValues() const;
+
+ typedef QMap<QString, Texture*> TextureDict;
+ TextureDict textureValues() const;
+
+ void setTextureParameter(QString name, Texture* tex);
+
+signals:
+ void effectChanged();
+ void parametersChanged();
+
+private slots:
+ void onTagValueChanged();
+
+private:
+ QQmlListProperty<Tag> qmlParameters();
+
+ // FIXME - remove when we have a custom QML parser
+ static void appendTag(QQmlListProperty<Tag> *list, Tag *bar);
+ static Tag *tagAt(QQmlListProperty<Tag> *list, int index);
+ static int tagCount(QQmlListProperty<Tag> *list);
+ static void clearTags(QQmlListProperty<Tag> *list);
+
+
+ Effect *m_effect;
+ QVariantMap m_parameters;
+
+ // FIXME - remove with tags
+ QList<Tag *> m_tagList;
+
+ TextureDict m_textures;
+};
+
+}
+
+#endif // MATERIAL_H
diff --git a/src/render/frontend/mesh.cpp b/src/render/frontend/mesh.cpp
new file mode 100644
index 000000000..27f8c513b
--- /dev/null
+++ b/src/render/frontend/mesh.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mesh.h"
+
+#include <qchangearbiter.h>
+
+#include <QDebug>
+#include <QFile>
+#include <QFileInfo>
+
+#include <objloader.h>
+
+namespace Qt3D {
+
+Mesh::Mesh(Node *parent)
+ : Component( parent )
+ , m_sourceDirty( false )
+{
+}
+
+Mesh::~Mesh()
+{
+}
+
+void Mesh::setSource( const QString& source )
+{
+ if ( source == m_source )
+ return;
+ m_source = source;
+ m_sourceDirty = true;
+
+ // FIXME - synchronous update
+ update();
+
+ // Let aspects know about the change
+ QScenePropertyChangePtr e(new QScenePropertyChange(Qt3D::MeshChange, this));
+ e->m_propertyName = QByteArrayLiteral("source");
+ e->m_value = m_source;
+ notifySceneChange(e);
+
+ emit sourceChanged();
+}
+
+QString Mesh::source() const
+{
+ return m_source;
+}
+
+MeshDataPtr Mesh::data() const
+{
+ return m_data;
+}
+
+void Mesh::setData(MeshDataPtr d)
+{
+ m_data = d;
+}
+
+void Mesh::update()
+{
+ if (m_sourceDirty) {
+ m_data = MeshDataPtr();
+ m_sourceDirty = false;
+
+ QFileInfo finfo(m_source);
+ if (!finfo.exists()) {
+ qWarning() << Q_FUNC_INFO << "not found:" << m_source;
+ return;
+ }
+
+ QFile f(m_source);
+ f.open(QIODevice::ReadOnly);
+
+ ObjLoader objLoad;
+ objLoad.setLoadTextureCoordinatesEnabled(true);
+
+ if (!objLoad.load(&f)) {
+ qWarning() << Q_FUNC_INFO << "OBJ load failure for:" << m_source;
+ return;
+ }
+
+ qDebug() << "Loaded OBJ ok";
+ setData(objLoad.mesh());
+ setObjectName("OBJ");
+ }
+
+ m_sourceDirty = false;
+}
+
+} // of namespace Qt3D
diff --git a/src/render/frontend/mesh.h b/src/render/frontend/mesh.h
new file mode 100644
index 000000000..766f38042
--- /dev/null
+++ b/src/render/frontend/mesh.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_MESH_H
+#define QT3D_MESH_H
+
+#include <component.h>
+
+#include <meshdata.h>
+
+namespace Qt3D {
+
+/**
+* @brief Simple static mesh
+*
+*/
+class Mesh : public Component
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
+
+public:
+ Mesh(Node *parent = 0);
+ virtual ~Mesh();
+
+ void setSource(const QString &source);
+ QString source() const;
+
+ MeshDataPtr data() const;
+ void setData(MeshDataPtr d);
+signals:
+ void sourceChanged();
+
+private:
+ Q_INVOKABLE void update();
+
+ MeshDataPtr m_data;
+ QString m_source;
+ bool m_sourceDirty;
+};
+
+}
+
+#endif // of QT3D_MESH_H
diff --git a/src/render/frontend/qitemmodelbuffer.cpp b/src/render/frontend/qitemmodelbuffer.cpp
new file mode 100644
index 000000000..d13e389b4
--- /dev/null
+++ b/src/render/frontend/qitemmodelbuffer.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qitemmodelbuffer.h"
+
+#include <QDebug>
+#include <QColor>
+
+namespace Qt3D {
+
+void variantToBytes(void* dest, const QVariant& v, GLint type)
+{
+ int varType = v.type();
+ switch (type) {
+ case GL_FLOAT: {
+ float f = v.toFloat();
+ memcpy(dest, &f, sizeof(float));
+ return;
+ }
+
+ case GL_INT: {
+ GLint i = v.toInt();
+ memcpy(dest, &i, sizeof(GLint));
+ return;
+ }
+
+ case GL_UNSIGNED_INT: {
+ GLuint i = v.toUInt();
+ memcpy(dest, &i, sizeof(GLuint));
+ return;
+ }
+
+ case GL_FLOAT_VEC3:
+ if (varType == QVariant::Vector3D) {
+ QVector3D v3(v.value<QVector3D>());
+ memcpy(dest, &v3[0], sizeof(float) * 3);
+ return;
+ }
+
+ break;
+
+ case GL_FLOAT_VEC4:
+ if (varType == QVariant::Vector4D) {
+ QVector4D v4(v.value<QVector4D>());
+ memcpy(dest, &v4[0], sizeof(float) * 4);
+ return;
+ }
+
+ if (varType == QVariant::Color) {
+ QColor c = v.value<QColor>();
+ float* fptr = reinterpret_cast<float*>(dest);
+ *fptr++ = c.redF();
+ *fptr++ = c.greenF();
+ *fptr++ = c.blueF();
+ *fptr++ = c.alphaF();
+ return;
+ }
+
+ if (varType == QVariant::Quaternion) {
+ QVector4D qv = v.value<QQuaternion>().toVector4D();
+ memcpy(dest, &qv[0], sizeof(float) * 4);
+ return;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ qWarning() << Q_FUNC_INFO << "failed to convert" << v << "to GL type" <<
+ QString::number(type, 16);
+}
+
+QItemModelBuffer::QItemModelBuffer()
+{
+}
+
+void QItemModelBuffer::setModel(QAbstractItemModel *model)
+{
+ if (model == m_model)
+ return;
+
+ m_model = model;
+ m_buffer.clear();
+
+ connect(m_model, SIGNAL(modelReset()), this, SLOT(onModelReset()));
+ connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(onModelDataChanged(QModelIndex,QModelIndex)));
+}
+
+void QItemModelBuffer::setRoot(const QModelIndex &rootIndex)
+{
+ m_rootIndex = rootIndex;
+ m_buffer.clear();
+}
+
+void QItemModelBuffer::mapRoleName(QByteArray roleName, int elementType)
+{
+ mapRoleName(roleName, roleName, elementType);
+}
+
+void QItemModelBuffer::mapRoleName(QByteArray roleName, QString attributeName, int elementType)
+{
+ if (m_model) {
+ if (!m_model->roleNames().values().contains(roleName)) {
+ qWarning() << Q_FUNC_INFO << "unknown role name" << roleName;
+ }
+ }
+
+ m_mappings.append(RoleMapping(roleName, attributeName, elementType));
+ m_buffer.clear();
+}
+
+BufferPtr QItemModelBuffer::buffer()
+{
+ if (!m_buffer) {
+ if (!validateRoles())
+ return m_buffer;
+
+ m_attributes.clear();
+ m_itemStride = 0;
+
+ m_buffer.reset(new Buffer(QOpenGLBuffer::VertexBuffer));
+ // assume model will change
+ m_buffer->setUsage(QOpenGLBuffer::DynamicDraw);
+
+ int rowCount = m_model->rowCount(m_rootIndex);
+ int offset = 0;
+ int mappingCount = m_mappings.count();
+ for (int m=0; m<mappingCount; ++m)
+ m_itemStride += m_mappings.at(m).byteSize;
+
+ for (int m=0; m<mappingCount; ++m) {
+ const RoleMapping mapping(m_mappings.at(m));
+ AttributePtr attr(new Attribute(m_buffer, mapping.type,
+ rowCount,
+ offset, m_itemStride));
+ m_attributes[mapping.attribute] = attr;
+ offset += byteSizeFromType(mapping.type);
+ } // of mappings iteration
+
+ m_buffer->setData(computeBufferData());
+ }
+
+ return m_buffer;
+}
+
+QStringList QItemModelBuffer::attributeNames() const
+{
+ return m_attributes.keys();
+}
+
+AttributePtr QItemModelBuffer::attributeByName(QString nm) const
+{
+ return m_attributes.value(nm);
+}
+
+void QItemModelBuffer::onModelDataChanged(const QModelIndex& topLeft,
+ const QModelIndex& bottomRight)
+{
+ if (!m_buffer)
+ return;
+
+ if (topLeft.parent() != m_rootIndex)
+ return;
+
+ QByteArray newBytes = m_buffer->data();
+ for (int row=topLeft.row(); row<=bottomRight.row(); ++row) {
+ QModelIndex index = topLeft.sibling(row, topLeft.column());
+
+ char* itemPtr = newBytes.data();
+ itemPtr += m_itemStride * row;
+
+ writeDataForIndex(index, m_mappings.count(), itemPtr);
+ } // of rows changed iteration
+
+ m_buffer->setData(newBytes);
+}
+
+void QItemModelBuffer::onModelReset()
+{
+ if (!m_buffer)
+ return;
+
+ QByteArray b = computeBufferData();
+ m_buffer->setData(b);
+}
+
+QByteArray QItemModelBuffer::computeBufferData()
+{
+ int rowCount = m_model->rowCount(m_rootIndex);
+
+ int mappingCount = m_mappings.count();
+ QByteArray newData;
+ newData.resize(m_itemStride * rowCount);
+ char* bufferPtr = newData.data();
+
+ for (int row=0; row<rowCount; ++row) {
+ writeDataForIndex(m_model->index(row, 0, m_rootIndex), mappingCount, bufferPtr);
+ bufferPtr += m_itemStride;
+ } // of rows iteration
+
+ return newData;
+}
+
+void QItemModelBuffer::writeDataForIndex(const QModelIndex& index, int mappingCount, char* bufferPtr)
+{
+ char* fieldPtr = bufferPtr;
+ for (int m=0; m<mappingCount; ++m) {
+ const RoleMapping& mapping(m_mappings.at(m));
+ QVariant v = m_model->data(index, mapping.cachedRole);
+ variantToBytes(fieldPtr, v, mapping.type);
+
+ fieldPtr += mapping.byteSize;
+ } // of mappings iteration
+}
+
+bool QItemModelBuffer::validateRoles()
+{
+ Q_ASSERT(m_model);
+
+ QHash<int, QByteArray> roles(m_model->roleNames());
+ // create a lookup that's the the way round we need
+ QHash<QByteArray, int> inverseRoles;
+ foreach (int r, roles.keys())
+ inverseRoles[roles.value(r)] = r;
+
+ for (int m=0; m<m_mappings.count(); ++m) {
+ QByteArray rnm(m_mappings.at(m).roleName);
+ if (!inverseRoles.contains(rnm)) {
+ qWarning() << "unknown role:" << rnm;
+ return false;
+ }
+
+ m_mappings[m].cachedRole = inverseRoles[rnm];
+ } // of mappings iteration
+
+ return true;
+}
+
+QItemModelBuffer::RoleMapping::RoleMapping(QByteArray rnm, QString nm, int ty) :
+ roleName(rnm),
+ cachedRole(-1),
+ attribute(nm),
+ type(ty)
+{
+ byteSize = byteSizeFromType(ty);
+}
+
+} // namespace Qt3D
diff --git a/src/render/frontend/qitemmodelbuffer.h b/src/render/frontend/qitemmodelbuffer.h
new file mode 100644
index 000000000..c567ab545
--- /dev/null
+++ b/src/render/frontend/qitemmodelbuffer.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QITEMMODELBUFFER_H
+#define QT3D_QITEMMODELBUFFER_H
+
+#include <QAbstractItemModel>
+#include <QMap>
+#include <QObject>
+
+#include <meshdata.h>
+
+namespace Qt3D {
+
+class QItemModelBuffer : public QObject
+{
+ Q_OBJECT
+public:
+ QItemModelBuffer();
+
+ void setModel(QAbstractItemModel* model);
+ void setRoot(const QModelIndex& rootIndex);
+
+ void mapRoleName(QByteArray roleName, int type);
+ void mapRoleName(QByteArray roleName, QString attributeName, int type);
+
+ BufferPtr buffer();
+
+ QStringList attributeNames() const;
+ AttributePtr attributeByName(QString nm) const;
+
+private slots:
+
+ void onModelReset();
+
+ void onModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+private:
+ QAbstractItemModel* m_model;
+ QModelIndex m_rootIndex;
+
+ struct RoleMapping {
+ RoleMapping(QByteArray role, QString attr, int ty);
+
+ QByteArray roleName;
+ int cachedRole;
+ QString attribute;
+ int type;
+ int byteSize;
+ };
+
+ QList<RoleMapping> m_mappings;
+
+ BufferPtr m_buffer;
+ QMap<QString, AttributePtr> m_attributes;
+ int m_itemStride;
+
+ QByteArray computeBufferData();
+
+ void writeDataForIndex(const QModelIndex &index, int mappingCount, char *bufferPtr);
+ bool validateRoles();
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_QITEMMODELBUFFER_H
diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri
new file mode 100644
index 000000000..84930815e
--- /dev/null
+++ b/src/render/frontend/render-frontend.pri
@@ -0,0 +1,37 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/camera.h \
+ $$PWD/camera_p.h \
+ $$PWD/effect.h \
+ $$PWD/material.h \
+ $$PWD/mesh.h \
+ $$PWD/renderpass.h \
+ $$PWD/renderpassfilter.h \
+ $$PWD/shaderprogram.h \
+ $$PWD/technique.h \
+ $$PWD/viewport.h \
+ $$PWD/cameraselector.h \
+ $$PWD/techniquefilter.h \
+ $$PWD/tag.h \
+ $$PWD//shape.h \
+ $$PWD//transform.h \
+ $$PWD//qitemmodelbuffer.h \
+ $$PWD//texture.h
+
+SOURCES += \
+ $$PWD/camera.cpp \
+ $$PWD/effect.cpp \
+ $$PWD/material.cpp \
+ $$PWD/mesh.cpp \
+ $$PWD/renderpass.cpp \
+ $$PWD/renderpassfilter.cpp \
+ $$PWD/shaderprogram.cpp \
+ $$PWD/technique.cpp \
+ $$PWD/viewport.cpp \
+ $$PWD/cameraselector.cpp \
+ $$PWD/techniquefilter.cpp \
+ $$PWD/shape.cpp \
+ $$PWD/transform.cpp \
+ $$PWD/qitemmodelbuffer.cpp \
+ $$PWD/texture.cpp
diff --git a/src/render/frontend/renderpass.cpp b/src/render/frontend/renderpass.cpp
new file mode 100644
index 000000000..59c083fce
--- /dev/null
+++ b/src/render/frontend/renderpass.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderpass.h"
+#include "technique.h"
+
+#include <QDebug>
+
+namespace Qt3D {
+
+RenderPass::RenderPass(Node *parent)
+ : Node(parent)
+ , m_name()
+ , m_shaderProgram(0)
+ , m_stateSet(0)
+{
+}
+
+void RenderPass::setName(const QString &name)
+{
+ if (name != m_name) {
+ m_name = name;
+ emit nameChanged();
+ }
+}
+
+QString RenderPass::name() const
+{
+ return m_name;
+}
+
+void RenderPass::setShaderProgram(Qt3D::ShaderProgram *shaderProgram)
+{
+ if (shaderProgram != m_shaderProgram) {
+ m_shaderProgram = shaderProgram;
+ emit shaderProgramChanged();
+ }
+}
+
+Qt3D::ShaderProgram *RenderPass::shaderProgram() const
+{
+ return m_shaderProgram;
+}
+
+void RenderPass::addUniformBinding(Parameter *param, QString glslUniformName)
+{
+ m_uniforms.append(param);
+ m_parameterNameDict[param->name()] = glslUniformName;
+}
+
+void RenderPass::addAttributeBinding(Parameter *param, QString glslAttributeName)
+{
+ m_attributes.append(param);
+ m_parameterNameDict[param->name()] = glslAttributeName;
+}
+
+QString RenderPass::glslNameForParameter(QString paramName) const
+{
+ return m_parameterNameDict.value(paramName);
+}
+
+ParameterList RenderPass::attributes() const
+{
+ return m_attributes;
+}
+
+ParameterList RenderPass::uniforms() const
+{
+ return m_uniforms;
+}
+
+void RenderPass::setStateSet(DrawStateSet *ss)
+{
+ m_stateSet = ss;
+}
+
+DrawStateSet *RenderPass::stateSet() const
+{
+ return m_stateSet;
+}
+
+} // of namespace Qt3D
diff --git a/src/render/frontend/renderpass.h b/src/render/frontend/renderpass.h
new file mode 100644
index 000000000..ad2fb0088
--- /dev/null
+++ b/src/render/frontend/renderpass.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERPASS_H
+#define RENDERPASS_H
+
+#include <node.h>
+#include <qt3dcore_global.h>
+
+#include "shaderprogram.h"
+#include <drawstate.h>
+
+#include <QHash>
+
+namespace Qt3D {
+
+class Parameter;
+typedef QList<Parameter*> ParameterList;
+
+class QT3DCORESHARED_EXPORT RenderPass : public Node
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(Qt3D::ShaderProgram * shaderProgram READ shaderProgram WRITE setShaderProgram NOTIFY shaderProgramChanged)
+
+public:
+ explicit RenderPass(Node *parent = 0);
+
+ void setName(const QString &name);
+ QString name() const;
+
+ void setShaderProgram(Qt3D::ShaderProgram* shaderProgram);
+ Qt3D::ShaderProgram* shaderProgram() const;
+
+ void addUniformBinding(Parameter* param, QString glslUniformName);
+
+ void addAttributeBinding(Parameter* param, QString glslAttributeName);
+
+ QString glslNameForParameter(QString paramName) const;
+
+ ParameterList attributes() const;
+ ParameterList uniforms() const;
+
+ void setStateSet(DrawStateSet* ss);
+ DrawStateSet* stateSet() const;
+
+signals:
+ void nameChanged();
+ void shaderProgramChanged();
+
+protected:
+ QString m_name;
+ ShaderProgram* m_shaderProgram;
+ ParameterList m_attributes;
+ ParameterList m_uniforms;
+
+ // map Parameter names to GLSL names
+ QHash<QString, QString> m_parameterNameDict;
+
+ DrawStateSet* m_stateSet;
+};
+
+}
+
+#endif // RENDERPASS_H
diff --git a/src/render/frontend/renderpassfilter.cpp b/src/render/frontend/renderpassfilter.cpp
new file mode 100644
index 000000000..8b25fe239
--- /dev/null
+++ b/src/render/frontend/renderpassfilter.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderpassfilter.h"
+
+namespace Qt3D {
+
+RenderPassFilter::RenderPassFilter(Node *parent)
+ : Component(parent)
+{
+}
+
+void RenderPassFilter::setRenderPassNames(const QString &renderpassNames)
+{
+ if (m_renderPassNames != renderpassNames) {
+ m_renderPassNames = renderpassNames;
+ emit renderPassNamesChanged();
+ }
+}
+
+QString RenderPassFilter::renderPassNames() const
+{
+ return m_renderPassNames;
+}
+
+}
diff --git a/src/render/frontend/renderpassfilter.h b/src/render/frontend/renderpassfilter.h
new file mode 100644
index 000000000..cd9f81e88
--- /dev/null
+++ b/src/render/frontend/renderpassfilter.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERPASSFILTER_H
+#define RENDERPASSFILTER_H
+
+#include <qt3dcore_global.h>
+#include <component.h>
+
+#include <QString>
+
+namespace Qt3D {
+
+class QT3DCORESHARED_EXPORT RenderPassFilter : public Component
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString renderPassNames READ renderPassNames WRITE setRenderPassNames NOTIFY renderPassNamesChanged)
+
+public:
+ explicit RenderPassFilter(Node *parent = 0);
+
+ void setRenderPassNames(const QString &renderpassNames);
+ QString renderPassNames() const;
+
+signals:
+ void renderPassNamesChanged();
+
+private:
+ QString m_renderPassNames;
+};
+
+} // namespace Qt3D
+
+#endif // RENDERPASSFILTER_H
diff --git a/src/render/frontend/shaderprogram.cpp b/src/render/frontend/shaderprogram.cpp
new file mode 100644
index 000000000..e0ef62d2a
--- /dev/null
+++ b/src/render/frontend/shaderprogram.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shaderprogram.h"
+
+#include <QDebug>
+#include <QFile>
+
+namespace Qt3D {
+
+ShaderProgram::ShaderProgram(Node *parent)
+ : Node(parent)
+ , m_vertexSourceFile()
+ , m_fragmentSourceFile()
+ , m_isLoaded(false)
+{
+}
+
+void ShaderProgram::setVertexSourceFile(const QString& vertexSourceFile)
+{
+ if (vertexSourceFile != m_vertexSourceFile) {
+ m_vertexSourceFile = vertexSourceFile;
+ m_isLoaded = false;
+ emit vertexSourceFileChanged();
+ }
+}
+
+QString ShaderProgram::vertexSourceFile() const
+{
+ return m_vertexSourceFile;
+}
+
+void ShaderProgram::setFragmentSourceFile(const QString& fragmentSourceFile)
+{
+ if (fragmentSourceFile != m_fragmentSourceFile) {
+ m_fragmentSourceFile = fragmentSourceFile;
+ m_isLoaded = false;
+ emit fragmentSourceFileChanged();
+ }
+}
+
+QString ShaderProgram::fragmentSourceFile() const
+{
+ return m_fragmentSourceFile;
+}
+
+QByteArray ShaderProgram::vertexSourceCode() const
+{
+ if (!isLoaded())
+ return QByteArray();
+
+ return m_cachedVertexCode;
+}
+
+QByteArray ShaderProgram::fragmentSourceCode() const
+{
+ if (!isLoaded())
+ return QByteArray();
+
+ return m_cachedFragmentCode;
+}
+
+bool ShaderProgram::isLoaded() const
+{
+ return m_isLoaded;
+}
+
+void ShaderProgram::load()
+{
+ if (m_isLoaded)
+ return;
+
+ m_isLoaded = true;
+
+ QFile f(m_fragmentSourceFile);
+ if (!f.exists()) {
+ qWarning() << "couldn't find shader source file:" << m_fragmentSourceFile;
+ return;
+ } else {
+ f.open(QIODevice::ReadOnly);
+ m_cachedFragmentCode = f.readAll();
+ }
+
+ QFile vs(m_vertexSourceFile);
+ if (!vs.exists()) {
+ qWarning() << "couldn't find shader source file:" << m_vertexSourceFile;
+ return;
+ } else {
+ vs.open(QIODevice::ReadOnly);
+ m_cachedVertexCode = vs.readAll();
+ }
+}
+
+} // of namespace Qt3D
+
diff --git a/src/render/frontend/shaderprogram.h b/src/render/frontend/shaderprogram.h
new file mode 100644
index 000000000..3b49fe651
--- /dev/null
+++ b/src/render/frontend/shaderprogram.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHADERPROGRAM_H
+#define SHADERPROGRAM_H
+
+#include <node.h>
+
+namespace Qt3D {
+
+class ShaderProgram : public Node
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString vertexSourceFile READ vertexSourceFile WRITE setVertexSourceFile NOTIFY vertexSourceFileChanged)
+ Q_PROPERTY(QString fragmentSourceFile READ fragmentSourceFile WRITE setFragmentSourceFile NOTIFY fragmentSourceFileChanged)
+
+public:
+ explicit ShaderProgram(Node *parent = 0);
+
+ void setVertexSourceFile(const QString &vertexSourceFile);
+ QString vertexSourceFile() const;
+
+ void setFragmentSourceFile(const QString &fragmentSource);
+ QString fragmentSourceFile() const;
+
+ QByteArray vertexSourceCode() const;
+ QByteArray fragmentSourceCode() const;
+
+ bool isLoaded() const;
+
+ /**
+ * @brief load - call from main / worker thread to do synchronous
+ * loading of shader source files
+ */
+ void load();
+
+signals:
+ void vertexSourceFileChanged();
+ void fragmentSourceFileChanged();
+
+private:
+ QString m_vertexSourceFile;
+ QString m_fragmentSourceFile;
+
+ bool m_sourcesDirty, m_isLoaded;
+ QByteArray m_cachedVertexCode,
+ m_cachedFragmentCode;
+
+};
+
+}
+
+#endif // SHADERPROGRAM_H
diff --git a/src/render/frontend/shape.cpp b/src/render/frontend/shape.cpp
new file mode 100644
index 000000000..5e9fa3c0f
--- /dev/null
+++ b/src/render/frontend/shape.cpp
@@ -0,0 +1,386 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define _USE_MATH_DEFINES // For MSVC
+#include "shape.h"
+
+#include <cmath>
+
+#include <QDebug>
+
+namespace Qt3D {
+
+namespace {
+
+MeshDataPtr createSphereMesh(double radius, int rings, int slices, bool hasTangents)
+{
+ MeshDataPtr mesh(new MeshData(GL_TRIANGLES));
+
+ int nVerts = ( slices + 1 ) * ( rings + 1 ); // One extra line of latitude
+ QByteArray bufferBytes;
+ // vec3 pos, vec2 texCoord, vec3 normal, vec4 tangent
+ quint32 elementSize = 3 + 2 + 3 + (hasTangents ? 4 : 0);
+ quint32 stride = elementSize * sizeof(float);
+ bufferBytes.resize(stride * nVerts);
+
+ float* fptr = reinterpret_cast<float*>(bufferBytes.data());
+
+ const float dTheta = (M_PI * 2) / static_cast<float>( slices );
+ const float dPhi = M_PI / static_cast<float>( rings );
+ const float du = 1.0f / static_cast<float>( slices );
+ const float dv = 1.0f / static_cast<float>( rings );
+
+ // Iterate over latitudes (rings)
+ for ( int lat = 0; lat < rings + 1; ++lat )
+ {
+ const float phi = M_PI_2 - static_cast<float>( lat ) * dPhi;
+ const float cosPhi = cosf( phi );
+ const float sinPhi = sinf( phi );
+ const float v = 1.0f - static_cast<float>( lat ) * dv;
+
+ // Iterate over longitudes (slices)
+ for ( int lon = 0; lon < slices + 1; ++lon )
+ {
+ const float theta = static_cast<float>( lon ) * dTheta;
+ const float cosTheta = cosf( theta );
+ const float sinTheta = sinf( theta );
+ const float u = static_cast<float>( lon ) * du;
+
+ *fptr++ = radius * cosTheta * cosPhi;
+ *fptr++ = radius * sinPhi;
+ *fptr++ = radius * sinTheta * cosPhi;
+
+ *fptr++ = u;
+ *fptr++ = v;
+
+ *fptr++ = cosTheta * cosPhi;
+ *fptr++ = sinPhi;
+ *fptr++ = sinTheta * cosPhi;
+
+ if (hasTangents) {
+ *fptr++ = sinTheta;
+ *fptr++ = 0.0;
+ *fptr++ = -cosTheta;
+ *fptr++ = 1.0;
+ }
+ }
+ }
+
+ BufferPtr buf(new Buffer(QOpenGLBuffer::VertexBuffer));
+ buf->setUsage(QOpenGLBuffer::StaticDraw);
+ buf->setData(bufferBytes);
+
+ mesh->addAttribute("position", new Attribute(buf, GL_FLOAT_VEC3, nVerts, 0, stride));
+ quint32 offset = sizeof(float) * 3;
+
+ mesh->addAttribute("texcoord", new Attribute(buf, GL_FLOAT_VEC2, nVerts, offset, stride));
+ offset += sizeof(float) * 2;
+
+ mesh->addAttribute("normal", new Attribute(buf, GL_FLOAT_VEC3, nVerts, offset, stride));
+ offset += sizeof(float) * 3;
+
+ if (hasTangents) {
+ mesh->addAttribute("tangent", new Attribute(buf, GL_FLOAT_VEC4, nVerts, offset, stride));
+ offset += sizeof(float) * 4;
+ }
+
+ int faces = (slices * 2) * (rings - 1); // two tris per slice, for all middle rings
+ faces += 2 * slices; // tri per slice for both top and bottom
+
+ QByteArray indexBytes;
+ int indices = faces * 3;
+ Q_ASSERT(indices < 65536);
+ indexBytes.resize(indices * sizeof(quint16));
+ quint16* indexPtr = reinterpret_cast<quint16*>(indexBytes.data());
+
+ // top cap
+ {
+ const int nextRingStartIndex = slices + 1;
+ for ( int j = 0; j < slices; ++j )
+ {
+ *indexPtr++ = nextRingStartIndex + j;
+ *indexPtr++ = 0;
+ *indexPtr++ = nextRingStartIndex + j + 1;
+ }
+ }
+
+ for ( int i = 1; i < (rings - 1); ++i )
+ {
+ const int ringStartIndex = i * ( slices + 1 );
+ const int nextRingStartIndex = ( i + 1 ) * ( slices + 1 );
+
+ for ( int j = 0; j < slices; ++j )
+ {
+ // Split the quad into two triangles
+ *indexPtr++ = ringStartIndex + j;
+ *indexPtr++ = ringStartIndex + j + 1;
+ *indexPtr++ = nextRingStartIndex + j;
+ *indexPtr++ = nextRingStartIndex + j;
+ *indexPtr++ = ringStartIndex + j + 1;
+ *indexPtr++ = nextRingStartIndex + j + 1;
+ }
+ }
+
+ // bottom cap
+ {
+ const int ringStartIndex = (rings - 1) * ( slices + 1);
+ const int nextRingStartIndex = (rings) * ( slices + 1);
+ for ( int j = 0; j < slices; ++j )
+ {
+ *indexPtr++ = ringStartIndex + j + 1;
+ *indexPtr++ = nextRingStartIndex;
+ *indexPtr++ = ringStartIndex + j;
+ }
+ }
+
+ BufferPtr indexBuffer(new Buffer(QOpenGLBuffer::IndexBuffer));
+ indexBuffer->setUsage(QOpenGLBuffer::StaticDraw);
+ indexBuffer->setData(indexBytes);
+ mesh->setIndexAttr(AttributePtr(new Attribute(indexBuffer, GL_UNSIGNED_SHORT, indices, 0, 0)));
+
+ mesh->computeBoundsFromAttribute("position");
+ qDebug() << "computed sphere bounds is:" << mesh->boundingBox();
+
+ return mesh;
+}
+
+
+MeshDataPtr createTorusMesh(double radius, double minorRadius,
+ int rings, int sides)
+{
+ MeshDataPtr mesh(new MeshData(GL_TRIANGLES));
+
+ int nVerts = ( sides + 1 ) * ( rings + 1 );
+ QByteArray bufferBytes;
+ // vec3 pos, vec2 texCoord, vec3 normal
+ quint32 elementSize = 3 + 2 + 3;
+ quint32 stride = elementSize * sizeof(float);
+ bufferBytes.resize(stride * nVerts);
+
+ float* fptr = reinterpret_cast<float*>(bufferBytes.data());
+
+ float ringFactor = (M_PI * 2) / static_cast<float>( rings );
+ float sideFactor = (M_PI * 2) / static_cast<float>( sides );
+
+ for ( int ring = 0; ring <= rings; ring++ )
+ {
+ float u = ring * ringFactor;
+ float cu = cos( u );
+ float su = sin( u );
+
+ for ( int side = 0; side < sides; side++ )
+ {
+ float v = side * sideFactor;
+ float cv = cos( v );
+ float sv = sin( v );
+ float r = ( radius + minorRadius * cv );
+
+ *fptr++ = r * cu;
+ *fptr++ = r * su;
+ *fptr++ = minorRadius * sv;
+
+
+ *fptr++ = u / (M_PI * 2);
+ *fptr++ = v / (M_PI * 2);
+
+ QVector3D n(cv * cu * r, cv * su * r, sv * r);
+ n.normalize();
+ *fptr++ = n.x();
+ *fptr++ = n.y();
+ *fptr++ = n.z();
+ }
+ }
+
+ BufferPtr buf(new Buffer(QOpenGLBuffer::VertexBuffer));
+ buf->setUsage(QOpenGLBuffer::StaticDraw);
+ buf->setData(bufferBytes);
+
+ mesh->addAttribute("position", new Attribute(buf, GL_FLOAT_VEC3, nVerts, 0, stride));
+ quint32 offset = sizeof(float) * 3;
+
+ mesh->addAttribute("texcoord", new Attribute(buf, GL_FLOAT_VEC2, nVerts, offset, stride));
+ offset += sizeof(float) * 2;
+
+ mesh->addAttribute("normal", new Attribute(buf, GL_FLOAT_VEC3, nVerts, offset, stride));
+ offset += sizeof(float) * 3;
+
+ QByteArray indexBytes;
+ int faces = (sides * 2) * rings; // two tris per side, for all rings
+ int indices = faces * 3;
+ Q_ASSERT(indices < 65536);
+ indexBytes.resize(indices * sizeof(quint16));
+ quint16* indexPtr = reinterpret_cast<quint16*>(indexBytes.data());
+
+ for ( int ring = 0; ring < rings; ring++ )
+ {
+ int ringStart = ring * sides;
+ int nextRingStart = ( ring + 1 ) * sides;
+ for ( int side = 0; side < sides; side++ )
+ {
+ int nextSide = ( side + 1 ) % sides;
+ *indexPtr++ = ( ringStart + side );
+ *indexPtr++ = ( nextRingStart + side );
+ *indexPtr++ = ( nextRingStart + nextSide );
+ *indexPtr++ = ringStart + side;
+ *indexPtr++ = nextRingStart + nextSide;
+ *indexPtr++ = ( ringStart + nextSide );
+ }
+ }
+
+ BufferPtr indexBuffer(new Buffer(QOpenGLBuffer::IndexBuffer));
+ indexBuffer->setUsage(QOpenGLBuffer::StaticDraw);
+ indexBuffer->setData(indexBytes);
+ mesh->setIndexAttr(AttributePtr(new Attribute(indexBuffer, GL_UNSIGNED_SHORT, indices, 0, 0)));
+
+ mesh->computeBoundsFromAttribute("position");
+
+ return mesh;
+}
+
+} // anonymous namespace
+
+Shape::Shape(Node *parent) :
+ Qt3D::Component(parent),
+ m_generateTangents(false),
+ m_type(ShapeSphere),
+ m_rings(16),
+ m_slices(16),
+ m_radius(1.0),
+ m_minorRadius(1.0)
+{
+}
+
+Shape::ShapeType Shape::type() const
+{
+ return m_type;
+}
+
+MeshDataPtr Shape::data() const
+{
+ if (m_type == ShapeTorus)
+ return createTorusMesh(m_radius, m_minorRadius, m_rings, m_slices);
+
+ return createSphereMesh(m_radius, m_rings, m_slices, m_generateTangents);
+}
+
+int Shape::rings() const
+{
+ return m_rings;
+}
+
+int Shape::slices() const
+{
+ return m_slices;
+}
+
+bool Shape::generateTangents() const
+{
+ return m_generateTangents;
+}
+
+double Shape::radius() const
+{
+ return m_radius;
+}
+
+double Shape::minorRadius() const
+{
+ return m_minorRadius;
+}
+
+void Shape::setType(Shape::ShapeType arg)
+{
+ if (m_type != arg) {
+ m_type = arg;
+ m_rebuildMesh = true;
+ emit typeChanged(arg);
+ }
+}
+
+void Shape::setRings(int arg)
+{
+ if (m_rings == arg)
+ return;
+
+ m_rings = arg;
+ m_rebuildMesh = true;
+ emit shapeChanged();
+}
+
+void Shape::setSlices(int arg)
+{
+ if (m_slices == arg)
+ return;
+
+ m_slices = arg;
+ m_rebuildMesh = true;
+ emit shapeChanged();
+}
+
+void Shape::setGenerateTangents(bool gen)
+{
+ if (m_generateTangents == gen)
+ return;
+
+ m_generateTangents = gen;
+ m_rebuildMesh = true;
+ emit shapeChanged();
+}
+
+void Shape::setRadius(double arg)
+{
+ if (m_radius != arg) {
+ m_radius = arg;
+ m_rebuildMesh = true;
+ emit shapeChanged();
+ }
+}
+
+void Shape::setMinorRadius(double arg)
+{
+ if (m_minorRadius != arg) {
+ m_minorRadius = arg;
+ m_rebuildMesh = true;
+ emit shapeChanged();
+ }
+}
+
+} // namespace Qt3D
diff --git a/src/render/frontend/shape.h b/src/render/frontend/shape.h
new file mode 100644
index 000000000..4207720b5
--- /dev/null
+++ b/src/render/frontend/shape.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_SHAPE_H
+#define QT3D_SHAPE_H
+
+#include <component.h>
+
+#include <meshdata.h>
+
+namespace Qt3D {
+
+class Shape : public Qt3D::Component
+{
+ Q_OBJECT
+
+ Q_ENUMS(ShapeType)
+
+ Q_PROPERTY(ShapeType type READ type WRITE setType NOTIFY typeChanged)
+
+ Q_PROPERTY(bool generateTangents READ generateTangents
+ WRITE setGenerateTangents
+ NOTIFY shapeChanged)
+
+ Q_PROPERTY(int rings READ rings WRITE setRings NOTIFY shapeChanged)
+ Q_PROPERTY(int slices READ slices WRITE setSlices NOTIFY shapeChanged)
+
+ Q_PROPERTY(double radius READ radius WRITE setRadius NOTIFY shapeChanged)
+ Q_PROPERTY(double minorRadius READ minorRadius WRITE setMinorRadius NOTIFY shapeChanged)
+
+public:
+ explicit Shape(Node *parent = 0);
+
+ enum ShapeType
+ {
+ ShapeCube,
+ ShapeSphere,
+ ShapeCylinder,
+ ShapeTorus
+ };
+
+ ShapeType type() const;
+
+ MeshDataPtr data() const;
+
+ int rings() const;
+ int slices() const;
+ bool generateTangents() const;
+ double radius() const;
+ double minorRadius() const;
+
+signals:
+
+ void typeChanged(ShapeType arg);
+ void shapeChanged();
+
+public slots:
+
+ void setType(ShapeType arg);
+ void setRings(int arg);
+ void setSlices(int arg);
+
+ void setGenerateTangents(bool gen);
+
+ void setRadius(double arg);
+ void setMinorRadius(double arg);
+
+private:
+ bool m_rebuildMesh,
+ m_generateTangents;
+ ShapeType m_type;
+ int m_rings,
+ m_slices;
+ double m_radius;
+ double m_minorRadius;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_SHAPE_H
diff --git a/src/render/frontend/tag.h b/src/render/frontend/tag.h
new file mode 100644
index 000000000..7dc4b7dc4
--- /dev/null
+++ b/src/render/frontend/tag.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TAG_H
+#define TAG_H
+
+#include <QDebug>
+
+#include <qt3dcore_global.h>
+#include <node.h>
+
+namespace Qt3D {
+
+class QT3DCORESHARED_EXPORT Tag : public Node
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ Tag(Node *parent = 0)
+ : Node(parent)
+ , m_name()
+ , m_value()
+ {}
+
+ void setName( const QString& name )
+ {
+ if (name != m_name) {
+ m_name = name;
+ emit nameChanged();
+ }
+ }
+
+ QString name() const { return m_name; }
+
+ void setValue( const QVariant& value )
+ {
+ if (value != m_value) {
+ m_value = value;
+ emit valueChanged();
+ }
+ }
+
+ QVariant value() const { return m_value; }
+
+signals:
+ void nameChanged();
+ void valueChanged();
+
+private:
+ QString m_name;
+ QVariant m_value;
+};
+
+} // namespace Qt3D
+
+#endif // TAG_H
diff --git a/src/render/frontend/technique.cpp b/src/render/frontend/technique.cpp
new file mode 100644
index 000000000..5779e8f10
--- /dev/null
+++ b/src/render/frontend/technique.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "technique.h"
+
+#include <QDebug>
+#include <QOpenGLContext>
+
+namespace Qt3D {
+
+Technique::Technique(Node *parent)
+ : Node(parent)
+{
+}
+
+QQmlListProperty<Qt3D::Tag> Technique::tags()
+{
+ return QQmlListProperty<Qt3D::Tag>(this, 0,
+ &Technique::appendTag,
+ &Technique::tagCount,
+ &Technique::tagAt,
+ &Technique::clearTags );
+}
+
+void Technique::addTag(const QString &name, const QVariant &value)
+{
+ Tag *tag = new Tag(this);
+ tag->setName(name);
+ tag->setValue(value);
+ m_tags.insert(name, tag);
+ m_tagList.append(tag);
+ emit tagsChanged();
+}
+
+void Technique::removeTag(const QString &name)
+{
+ Tag *tag = m_tags.value(name);
+ m_tags.remove(name);
+ m_tagList.removeOne(tag);
+ if (tag) {
+ delete tag;
+ emit tagsChanged();
+ }
+}
+
+void Technique::setTagValue(const QString &name, const QVariant &value)
+{
+ Tag *tag = m_tags.value(name);
+ if (tag)
+ tag->setValue(value);
+}
+
+QVariant Technique::tagValue(const QString &name) const
+{
+ return m_tags.value(name)->value();
+}
+
+bool Technique::containsTag(const QString &name) const
+{
+ return m_tags.contains(name);
+}
+
+void Technique::addPass(RenderPass *pass)
+{
+ Q_ASSERT(pass);
+ pass->setParent(this);
+ m_renderPasses.append(pass);
+ emit renderPassesChanged();
+}
+
+QList<RenderPass *> Technique::renderPasses() const
+{
+ return m_renderPasses;
+}
+
+void Technique::appendTag(QQmlListProperty<Tag> *list, Tag *tag)
+{
+ Technique *technique = qobject_cast<Technique *>(list->object);
+ if (technique) {
+ tag->setParent(technique);
+ technique->m_tags.insert(tag->name(), tag);
+ technique->m_tagList.append(tag);
+ emit technique->tagsChanged();
+ }
+}
+
+Tag *Technique::tagAt(QQmlListProperty<Tag> *list, int index)
+{
+ Technique *technique = qobject_cast<Technique *>(list->object);
+ if (technique)
+ return technique->m_tagList.value(index);
+ return 0;
+}
+
+int Technique::tagCount(QQmlListProperty<Tag> *list)
+{
+ Technique *technique = qobject_cast<Technique *>(list->object);
+ if (technique)
+ return technique->m_tagList.size();
+ return 0;
+}
+
+void Technique::clearTags(QQmlListProperty<Tag> *list)
+{
+ Technique *technique = qobject_cast<Technique *>(list->object);
+ if (technique) {
+ technique->m_tags.clear();
+ technique->m_tagList.clear();
+ emit technique->tagsChanged();
+ }
+}
+
+QQmlListProperty<Qt3D::RenderPass> Technique::renderPassList()
+{
+ return QQmlListProperty<Qt3D::RenderPass>(this, 0,
+ &Technique::appendRenderPass,
+ &Technique::renderPassCount,
+ &Technique::renderPassAt,
+ &Technique::clearRenderPasses);
+}
+
+void Technique::addParameter(Parameter *p)
+{
+ Q_CHECK_PTR(p);
+ m_parameters.append(p);
+}
+
+Parameter *Technique::parameterByName(QString name) const
+{
+ foreach (Parameter* p, m_parameters) {
+ if (p->name() == name)
+ return p;
+ }
+
+ return NULL;
+}
+
+void Technique::appendRenderPass(QQmlListProperty<RenderPass> *list, RenderPass *renderPass)
+{
+ Technique *technique = qobject_cast<Technique *>(list->object);
+ if (technique) {
+ technique->addPass(renderPass);
+ }
+}
+
+RenderPass *Technique::renderPassAt(QQmlListProperty<RenderPass> *list, int index)
+{
+ Technique *technique = qobject_cast<Technique *>(list->object);
+ if (technique)
+ return technique->m_renderPasses.value(index);
+ return 0;
+}
+
+int Technique::renderPassCount(QQmlListProperty<RenderPass> *list)
+{
+ Technique *technique = qobject_cast<Technique *>(list->object);
+ if (technique)
+ return technique->m_renderPasses.size();
+ return 0;
+}
+
+void Technique::clearRenderPasses(QQmlListProperty<RenderPass> *list)
+{
+ Technique *technique = qobject_cast<Technique *>(list->object);
+ if (technique) {
+ technique->m_renderPasses.clear();
+ emit technique->renderPassesChanged();
+ }
+}
+
+Parameter::Parameter(QObject *parent, QString name, int ty) :
+ QObject(parent),
+ m_name(name),
+ m_type(ty),
+ m_standardUniform(None)
+{
+
+}
+
+void Parameter::setMeshAttributeName(QString name)
+{
+ m_meshName = name;
+}
+
+bool Parameter::isStandardUniform() const
+{
+ return (m_standardUniform != None);
+}
+
+void Parameter::setStandardUniform(Parameter::StandardUniform su)
+{
+ m_standardUniform = su;
+}
+
+Parameter::StandardUniform Parameter::standardUniform() const
+{
+ return m_standardUniform;
+}
+
+bool Parameter::isTextureType() const
+{
+ switch (m_type) {
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+Render::QUniformValue::Type Parameter::uniformType() const
+{
+ switch (m_type) {
+ case GL_BOOL:
+ case GL_BOOL_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ return Render::QUniformValue::Bool;
+
+ // integers!
+
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ case GL_FLOAT_MAT4:
+ return Render::QUniformValue::Float;
+
+ case GL_DOUBLE:
+ case GL_DOUBLE_VEC2:
+ case GL_DOUBLE_VEC3:
+ case GL_DOUBLE_VEC4:
+ return Render::QUniformValue::Double;
+
+ default:
+ qWarning() << Q_FUNC_INFO << "couldn't map datatype:" << QString::number(m_type, 16);
+ return Render::QUniformValue::Invalid;
+ }
+}
+
+} // of namespace Qt3D
diff --git a/src/render/frontend/technique.h b/src/render/frontend/technique.h
new file mode 100644
index 000000000..f4050eb3e
--- /dev/null
+++ b/src/render/frontend/technique.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TECHNIQUE_H
+#define TECHNIQUE_H
+
+#include <qt3dcore_global.h>
+#include <node.h>
+
+#include "tag.h"
+#include "renderpass.h"
+
+#include <QList>
+#include <QMap>
+#include <QQmlListProperty>
+#include <QSharedPointer>
+
+// FIXME - move enum somewhere common so don't need to include this here
+#include <quniformvalue.h>
+
+namespace Qt3D {
+
+class QT3DCORESHARED_EXPORT Parameter : public QObject
+{
+ Q_OBJECT
+
+public:
+ // FIXME - sort this by frequency, to minimize the size of the
+ // vector in RenderShader. (We want to use compact storage, but we index
+ // by this enum, and resize to the largest value)
+ enum StandardUniform
+ {
+ None = -1,
+
+ ModelMatrix = 0,
+ ViewMatrix,
+ ProjectionMatrix,
+ ModelView,
+ ModelViewProjection,
+
+ ModelInverse,
+ ViewInverse,
+ ProjectionInverse,
+ ModelViewInverse,
+ ModelViewProjectionInverse,
+
+ ModelNormal,
+ ModelViewNormal
+ };
+
+ Parameter(QObject* parent, QString name, int ty);
+
+ QString name() const
+ { return m_name; }
+
+ // permit one extra level of indrection in mesh naming of
+ // attributes (glTf at least does this)
+ void setMeshAttributeName(QString name);
+ QString meshAttributeName() const
+ { return m_meshName; }
+
+ bool isStandardUniform() const;
+
+ void setStandardUniform(StandardUniform su);
+ StandardUniform standardUniform() const;
+
+ /**
+ * @brief setDefaultValue - for non-texture uniform parameters
+ * @param dv
+ */
+ void setDefaultValue(QVariant dv);
+
+ // setUniformValue();
+
+ QVariant value() const;
+
+ int datatype() const
+ { return m_type; }
+
+ bool isTextureType() const;
+
+ /**
+ * @brief uniformType - map the data type to the primitive uniform type
+ * @return
+ */
+ Render::QUniformValue::Type uniformType() const;
+signals:
+ void valueChanged();
+
+private:
+ QString m_name;
+ int m_type;
+ QVariant m_value;
+ QVariant m_defaultValue;
+ QString m_meshName;
+ StandardUniform m_standardUniform;
+};
+
+class QT3DCORESHARED_EXPORT Technique : public Node
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQmlListProperty<Qt3D::Tag> tags READ tags NOTIFY tagsChanged)
+ Q_PROPERTY(QQmlListProperty<Qt3D::RenderPass> renderPasses READ renderPassList NOTIFY renderPassesChanged)
+
+public:
+ explicit Technique(Node *parent = 0);
+
+ QQmlListProperty<Qt3D::Tag> tags();
+ void addTag( const QString& name, const QVariant& value );
+ void removeTag( const QString& name );
+ void setTagValue( const QString& name, const QVariant& value );
+ QVariant tagValue( const QString& name ) const;
+ bool containsTag( const QString& name ) const;
+
+
+ void addPass(RenderPass* pass);
+ QList<RenderPass *> renderPasses() const;
+
+ QQmlListProperty<Qt3D::RenderPass> renderPassList();
+
+
+
+ // QQmlListProperty<Qt3D::Parameter> parameters();
+
+ void addParameter(Parameter* p);
+ QList<Parameter *> parameters() const
+ { return m_parameters; }
+
+ Parameter* parameterByName(QString name) const;
+signals:
+ void tagsChanged();
+ void renderPassesChanged();
+
+private:
+ static void appendTag(QQmlListProperty<Tag> *list, Tag *bar);
+ static Tag *tagAt(QQmlListProperty<Tag> *list, int index);
+ static int tagCount(QQmlListProperty<Tag> *list);
+ static void clearTags(QQmlListProperty<Tag> *list);
+
+ static void appendRenderPass(QQmlListProperty<RenderPass> *list, RenderPass* renderPass);
+ static RenderPass *renderPassAt(QQmlListProperty<RenderPass> *list, int index);
+ static int renderPassCount(QQmlListProperty<RenderPass> *list);
+ static void clearRenderPasses( QQmlListProperty<RenderPass> *list);
+
+ QList<Tag *> m_tagList;
+ QMap<QString, Tag *> m_tags;
+
+ QList<Parameter *> m_parameters;
+
+ QList<RenderPass *> m_renderPasses;
+};
+
+}
+
+#endif // TECHNIQUE_H
diff --git a/src/render/frontend/techniquefilter.cpp b/src/render/frontend/techniquefilter.cpp
new file mode 100644
index 000000000..038fa51f1
--- /dev/null
+++ b/src/render/frontend/techniquefilter.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "techniquefilter.h"
+
+namespace Qt3D {
+
+TechniqueFilter::TechniqueFilter(Node *parent)
+ : Qt3D::Component(parent)
+{
+}
+
+QQmlListProperty<Qt3D::Tag> TechniqueFilter::tags()
+{
+ return QQmlListProperty<Qt3D::Tag>(this, 0,
+ &TechniqueFilter::appendTag,
+ &TechniqueFilter::tagCount,
+ &TechniqueFilter::tagAt,
+ &TechniqueFilter::clearTags);
+}
+
+void TechniqueFilter::appendTag(QQmlListProperty<Tag> *list, Tag *tag)
+{
+ TechniqueFilter *filter = qobject_cast<TechniqueFilter *>(list->object);
+ if (filter) {
+ tag->setParent(filter);
+ filter->m_tagList.append(tag);
+ emit filter->tagsChanged();
+ }
+}
+
+Tag *TechniqueFilter::tagAt(QQmlListProperty<Tag> *list, int index)
+{
+ TechniqueFilter *filter = qobject_cast<TechniqueFilter *>(list->object);
+ if (filter)
+ return filter->m_tagList.value(index);
+ return 0;
+}
+
+int TechniqueFilter::tagCount(QQmlListProperty<Tag> *list)
+{
+ TechniqueFilter *filter = qobject_cast<TechniqueFilter *>(list->object);
+ if (filter)
+ return filter->m_tagList.size();
+ return 0;
+}
+
+void TechniqueFilter::clearTags(QQmlListProperty<Tag> *list)
+{
+ TechniqueFilter *filter = qobject_cast<TechniqueFilter *>(list->object);
+ if (filter) {
+ filter->m_tagList.clear();
+ emit filter->tagsChanged();
+ }
+}
+
+} // namespace Qt3D
diff --git a/src/render/frontend/techniquefilter.h b/src/render/frontend/techniquefilter.h
new file mode 100644
index 000000000..102f68a1d
--- /dev/null
+++ b/src/render/frontend/techniquefilter.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_TECHNIQUEFILTER_H
+#define QT3D_TECHNIQUEFILTER_H
+
+#include <qt3dcore_global.h>
+#include <component.h>
+
+#include "tag.h"
+
+#include <QQmlListProperty>
+
+namespace Qt3D {
+
+class TechniqueFilter : public Qt3D::Component
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQmlListProperty<Qt3D::Tag> tags READ tags NOTIFY tagsChanged)
+ Q_CLASSINFO("DefaultProperty", "tags")
+
+public:
+ explicit TechniqueFilter(Node *parent = 0);
+
+ QQmlListProperty<Qt3D::Tag> tags();
+
+signals:
+ void tagsChanged();
+
+private:
+ static void appendTag(QQmlListProperty<Tag> *list, Tag *bar);
+ static Tag *tagAt(QQmlListProperty<Tag> *list, int index);
+ static int tagCount(QQmlListProperty<Tag> *list);
+ static void clearTags(QQmlListProperty<Tag> *list);
+
+ QList<Tag *> m_tagList;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_TECHNIQUEFILTER_H
diff --git a/src/render/frontend/texture.cpp b/src/render/frontend/texture.cpp
new file mode 100644
index 000000000..81c1be5f9
--- /dev/null
+++ b/src/render/frontend/texture.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "texture.h"
+
+#include <texturedata.h>
+
+#include <QImage>
+#include <QDebug>
+
+namespace Qt3D {
+
+QmlTexture::QmlTexture(Node *parent) :
+ Node(parent),
+ m_texture(new Texture)
+{
+ m_texture->setTarget(QOpenGLTexture::Target2D);
+ m_texture->setInternalFormat(QOpenGLTexture::RGBA8_UNorm);
+}
+
+QUrl QmlTexture::source() const
+{
+ return m_source;
+}
+
+bool QmlTexture::isRectangle() const
+{
+ return (m_texture->target() == QOpenGLTexture::TargetRectangle);
+}
+
+Texture *QmlTexture::texture() const
+{
+ return m_texture;
+}
+
+void QmlTexture::setSource(QUrl arg)
+{
+ if (m_source != arg) {
+ m_source = arg;
+
+ if (m_source.isLocalFile()) {
+ QImage img(m_source.toLocalFile());
+ m_texture->setInternalFormat(img.hasAlphaChannel() ?
+ QOpenGLTexture::RGBA8_UNorm :
+ QOpenGLTexture::RGB8_UNorm);
+
+ m_texture->setFromQImage(img);
+ } else {
+ qWarning() << "implement loading from remote URLs";
+ }
+
+ emit sourceChanged();
+ }
+}
+
+void QmlTexture::setRectangle(bool r)
+{
+ m_texture->setTarget(r ? QOpenGLTexture::TargetRectangle :
+ QOpenGLTexture::Target2D);
+}
+
+
+} // namespace Qt3D
diff --git a/src/render/frontend/texture.h b/src/render/frontend/texture.h
new file mode 100644
index 000000000..910f66aca
--- /dev/null
+++ b/src/render/frontend/texture.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_TEXTURE_H
+#define QT3D_TEXTURE_H
+
+#include "node.h"
+
+#include <QUrl>
+
+namespace Qt3D {
+
+class Texture;
+
+class QmlTexture : public Node
+{
+ Q_OBJECT
+public:
+ explicit QmlTexture(Node *parent = 0);
+
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(bool rectangle READ isRectangle WRITE setRectangle NOTIFY formatChanged)
+
+ QUrl source() const;
+
+ bool isRectangle() const;
+
+ Texture* texture() const;
+signals:
+ void sourceChanged();
+ void formatChanged();
+
+public slots:
+
+
+ void setSource(QUrl arg);
+
+ void setRectangle(bool r);
+
+private:
+ Texture* m_texture;
+
+ QUrl m_source;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_TEXTURE_H
diff --git a/src/render/frontend/transform.cpp b/src/render/frontend/transform.cpp
new file mode 100644
index 000000000..5ac195dc3
--- /dev/null
+++ b/src/render/frontend/transform.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "transform.h"
+
+#include <matrixtransform.h>
+
+namespace Qt3D {
+
+Transform::Transform(Node *parent)
+ : Qt3D::Component(parent)
+{
+}
+
+QQmlListProperty<AbstractTransform> Transform::transformList()
+{
+ return QQmlListProperty<AbstractTransform>(this, 0,
+ Transform::qmlAppendTransform,
+ Transform::transformCount,
+ Transform::transformAt,
+ Transform::qmlClearTransforms);
+}
+
+QMatrix4x4 Transform::matrix() const
+{
+ if (m_transformsDirty) {
+ m_matrix = applyTransforms();
+ m_transformsDirty = false;
+ }
+ return m_matrix;
+}
+
+void Transform::setMatrix(const QMatrix4x4 &m)
+{
+ qDeleteAll(m_transforms);
+ m_transforms.clear();
+ appendTransfrom(new MatrixTransform(m));
+}
+
+/*!
+ The center of rotation for the entity. Defaults to the local origin.
+*/
+QVector3D Transform::rotationCenter() const
+{
+ return QVector3D();
+}
+
+QList<AbstractTransform *> Transform::transforms() const
+{
+ return m_transforms;
+}
+
+void Transform::setRotationCenter(const QVector3D &rc)
+{
+ Q_UNUSED(rc);
+}
+
+void Transform::appendTransfrom(AbstractTransform *xform)
+{
+ m_transformsDirty = true;
+ m_transforms.append( xform );
+}
+
+void Transform::removeTransform(AbstractTransform *xform)
+{
+ m_transformsDirty = true;
+ m_transforms.removeOne( xform );
+}
+
+QMatrix4x4 Transform::applyTransforms() const
+{
+ QMatrix4x4 m;
+ m.setToIdentity();
+ Q_FOREACH (AbstractTransform *t, m_transforms)
+ m = t->matrix() * m;
+ return m;
+}
+
+
+void Transform::qmlAppendTransform(QQmlListProperty<AbstractTransform> *list, AbstractTransform *obj )
+{
+ if ( !obj )
+ return;
+
+ Transform *self = static_cast<Transform *>(list->object);
+ self->appendTransfrom(obj);
+}
+
+AbstractTransform* Transform::transformAt(QQmlListProperty<AbstractTransform> *list, int index)
+{
+ Transform *self = static_cast<Transform *>(list->object);
+ return self->transforms().at(index);
+}
+
+int Transform::transformCount(QQmlListProperty<AbstractTransform> *list)
+{
+ Transform *self = static_cast<Transform *>(list->object);
+ return self->transforms().count();
+}
+
+void Transform::qmlClearTransforms(QQmlListProperty<AbstractTransform> *list)
+{
+ Transform *self = static_cast<Transform *>(list->object);
+ qDeleteAll(self->m_transforms);
+ self->m_transforms.clear();
+ self->m_transformsDirty = true;
+}
+
+} // namespace Qt3D
diff --git a/src/render/frontend/transform.h b/src/render/frontend/transform.h
new file mode 100644
index 000000000..65cbadb35
--- /dev/null
+++ b/src/render/frontend/transform.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_TRANSFORM_H
+#define QT3D_TRANSFORM_H
+
+#include <component.h>
+
+#include <QMatrix4x4>
+
+namespace Qt3D {
+
+class AbstractTransform;
+
+class Transform : public Qt3D::Component
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Qt3D::AbstractTransform> transforms READ transformList)
+ Q_CLASSINFO("DefaultProperty", "transforms")
+
+public:
+ explicit Transform(Node *parent = 0);
+
+ QMatrix4x4 matrix() const;
+ void setMatrix(const QMatrix4x4 &m);
+
+ QVector3D rotationCenter() const;
+ void setRotationCenter(const QVector3D &rc);
+
+ QList<AbstractTransform*> transforms() const;
+
+ // void insertTransformAt(...)
+ Q_INVOKABLE void appendTransfrom(AbstractTransform *xform);
+ Q_INVOKABLE void removeTransform(AbstractTransform *xform);
+
+ QQmlListProperty<Qt3D::AbstractTransform> transformList();
+
+private:
+ QMatrix4x4 applyTransforms() const;
+
+ static void qmlAppendTransform(QQmlListProperty<Qt3D::AbstractTransform> *list, Qt3D::AbstractTransform *bar);
+ static AbstractTransform* transformAt(QQmlListProperty<Qt3D::AbstractTransform> *list, int index);
+ static int transformCount(QQmlListProperty<Qt3D::AbstractTransform> *list);
+ static void qmlClearTransforms(QQmlListProperty<Qt3D::AbstractTransform> *list);
+
+ mutable bool m_transformsDirty;
+ bool m_visible;
+ QList<AbstractTransform*> m_transforms;
+
+ mutable QMatrix4x4 m_matrix;
+ QMatrix4x4 m_sceneMatrix;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_TRANSFORM_H
diff --git a/src/render/frontend/viewport.cpp b/src/render/frontend/viewport.cpp
new file mode 100644
index 000000000..8c13190a1
--- /dev/null
+++ b/src/render/frontend/viewport.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "viewport.h"
+
+namespace Qt3D {
+
+Viewport::Viewport(Node *parent)
+ : Component(parent)
+{
+}
+
+QRectF Viewport::rect() const
+{
+ return m_rect;
+}
+
+void Viewport::setRect(const QRectF &rect)
+{
+ if (m_rect != rect) {
+ m_rect = rect;
+ emit rectChanged( rect );
+ }
+}
+
+}
diff --git a/src/render/frontend/viewport.h b/src/render/frontend/viewport.h
new file mode 100644
index 000000000..7a420d108
--- /dev/null
+++ b/src/render/frontend/viewport.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIEWPORT_H
+#define VIEWPORT_H
+
+#include <qt3dcore_global.h>
+
+#include <component.h>
+
+#include <QRectF>
+
+namespace Qt3D {
+
+class Viewport : public Component
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QRectF rect READ rect WRITE setRect NOTIFY rectChanged)
+
+public:
+ explicit Viewport(Node *parent = 0);
+
+ QRectF rect() const;
+
+public slots:
+ void setRect( const QRectF& rect );
+
+signals:
+ void rectChanged( const QRectF& arg );
+
+private:
+ QRectF m_rect;
+};
+
+}
+
+#endif // VIEWPORT_H
diff --git a/src/render/io/gltfparser.cpp b/src/render/io/gltfparser.cpp
new file mode 100644
index 000000000..67bd83960
--- /dev/null
+++ b/src/render/io/gltfparser.cpp
@@ -0,0 +1,842 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gltfparser.h"
+
+#include "texturedata.h"
+
+#include <entity.h>
+#include <mesh.h>
+#include <material.h>
+#include <technique.h>
+#include <shaderprogram.h>
+#include <effect.h>
+#include <camera.h>
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QFile>
+#include <QDir>
+#include <QFileInfo>
+#include <QQuaternion>
+#include <QMatrix4x4>
+#include <QColor>
+#include <QVector2D>
+#include <QVector3D>
+
+// need to move these to somewhere common?
+#include <drawstate.h>
+#include <states/blendstate.h>
+
+namespace Qt3D {
+
+namespace
+{
+
+Parameter::StandardUniform parseSemanticName(QString s)
+{
+ if (s == "MODEL") return Parameter::ModelMatrix;
+ if (s == "VIEW") return Parameter::ViewMatrix;
+ if (s == "PROJECTION") return Parameter::ProjectionMatrix;
+ if (s == "MODELVIEW") return Parameter::ModelView;
+ if (s == "MODELVIEWPROJECTION")
+ return Parameter::ModelViewProjection;
+
+ if (s == "MODELINVERSE") return Parameter::ModelInverse;
+ if (s == "VIEWINVERSE") return Parameter::ViewInverse;
+ if (s == "PROJECTIONINVERSE")
+ return Parameter::ProjectionInverse;
+ if (s == "MODELVIEWINVERSE")
+ return Parameter::ModelViewInverse;
+ if (s == "MODELVIEWPROJECTIONINVERSE")
+ return Parameter::ModelViewProjectionInverse;
+
+ if (s == "MODELINVERSETRANSPOSE")
+ return Parameter::ModelNormal;
+ if (s == "MODELVIEWINVERSETRANSPOSE")
+ return Parameter::ModelViewNormal;
+
+ return Parameter::None;
+}
+
+} // of anonymous namespace
+
+GLTFParser::GLTFParser() :
+ m_parseDone(false)
+{
+}
+
+bool GLTFParser::isGLTFPath(QString path)
+{
+ QFileInfo finfo(path);
+ if (!finfo.exists())
+ return false;
+
+ // might need to detect other things in the future, but would
+ // prefer to avoid doing a full parse.
+ return (finfo.suffix().toLower() == "json");
+}
+
+void GLTFParser::setFilePath(QString path)
+{
+ QFileInfo finfo(path);
+ if (!finfo.exists()) {
+ qWarning() << "missing file:" << path;
+ return;
+ }
+
+ QFile f(path);
+ f.open(QIODevice::ReadOnly);
+
+ if (!setJSON(QJsonDocument::fromJson(f.readAll()))) {
+ qWarning() << "not a JSON document";
+ return;
+ }
+
+ setBasePath(finfo.dir().absolutePath());
+}
+
+void GLTFParser::setBasePath(QString path)
+{
+ m_basePath = path;
+}
+
+bool GLTFParser::setJSON( QJsonDocument json )
+{
+ if ( !json.isObject() ) {
+ return false;
+ }
+
+ m_json = json;
+ m_parseDone = false;
+
+ m_meshDict.clear();
+ m_attributeDict.clear();
+ m_defaultScene.clear();
+
+ return true;
+}
+
+MeshDataPtr GLTFParser::mesh(QString id)
+{
+ parse();
+ if (m_meshDict.contains(id))
+ return m_meshDict.value(id);
+
+ qWarning() << "Unknown mesh" << id << "in GLTF file" << m_basePath;
+ return MeshDataPtr();
+}
+
+Entity* GLTFParser::defaultScene()
+{
+ parse();
+ if (m_defaultScene.isEmpty()) {
+ qWarning() << Q_FUNC_INFO << "no default scene";
+ return NULL;
+ }
+
+ return scene(m_defaultScene);
+}
+
+Entity* GLTFParser::scene(QString id)
+{
+ parse();
+
+ QJsonObject scenes = m_json.object().value("scenes").toObject();
+ if (!scenes.contains(id)) {
+ qWarning() << "GLTF: no such scene" << id << "in file" << m_basePath;
+ return NULL;
+ }
+
+ QJsonObject sceneObj = scenes.value(id).toObject();
+ Entity* sceneEntity = new Entity;
+ foreach (QJsonValue nnv, sceneObj.value("nodes").toArray()) {
+ QString nodeName = nnv.toString();
+ Entity* child = node(nodeName);
+ if (!child)
+ continue;
+
+ sceneEntity->addChild(child);
+ }
+
+ return sceneEntity;
+}
+
+Entity* GLTFParser::node(QString id)
+{
+ QJsonObject nodes = m_json.object().value("nodes").toObject();
+ if (!nodes.contains(id)) {
+ qWarning() << "unknown node" << id << "in GLTF file" << m_basePath;
+ return NULL;
+ }
+
+ QJsonObject jsonObj = nodes.value(id).toObject();
+ Entity* result( new Entity );
+ parse();
+
+ if ( jsonObj.contains( "children" ) )
+ {
+ foreach (QJsonValue c, jsonObj.value( "children" ).toArray()) {
+ Entity* child = node(c.toString());
+ if (!child)
+ continue;
+ result->addChild(child);
+ }
+ }
+
+ if ( jsonObj.contains( "meshes") )
+ {
+ typedef QList<Mesh*> MeshList;
+ QMap<QString, MeshList> materialDict;
+
+ foreach (QJsonValue m, jsonObj.value( "meshes" ).toArray())
+ {
+ if (!m_meshDict.contains(m.toString())) {
+ qWarning() << "node" << id << "references unknown mesh" << m.toString();
+ continue;
+ }
+
+ foreach (MeshDataPtr md, m_meshDict.values(m.toString())) {
+ QString matId = m_meshMaterialDict[md.data()];
+ Mesh* meshComp = new Mesh;
+ meshComp->setData(md);
+ materialDict[matId].append(meshComp);
+ }
+ }
+
+ if (materialDict.size() == 1) {
+ // common case
+ result->addComponent(material(materialDict.firstKey()));
+ foreach (Mesh* m, materialDict.first())
+ result->addComponent(m);
+ } else {
+ // need to make a child entity per material
+ foreach (QString matId, materialDict.keys()) {
+ Entity* subEntity(new Entity);
+ result->addChild(subEntity);
+
+ subEntity->addComponent(material(matId));
+ foreach (Mesh* m, materialDict.value(matId))
+ subEntity->addComponent(m);
+ } // of distinct material iteration
+ } // of multiple materials case
+ }
+
+ processName(jsonObj, result);
+
+ if ( jsonObj.contains( "matrix") )
+ {
+ QMatrix4x4 m;
+ QJsonArray matrixValues = jsonObj.value( "matrix" ).toArray();
+
+ for (int i=0; i<16; ++i) {
+ double v = matrixValues.at( i ).toDouble();
+ m(i % 4, i >> 2) = v;
+ }
+
+ result->setMatrix( m );
+ }
+
+ if ( jsonObj.contains( "camera") )
+ {
+ Camera* cam = camera( jsonObj.value("camera").toString() );
+ if (!cam) {
+ qWarning() << "failed to build camera:" << jsonObj.value("camera")
+ << "on node" << id;
+ } else {
+ result->addComponent(cam);
+ }
+ } // of have camera attribute
+
+ return result;
+}
+
+// Get rid of miniwindef.h clobbering legal variable names
+#if defined(near)
+#undef near
+#endif
+
+#if defined(far)
+#undef far
+#endif
+
+Camera* GLTFParser::camera(QString id)
+{
+ parse();
+ QJsonObject cams = m_json.object().value("cameras").toObject();
+ if (!cams.contains(id)) {
+ qWarning() << "unknown camera" << id << "in GLTF file" << m_basePath;
+ return NULL;
+ }
+
+ QJsonObject jsonObj = cams.value(id).toObject();
+ QString camTy = jsonObj.value("type").toString();
+
+ if (camTy == "perspective") {
+ if (!jsonObj.contains("perspective")) {
+ qWarning() << "camera:" << id << "missing 'perspective' object";
+ return NULL;
+ }
+
+ QJsonObject pObj = jsonObj.value("perspective").toObject();
+ double yfov = pObj.value("yfov").toDouble();
+ double near = pObj.value("znear").toDouble();
+ double far = pObj.value("zfar").toDouble();
+
+ Camera* result = new Camera;
+ result->setPerspectiveProjection(yfov, 1.0, near, far);
+ return result;
+ } else if (camTy == "orthographic") {
+ qWarning() << Q_FUNC_INFO << "implement me";
+
+ return NULL;
+ } else {
+ qWarning() << "camera:" << id << "has unsupported type:" << camTy;
+ return NULL;
+ }
+}
+
+Material* GLTFParser::material(QString id)
+{
+ parse();
+
+ if (m_materialCache.contains(id))
+ return m_materialCache.value(id);
+
+ QJsonObject mats = m_json.object().value("materials").toObject();
+ if (!mats.contains(id)) {
+ qWarning() << "unknown material" << id << "in GLTF file" << m_basePath;
+ return NULL;
+ }
+
+ QJsonObject jsonObj = mats.value(id).toObject();
+
+ QJsonObject tech = jsonObj.value("instanceTechnique").toObject();
+ QString tname = tech.value("technique").toString();
+ if (!m_techniques.contains(tname)) {
+ qWarning() << "unknown technique" << tname <<
+ "for material" << id << "in GLTF file" << m_basePath;
+ return NULL;
+ }
+
+ Technique *technique = m_techniques.value(tname);
+ if (!m_effectProxies.contains(tname)) {
+ Effect* eff = new Effect;
+ eff->setObjectName(tname);
+ eff->addTechnique(technique);
+ m_effectProxies[tname] = eff;
+ }
+
+ Material* mat = new Material;
+ mat->setEffect(m_effectProxies[tname]);
+
+ processName(jsonObj, mat);
+
+ QJsonObject values = tech.value("values").toObject();
+ foreach (QString vName, values.keys()) {
+ Parameter* param = technique->parameterByName(vName);
+ if (!param) {
+ qWarning() << "unknown parameter:" << vName << "in technique" << tname
+ << "processing material" << id;
+ continue;
+ }
+
+ if (param->isTextureType()) {
+ QString textureId = values.value(vName).toString();
+ if (!m_textures.contains(textureId)) {
+ qWarning() << "unknown texture" << textureId << "for parameter" << vName
+ << "of material" << id;
+ } else {
+ mat->setTextureParameter(vName, m_textures.value(textureId));
+ }
+ } else {
+ QVariant var = parameterValueFromJSON(param, values.value(vName));
+ mat->setParameter(vName, var);
+ }
+ } // of material technique-instance values iteration
+
+ m_materialCache[id] = mat;
+ return mat;
+}
+
+void GLTFParser::parse()
+{
+ if (m_parseDone)
+ return;
+
+ QJsonObject buffers = m_json.object().value("buffers").toObject();
+ foreach (QString nm, buffers.keys()) {
+ processJSONBuffer( nm, buffers.value(nm).toObject() );
+ }
+
+ QJsonObject views = m_json.object().value("bufferViews").toObject();
+ foreach (QString nm, views.keys()) {
+ processJSONBufferView( nm, views.value(nm).toObject() );
+ }
+
+ QJsonObject shaders = m_json.object().value("shaders").toObject();
+ foreach (QString nm, shaders.keys()) {
+ processJSONShader( nm, shaders.value(nm).toObject() );
+ }
+
+ QJsonObject programs = m_json.object().value("programs").toObject();
+ foreach (QString nm, programs.keys()) {
+ processJSONProgram( nm, programs.value(nm).toObject() );
+ }
+
+ QJsonObject techniques = m_json.object().value("techniques").toObject();
+ foreach (QString nm, techniques.keys()) {
+ processJSONTechnique( nm, techniques.value(nm).toObject() );
+ }
+
+ QJsonObject attrs = m_json.object().value("accessors").toObject();
+ foreach (QString nm, attrs.keys()) {
+ processJSONAccessor( nm, attrs.value(nm).toObject() );
+ }
+
+ QJsonObject meshes = m_json.object().value("meshes").toObject();
+ foreach (QString nm, meshes.keys()) {
+ processJSONMesh( nm, meshes.value(nm).toObject() );
+ }
+
+ QJsonObject images = m_json.object().value("images").toObject();
+ foreach (QString nm, images.keys()) {
+ processJSONImage( nm, images.value(nm).toObject() );
+ }
+
+ QJsonObject textures = m_json.object().value("textures").toObject();
+ foreach (QString nm, textures.keys()) {
+ processJSONTexture(nm, textures.value(nm).toObject() );
+ }
+
+ m_defaultScene = m_json.object().value("scene").toString();
+ m_parseDone = true;
+}
+
+void GLTFParser::processJSONBuffer( QString id, const QJsonObject& json )
+{
+ // simply cache buffers for lookup by buffer-views
+ m_bufferDatas[id] = BufferData(json);
+}
+
+void GLTFParser::processJSONBufferView( QString id, const QJsonObject& json )
+{
+ QString bufName = json.value("buffer").toString();
+ if (!m_bufferDatas.contains(bufName)) {
+ qWarning() << "unknown buffer:" << bufName << "processing view:" << id;
+ return;
+ }
+
+ int target = json.value("target").toInt();
+ QOpenGLBuffer::Type ty(QOpenGLBuffer::VertexBuffer);
+
+ switch (target) {
+ case GL_ARRAY_BUFFER: ty = QOpenGLBuffer::VertexBuffer; break;
+ case GL_ELEMENT_ARRAY_BUFFER: ty = QOpenGLBuffer::IndexBuffer; break;
+ default:
+ qWarning() << Q_FUNC_INFO << "buffer" << id << "unsupported target:" << target;
+ return;
+ }
+
+ quint64 offset = 0;
+ if (json.contains("byteOffset")) {
+ offset = json.value("byteOffset").toInt();
+ qDebug() << "bv:" << id << "has offset:" << offset;
+ }
+
+ quint64 len = json.value("byteLength").toInt();
+ QFile* f = resolveLocalData(m_bufferDatas[bufName].path);
+ if (!f->seek(offset)) {
+ qWarning() << "failed to seek to offset in file for bufferView:" << id << offset;
+ }
+
+ QByteArray bytes = f->read(len);
+ if (bytes.count() != (int) len) {
+ qWarning() << "failed to read sufficient bytes from:" << m_bufferDatas[bufName].path
+ << "for view" << id;
+ }
+ delete f;
+
+ BufferPtr b(new Buffer(ty));
+ b->setData(bytes);
+ m_buffers[id] = b;
+}
+
+void GLTFParser::processJSONAccessor( QString id, const QJsonObject& json )
+{
+ QString bvName = json.value("bufferView").toString();
+ if (!m_buffers.contains(bvName)) {
+ qWarning() << "unknown buffer-view:" << bvName << "processing accessor:" << id;
+ return;
+ }
+
+ BufferPtr buf = m_buffers.value(bvName);
+ int offset = 0, stride = 0;
+ int type = json.value("type").toInt();
+ int count = json.value("count").toInt();
+
+ if ( json.contains("byteOffset"))
+ offset = json.value("byteOffset").toInt();
+ if ( json.contains("byteStride"))
+ stride = json.value("byteStride").toInt();
+
+ AttributePtr attr( new Attribute( buf, type, count, offset, stride ) );
+ m_attributeDict[id] = attr;
+}
+
+void GLTFParser::processJSONMesh( QString id, QJsonObject jsonObj )
+{
+ QJsonArray primsArray = jsonObj.value( "primitives").toArray();
+ Q_FOREACH (QJsonValue primVal, primsArray) {
+ QJsonObject primObj = primVal.toObject();
+ int type = primObj.value( "primitive").toInt();
+ QString material = primObj.value( "material").toString();
+
+ if ( material.isEmpty()) {
+ qWarning() << "malformed primitive on " << id << ", missing material value"
+ << material;
+ continue;
+ }
+
+ MeshDataPtr md( new MeshData( type ) );
+ m_meshMaterialDict[md.data()] = material;
+
+ QJsonObject attrs = primObj.value("attributes").toObject();
+ Q_FOREACH (QString attrName, attrs.keys()) {
+ QString k = attrs.value(attrName).toString();
+ if (!m_attributeDict.contains(k)) {
+ qWarning() << "unknown attribute accessor:" << k << "on mesh" << id;
+ continue;
+ }
+
+ md->addAttribute(attrName, m_attributeDict[k]);
+
+ // qDebug() << "DUMP of:" << attrName;
+ // m_attributeDict[k]->dump(20);
+ }
+
+ if ( primObj.contains( "indices" )) {
+ QString k = primObj.value("indices").toString();
+ if (!m_attributeDict.contains(k)) {
+ qWarning() << "unknown index accessor:" << k << "on mesh" << id;
+ } else {
+ md->setIndexAttr(m_attributeDict[k]);
+ // m_attributeDict[k]->dump(100);
+ }
+ } // of has indices
+
+ m_meshDict.insert( id, md );
+ } // of primitives iteration
+}
+
+void GLTFParser::processName(const QJsonObject &json, QObject *ins)
+{
+ if ( json.contains( "name" ) )
+ {
+ ins->setObjectName( json.value("name").toString() );
+ }
+}
+
+void GLTFParser::processJSONProgram( QString id, QJsonObject jsonObj)
+{
+ ShaderProgram* prog = new ShaderProgram;
+ prog->setObjectName(id);
+
+ QString fragName = jsonObj.value("fragmentShader").toString(),
+ vertName = jsonObj.value("vertexShader").toString();
+ if (!m_shaderPaths.contains(fragName) || !m_shaderPaths.contains(vertName)) {
+ qWarning() << Q_FUNC_INFO << "program:" << id << "missing shader:" <<
+ fragName << vertName;
+ return;
+ }
+
+ prog->setFragmentSourceFile(m_shaderPaths[fragName]);
+ prog->setVertexSourceFile(m_shaderPaths[vertName]);
+ m_programs[id] = prog;
+}
+
+void GLTFParser::processJSONShader( QString id, QJsonObject jsonObj)
+{
+ // shaders are trivial for the moment, defer the real work
+ // to the program section
+ QString path = jsonObj.value("path").toString();
+
+ QFileInfo info(m_basePath, path);
+ if (!info.exists()) {
+ qWarning() << "can't find shader" << id << "from path" << path;
+ return;
+ }
+
+ m_shaderPaths[id] = info.absoluteFilePath();
+}
+
+void GLTFParser::processJSONImage( QString id, QJsonObject jsonObj)
+{
+ QString path = jsonObj.value("path").toString();
+ QFileInfo info(m_basePath, path);
+ if (!info.exists()) {
+ qWarning() << "can't find image" << id << "from path" << path;
+ return;
+ }
+
+ QImage img(info.absoluteFilePath());
+ if (img.isNull()) {
+ qWarning() << "failed to load image:" << info.absoluteFilePath();
+ return;
+ }
+
+ m_images[id] = img;
+}
+
+void GLTFParser::processJSONTexture( QString id, QJsonObject jsonObj)
+{
+ Texture* tex = new Texture();
+
+ int target = jsonObj.value("target").toInt();
+ int pixelFormat = jsonObj.value("format").toInt();
+ int internalFormat = jsonObj.value("internalFormat").toInt();
+
+ tex->setTarget(static_cast<QOpenGLTexture::Target>(target));
+ tex->setInternalFormat(QOpenGLTexture::RGBA8_UNorm /* static_cast<QOpenGLTexture::TextureFormat>(internalFormat)*/);
+
+ QString samplerId = jsonObj.value("sampler").toString();
+ QString source = jsonObj.value("source").toString();
+ if (!m_images.contains(source)) {
+ qWarning() << "texture" << id << "references missing image" << source;
+ return;
+ }
+
+ tex->setFromQImage(m_images[source]);
+
+ QJsonObject samplersDict(m_json.object().value("samplers").toObject());
+ if (!samplersDict.contains(samplerId)) {
+ qWarning() << "texture" << id << "references unknown sampler" << samplerId;
+ return;
+ }
+
+ QJsonObject sampler = samplersDict.value(samplerId).toObject();
+
+ tex->setWrapMode(static_cast<QOpenGLTexture::WrapMode>(sampler.value("wrapS").toInt()));
+ // tex->setWrapMode(sampler.value("wrapT").toInt());
+
+ tex->setMinificationFilter(static_cast<QOpenGLTexture::Filter>(sampler.value("minFilter").toInt()));
+ tex->setMagnificationFilter(static_cast<QOpenGLTexture::Filter>(sampler.value("magFilter").toInt()));
+
+ m_textures[id] = tex;
+}
+
+void GLTFParser::processJSONTechnique( QString id, QJsonObject jsonObj )
+{
+ Technique *t = new Technique;
+ t->setObjectName(id);
+
+ QHash<QString, Parameter*> paramDict;
+ QJsonObject params = jsonObj.value( "parameters").toObject();
+ Q_FOREACH (QString pname, params.keys()) {
+ QJsonObject po = params.value(pname).toObject();
+
+ int dataType = po.value("type").toInt();
+ QString semantic = po.value("semantic").toString();
+
+ Parameter* p = new Parameter(t, pname, dataType);
+ Parameter::StandardUniform su = parseSemanticName(semantic);
+ if (su != Parameter::None) {
+ p->setStandardUniform(su);
+ } else {
+ // should really verify it's an attribute parameter?
+ // but what would be the way to do that?
+ // check the accessor dict?
+ p->setMeshAttributeName(semantic);
+ }
+
+ t->addParameter(p);
+
+ paramDict[pname] = p;
+ } // of parameters iteration
+
+ QJsonObject passes = jsonObj.value("passes").toObject();
+ Q_FOREACH (QString pname, passes.keys()) {
+ QJsonObject po = passes.value(pname).toObject();
+ QJsonObject ip = po.value("instanceProgram").toObject();
+
+ QString programName = ip.value("program").toString();
+ if (!m_programs.contains(programName)) {
+ qWarning() << Q_FUNC_INFO << "technique" << id << "pass" << pname
+ << ": missing program" << programName;
+ continue;
+ }
+
+ RenderPass* pass = new RenderPass;
+ pass->setShaderProgram(m_programs[programName]);
+
+ QJsonObject attrs = ip.value("attributes").toObject();
+ Q_FOREACH ( QString attrName, attrs.keys() ) {
+ QString pname = attrs.value(attrName).toString();
+ pass->addAttributeBinding(paramDict[pname], attrName);
+ } // of program-instance attributes
+
+
+ QJsonObject uniforms = ip.value("uniforms").toObject();
+ Q_FOREACH (QString uniformName, uniforms.keys()) {
+ QString pname = uniforms.value(uniformName).toString();
+ pass->addUniformBinding(paramDict[pname], uniformName);
+ } // of program-instance attributes
+
+ QJsonObject states = po.value("states").toObject();
+ DrawStateSet* ss = new DrawStateSet;
+
+ Q_FOREACH (QString stateName, states.keys()) {
+ DrawState* s= buildState(stateName, states.value(stateName));
+ if (!s)
+ continue;
+
+ ss->addState(s);
+ } // of program-instance attributes
+
+ pass->setStateSet(ss);
+ t->addPass(pass);
+ } // of passes iteration
+
+ m_techniques[id] = t;
+}
+
+DrawState* GLTFParser::buildState(QString nm, QJsonValue v)
+{
+ if (nm == "blendEnable") {
+ return NULL; // will see a blendEquation spec too
+ }
+
+ if (nm == "blendFunc") {
+ QJsonObject obj = v.toObject();
+ GLenum srcF = static_cast<GLenum>(obj.value("sfactor").toInt());
+ GLenum dstF = static_cast<GLenum>(obj.value("dfactor").toInt());
+ return BlendState::getOrCreate(srcF, dstF);
+ }
+
+ if (nm == "blendEquation") {
+ return BlendEquation::getOrCreate(static_cast<GLenum>(v.toInt()));
+ }
+
+ if (nm == "cullFaceEnable" && v.toInt()) {
+ return CullFace::getOrCreate(GL_BACK);
+ }
+
+ if (nm == "depthTestEnable" && v.toInt()) {
+ return DepthTest::getOrCreate(GL_LESS);
+ }
+
+ if (nm == "depthMask") {
+ return DepthMask::getOrCreate(v.toInt() ? GL_TRUE : GL_FALSE);
+ }
+
+ qWarning() << Q_FUNC_INFO << "unsupported gltf state:" << nm;
+ return NULL;
+}
+
+QFile *GLTFParser::resolveLocalData(QString path)
+{
+ QDir d(m_basePath);
+ Q_ASSERT(d.exists());
+
+ QString absPath = d.absoluteFilePath(path);
+ QFile* f = new QFile(absPath);
+ f->open(QIODevice::ReadOnly);
+ return f;
+}
+
+GLTFParser::BufferData::BufferData() :
+ length(0)
+{
+}
+
+GLTFParser::BufferData::BufferData(QJsonObject json)
+{
+ path = json.value("path").toString();
+ length = json.value("length").toInt();
+ // url
+}
+
+QVariant GLTFParser::parameterValueFromJSON(Parameter* p, QJsonValue val)
+{
+ switch (p->datatype()) {
+ case GL_BOOL:
+ return val.toBool();
+
+ case GL_FLOAT:
+ return val.toDouble();
+
+ case GL_FLOAT_VEC2: {
+ QJsonArray a = val.toArray();
+ return QVector2D(a[0].toDouble(), a[1].toDouble());
+ }
+
+ case GL_FLOAT_VEC3: {
+ QJsonArray a = val.toArray();
+ return QVector3D(a[0].toDouble(), a[1].toDouble(), a[3].toDouble());
+ }
+
+ case GL_FLOAT_VEC4: {
+ QJsonArray a = val.toArray();
+ return QVector4D(a[0].toDouble(),
+ a[1].toDouble(),
+ a[2].toDouble(),
+ a[3].toDouble());
+ }
+
+ case GL_FLOAT_MAT4: {
+ QJsonArray a = val.toArray();
+
+ QMatrix4x4 m;
+ for (int i=0; i<16; ++i) {
+ m(i % 4, i / 4) = a[i].toDouble();
+ }
+ return m;
+ }
+
+ default:
+ qWarning() << Q_FUNC_INFO << "unhandled type:" << QString::number(p->datatype(), 16);
+ }
+
+ return QVariant();
+}
+
+} // of namespace Qt3D
diff --git a/src/render/io/gltfparser.h b/src/render/io/gltfparser.h
new file mode 100644
index 000000000..76f8662f5
--- /dev/null
+++ b/src/render/io/gltfparser.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GLTFPARSER_H
+#define GLTFPARSER_H
+
+#include "meshdata.h"
+
+#include <entity.h>
+#include <technique.h>
+
+#include <QJsonDocument>
+#include <QMultiHash>
+#include <QImage>
+
+class QFile;
+
+namespace Qt3D {
+
+class Material;
+class ShaderProgram;
+class Effect;
+class Camera;
+class Texture;
+
+class GLTFParser
+{
+public:
+ GLTFParser();
+
+ static bool isGLTFPath(QString path);
+
+ void setFilePath(QString path);
+
+ void setBasePath( QString path );
+
+ bool setJSON( QJsonDocument json );
+
+ /**
+ * @brief instantiate Create Nodes based on glTf JSON document
+ * @return A new scene-graph fragment based on the provided glTf
+ */
+ Entity *node(QString id);
+ Entity *defaultScene();
+ MeshDataPtr mesh(QString id);
+ Entity *scene(QString id);
+ Material *material(QString id);
+ Camera *camera(QString id);
+
+private:
+ void parse();
+
+ void processJSONMesh( QString id, QJsonObject jsonObj );
+ void processJSONAccessor(QString id, const QJsonObject &json);
+ void processJSONBuffer(QString id, const QJsonObject &json);
+ void processJSONBufferView(QString id, const QJsonObject &json);
+
+ void processName( const QJsonObject& json, QObject* ins );
+
+ QJsonDocument m_json;
+ QString m_basePath;
+ bool m_parseDone;
+ QString m_defaultScene;
+
+ // multi-hash because our MeshData corresponds to a single primitive
+ // in glTf.
+ QMultiHash<QString, MeshDataPtr> m_meshDict;
+
+ // GLTF assigns materials at the mesh level, but we do them as siblings,
+ // so record the association here for when we instantiate meshes
+ QMap<MeshData*, QString> m_meshMaterialDict;
+
+ QMap<QString, AttributePtr> m_attributeDict;
+
+ class BufferData
+ {
+ public:
+ BufferData();
+
+ BufferData(QJsonObject json);
+
+ quint64 length;
+ QString path;
+ // type if ever useful
+ };
+
+ QMap<QString, Material*> m_materialCache;
+
+ QMap<QString, BufferData> m_bufferDatas;
+ QMap<QString, BufferPtr> m_buffers;
+
+ QMap<QString, QString> m_shaderPaths;
+ QMap<QString, ShaderProgram*> m_programs;
+
+ QMap<QString, Technique *> m_techniques;
+ // glTF doesn't deal in effects, but we need a trivial one to wrap
+ // up our techniques
+ QMap<QString, Effect*> m_effectProxies;
+
+ QMap<QString, Texture*> m_textures;
+ QMap<QString, QImage> m_images;
+
+ QFile* resolveLocalData(QString path);
+
+ void processJSONShader(QString id, QJsonObject jsonObj);
+ void processJSONProgram(QString id, QJsonObject jsonObj);
+ void processJSONTechnique(QString id, QJsonObject jsonObj);
+
+ void processJSONImage(QString id, QJsonObject jsonObj);
+ void processJSONTexture(QString id, QJsonObject jsonObj);
+
+ QVariant parameterValueFromJSON(Parameter *p, QJsonValue val);
+
+ DrawState *buildState(QString nm, QJsonValue obj);
+};
+
+}
+
+#endif // GLTFPARSER_H
diff --git a/src/render/io/meshdata.cpp b/src/render/io/meshdata.cpp
new file mode 100644
index 000000000..7c68adb6b
--- /dev/null
+++ b/src/render/io/meshdata.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "meshdata.h"
+
+#include <QSet>
+#include <QDebug>
+#include <QOpenGLVertexArrayObject>
+
+namespace Qt3D
+{
+
+GLint elementType(GLint type)
+{
+ switch (type) {
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ return GL_FLOAT;
+
+ case GL_DOUBLE:
+ case GL_DOUBLE_VEC2:
+ case GL_DOUBLE_VEC3:
+ case GL_DOUBLE_VEC4:
+ return GL_DOUBLE;
+
+ default:
+ qWarning() << Q_FUNC_INFO << "unsupported:" << QString::number(type, 16);
+ }
+
+ return GL_INVALID_VALUE;
+}
+
+GLint tupleSizeFromType(GLint type)
+{
+ switch (type) {
+ case GL_FLOAT:
+ case GL_DOUBLE:
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_INT:
+ break; // fall through
+
+ case GL_FLOAT_VEC2:
+ case GL_DOUBLE_VEC2: return 2;
+
+ case GL_FLOAT_VEC3:
+ case GL_DOUBLE_VEC3: return 3;
+
+ case GL_FLOAT_VEC4:
+ case GL_DOUBLE_VEC4: return 4;
+
+ default:
+ qWarning() << Q_FUNC_INFO << "unsupported:" << QString::number(type, 16);
+ }
+
+ return 1;
+}
+
+GLuint byteSizeFromType(GLint type)
+{
+ switch (type) {
+ case GL_FLOAT: return sizeof(float);
+ case GL_DOUBLE: return sizeof(double);
+ case GL_UNSIGNED_BYTE: return sizeof(unsigned char);
+ case GL_UNSIGNED_INT: return sizeof(GLuint);
+
+ case GL_FLOAT_VEC2: return sizeof(float) * 2;
+ case GL_DOUBLE_VEC2: return sizeof(double) * 2;
+
+ case GL_FLOAT_VEC3: return sizeof(float) * 3;
+ case GL_DOUBLE_VEC3: return sizeof(double) * 3;
+
+ case GL_FLOAT_VEC4: return sizeof(float) * 4;
+ case GL_DOUBLE_VEC4: return sizeof(double) * 4;
+
+ default:
+ qWarning() << Q_FUNC_INFO << "unsupported:" << QString::number(type, 16);
+ }
+
+ return 0;
+}
+
+MeshData::MeshData()
+ : m_primitiveType(0)
+{
+}
+
+MeshData::MeshData(int primitiveType) :
+ m_primitiveType(primitiveType)
+{
+ Q_ASSERT((m_primitiveType == GL_TRIANGLES) ||
+ (m_primitiveType == GL_LINES) ||
+ (m_primitiveType == GL_POINTS));
+}
+
+void MeshData::addAttribute(QString name, AttributePtr attr)
+{
+ Q_ASSERT(!m_attributes.contains(name));
+ m_attributes[name] = attr;
+}
+
+void MeshData::addAttribute(QString name, Attribute *attr)
+{
+ Q_ASSERT(!m_attributes.contains(name));
+ m_attributes[name] = AttributePtr(attr);
+}
+
+void MeshData::setIndexAttr(AttributePtr indexAttr)
+{
+ m_indexAttr = indexAttr;
+}
+
+void MeshData::setIndexData(BufferPtr buf, int type, int count, int offset)
+{
+ m_indexAttr = AttributePtr(new Attribute(buf, type, count, offset));
+}
+
+GLint MeshData::primitiveType() const
+{
+ return m_primitiveType;
+}
+
+GLsizei MeshData::primitiveCount() const
+{
+ if (m_indexAttr) {
+ return m_indexAttr->count();
+ } else {
+ // assume all attribute arrays have the same size
+ // will break with instanced drawing, but probably per-instance
+ // arrays aren't coming from this code-path.
+ // Maybe.
+ return m_attributes.first()->count();
+ }
+}
+
+QStringList MeshData::attributeNames() const
+{
+ return m_attributes.keys();
+}
+
+AttributePtr MeshData::attributeByName(QString nm) const
+{
+ return m_attributes.value(nm);
+}
+
+AttributePtr MeshData::indexAttr() const
+{
+ return m_indexAttr;
+}
+
+QList<BufferPtr> MeshData::buffers() const
+{
+ QSet<BufferPtr> r;
+ if (m_indexAttr)
+ r.insert(m_indexAttr->buffer());
+
+ foreach (AttributePtr v, m_attributes.values())
+ r.insert(v->buffer());
+
+ return r.toList();
+}
+
+void MeshData::setBoundingBox(const AxisAlignedBoundingBox &bbox)
+{
+ m_box = bbox;
+}
+
+void MeshData::computeBoundsFromAttribute(QString name)
+{
+ AttributePtr attr = attributeByName(name);
+ if (!attr) {
+ qWarning() << Q_FUNC_INFO << "unknoen attribute:" << name;
+ return;
+ }
+
+ m_box.clear();
+ m_box.update(attr->asVector3D());
+}
+
+Attribute::Attribute(BufferPtr buf, int type, int count, int offset, int stride) :
+ m_buffer(buf),
+ m_type(type),
+ m_count(count),
+ m_stride(stride),
+ m_offset(offset),
+ m_divisor(0)
+{
+
+}
+
+void Attribute::setDivisor(unsigned int divisor)
+{
+ m_divisor = divisor;
+}
+
+BufferPtr Attribute::buffer() const
+{
+ return m_buffer;
+}
+
+QVector<QVector3D> Attribute::asVector3D() const
+{
+ const char* rawBuffer = m_buffer->data().constData();
+ rawBuffer += m_offset;
+ const float* fptr;
+ int stride;
+
+ switch (type()) {
+ case GL_FLOAT_VEC2:
+ stride = sizeof(float) * 2; break;
+
+ case GL_FLOAT_VEC3:
+ stride = sizeof(float) * 3; break;
+
+ case GL_FLOAT_VEC4:
+ stride = sizeof(float) * 4; break;
+
+ default:
+ qDebug() << Q_FUNC_INFO << "can't convert" << QString::number(type(), 16) << "to QVector3D";
+ return QVector<QVector3D>();
+ }
+
+ if (m_stride != 0)
+ stride = m_stride;
+ QVector<QVector3D> result;
+ result.resize(m_count);
+
+ for (int c=0; c<m_count; ++c) {
+ QVector3D v;
+ fptr = reinterpret_cast<const float*>(rawBuffer);
+
+ switch (type()) {
+ case GL_FLOAT_VEC2:
+ v.setX(fptr[0]);
+ v.setY(fptr[1]);
+ v.setZ(0.0f);
+ break;
+
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ v.setX(fptr[0]);
+ v.setY(fptr[1]);
+ v.setZ(fptr[2]);
+ break;
+
+ default:
+ break; // should never happen, we check types above
+ }
+
+ result[c] = v;
+ rawBuffer += stride;
+ }
+
+ return result;
+}
+
+QVector<QVector2D> Attribute::asVector2D() const
+{
+ char* rawBuffer = m_buffer->data().data();
+ rawBuffer += m_offset;
+ float* fptr;
+ int stride;
+
+ switch (type()) {
+ case GL_FLOAT_VEC2:
+ stride = sizeof(float) * 2; break;
+
+ case GL_FLOAT_VEC3:
+ stride = sizeof(float) * 3; break;
+
+ case GL_FLOAT_VEC4:
+ stride = sizeof(float) * 4; break;
+
+ default:
+ qDebug() << Q_FUNC_INFO << "can't convert" << QString::number(type(), 16) << "to QVector2D";
+ return QVector<QVector2D>();
+ }
+
+ if (m_stride != 0)
+ stride = m_stride;
+
+ QVector<QVector2D> result;
+ result.resize(m_count);
+
+ for (int c=0; c<m_count; ++c) {
+ QVector2D v;
+ fptr = reinterpret_cast<float*>(rawBuffer);
+ v.setX(fptr[0]);
+ v.setY(fptr[1]);
+ result[c] = v;
+ rawBuffer += stride;
+ }
+
+ return result;
+}
+
+void Attribute::dump(int count)
+{
+ char* rawBuffer = m_buffer->data().data();
+ rawBuffer += m_offset;
+
+ float* fptr;
+ quint16* usptr;
+
+ int stride = m_stride;
+
+ for (int c=0; c<count; ++c) {
+ switch (type()) {
+ case GL_UNSIGNED_SHORT:
+ if (!stride) stride = sizeof(quint16);
+ usptr = reinterpret_cast<quint16*>(rawBuffer);
+ qDebug() << c << ":u16:" << usptr[0];
+ break;
+
+ case GL_FLOAT_VEC2:
+ if (!stride) stride = sizeof(float) * 2;
+ fptr = reinterpret_cast<float*>(rawBuffer);
+ qDebug() << c << ":vec2:"<< fptr[0] << fptr[0];
+ break;
+
+ case GL_FLOAT_VEC3:
+ if (!stride) stride = sizeof(float) * 3;
+ fptr = reinterpret_cast<float*>(rawBuffer);
+ qDebug() << c << ":vec3:" << fptr[0] << fptr[0] << fptr[2];
+ break;
+
+ default: qDebug() << Q_FUNC_INFO << "unspported type:" << QString::number(type(), 16);
+ }
+
+
+ }
+}
+
+Buffer::Buffer(QOpenGLBuffer::Type ty) :
+ m_type(ty),
+ m_usage(QOpenGLBuffer::StaticDraw)
+{
+}
+
+void Buffer::setUsage(QOpenGLBuffer::UsagePattern usage)
+{
+ m_usage = usage;
+}
+
+void Buffer::setData(QByteArray bytes)
+{
+ m_clientSideBytes = bytes;
+ // mark as dirty for dynamic / stream data
+ // if static, check this is the first and only set.
+}
+
+QByteArray Buffer::data() const
+{
+ return m_clientSideBytes;
+}
+
+QOpenGLBuffer Buffer::createGL() const
+{
+ QOpenGLBuffer b(m_type);
+ b.setUsagePattern(m_usage);
+ if (!b.create())
+ qWarning() << Q_FUNC_INFO << "buffer creation failed";
+
+ if (!b.bind())
+ qWarning() << Q_FUNC_INFO << "buffer binding failed";
+
+ b.allocate(m_clientSideBytes.count());
+ b.release();
+ return b;
+}
+
+void Buffer::upload(QOpenGLBuffer b)
+{
+ if (!b.bind())
+ qWarning() << Q_FUNC_INFO << "buffer bind failed";
+ b.allocate(NULL, m_clientSideBytes.count()); // orphan the buffer
+ b.allocate(m_clientSideBytes.data(),
+ m_clientSideBytes.count());
+ b.release();
+ qDebug() << "uploaded buffer size=" << m_clientSideBytes.count();
+}
+
+} // of namespace
diff --git a/src/render/io/meshdata.h b/src/render/io/meshdata.h
new file mode 100644
index 000000000..92a9330bb
--- /dev/null
+++ b/src/render/io/meshdata.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESHDATA_H
+#define MESHDATA_H
+
+#include <QSharedPointer>
+#include <QList>
+#include <QMap>
+#include <QOpenGLBuffer>
+#include <QVector2D>
+
+#include <axisalignedboundingbox.h>
+
+
+namespace Qt3D
+{
+
+GLint elementType(GLint type);
+GLint tupleSizeFromType(GLint type);
+GLuint byteSizeFromType(GLint type);
+
+class Buffer
+{
+public:
+ Buffer(QOpenGLBuffer::Type ty);
+
+ void setUsage(QOpenGLBuffer::UsagePattern usage);
+
+ void setData(QByteArray bytes);
+ QByteArray data() const;
+
+ QOpenGLBuffer::Type type() const
+ { return m_type; }
+
+ void bind();
+
+ QOpenGLBuffer createGL() const;
+ void upload(QOpenGLBuffer b);
+
+ // make a QObject and signal when contents change?
+ // GraphicsContext could listen, orphan the QOpenGLBuffer and hence
+ // reupload next time it's need
+private:
+ const QOpenGLBuffer::Type m_type;
+ QOpenGLBuffer::UsagePattern m_usage;
+ QByteArray m_clientSideBytes;
+};
+
+typedef QSharedPointer<Buffer> BufferPtr;
+
+class Attribute
+{
+public:
+ Attribute(BufferPtr buf, int type, int count, int offset=0, int stride = 0);
+
+ void setDivisor(unsigned int divisor);
+
+ unsigned int divisor() const
+ { return m_divisor; }
+
+ BufferPtr buffer() const;
+
+ int type() const
+ { return m_type; }
+
+ unsigned int count() const
+ { return m_count; }
+
+ unsigned int byteStride() const
+ { return m_stride; }
+
+ unsigned int byteOffset() const
+ { return m_offset; }
+
+ QVector<QVector3D> asVector3D() const;
+ QVector<QVector2D> asVector2D() const;
+
+ void dump(int count);
+private:
+ BufferPtr m_buffer;
+ int m_type, m_count;
+ unsigned int m_stride, m_offset; // both in bytes
+ // AxisAlignedBoundBox m_range;
+ unsigned int m_divisor;
+};
+
+typedef QSharedPointer<Attribute> AttributePtr;
+
+/**
+ * @brief The MeshData class is shared by all instances of a RenderMesh,
+ * and holds the actual client (CPU)-side buffers representing mesh attributes
+ * and indices.
+ */
+class MeshData
+{
+public:
+ MeshData();
+ explicit MeshData(int primitiveType);
+
+ void addAttribute(QString name, AttributePtr attr);
+
+ // permit inline 'new' call, will take ownership
+ void addAttribute(QString name, Attribute* attr);
+
+ void setIndexAttr(AttributePtr indexAttr);
+ void setIndexData(BufferPtr buf, int type, int count, int offset = 0);
+
+ GLint primitiveType() const;
+ GLsizei primitiveCount() const;
+
+ QStringList attributeNames() const;
+
+ AttributePtr attributeByName(QString nm) const;
+
+ AttributePtr indexAttr() const;
+
+ QString materialName() const;
+
+ QList<BufferPtr> buffers() const;
+
+ // specify the bounding box explicitly
+ void setBoundingBox(const AxisAlignedBoundingBox& bbox);
+
+ void computeBoundsFromAttribute(QString name);
+
+ AxisAlignedBoundingBox boundingBox() const
+ { return m_box; }
+private:
+ QMap<QString, AttributePtr> m_attributes;
+ QString m_materialName;
+
+ int m_primitiveType;
+ AttributePtr m_indexAttr;
+
+ AxisAlignedBoundingBox m_box;
+};
+
+typedef QSharedPointer<MeshData> MeshDataPtr;
+
+}
+
+#endif // MESHDATA_H
diff --git a/src/render/io/objloader.cpp b/src/render/io/objloader.cpp
new file mode 100644
index 000000000..a01aa5e2e
--- /dev/null
+++ b/src/render/io/objloader.cpp
@@ -0,0 +1,442 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "objloader.h"
+
+#include "mesh.h"
+#include "axisalignedboundingbox.h"
+
+#include <QDebug>
+#include <QFile>
+#include <QOpenGLBuffer>
+#include <QOpenGLShaderProgram>
+#include <QTextStream>
+#include <QVector>
+
+namespace Qt3D {
+
+inline uint qHash(const Qt3D::FaceIndices &faceIndices)
+{
+ return faceIndices.positionIndex
+ + 10 * faceIndices.texCoordIndex
+ + 100 * faceIndices.normalIndex;
+}
+
+ObjLoader::ObjLoader()
+ : m_loadTextureCoords( true ),
+ m_generateTangents( true ),
+ m_centerMesh( false )
+{
+}
+
+bool ObjLoader::load( const QString& fileName )
+{
+ QFile file( fileName );
+ if ( !file.open( ::QIODevice::ReadOnly | ::QIODevice::Text ) )
+ {
+ qDebug() << "Could not open file" << fileName << "for reading";
+ return false;
+ }
+
+ return load( &file );
+}
+
+static void addFaceVertex(const FaceIndices &faceIndices,
+ QVector<FaceIndices> &faceIndexVector,
+ QHash<FaceIndices, unsigned int> &faceIndexMap)
+{
+ if (faceIndices.positionIndex != std::numeric_limits<unsigned int>::max()) {
+ faceIndexVector.append(faceIndices);
+ if (!faceIndexMap.contains(faceIndices))
+ faceIndexMap.insert(faceIndices, faceIndexMap.size());
+ } else {
+ qWarning( "Missing position index" );
+ }
+}
+
+bool ObjLoader::load(::QIODevice *ioDev)
+{
+ Q_CHECK_PTR(ioDev);
+ if (!ioDev->isOpen()) {
+ qWarning() << "iodevice" << ioDev << "not open for reading";
+ return false;
+ }
+
+ int faceCount = 0;
+
+ // Parse faces taking into account each vertex in a face can index different indices
+ // for the positions, normals and texture coords;
+ // Generate unique vertices (in OpenGL parlance) and output to m_points, m_texCoords,
+ // m_normals and calculate mapping from faces to unique indices
+ QVector<QVector3D> positions;
+ QVector<QVector3D> normals;
+ QVector<QVector2D> texCoords;
+ QHash<FaceIndices, unsigned int> faceIndexMap;
+ QVector<FaceIndices> faceIndexVector;
+
+ QTextStream stream(ioDev);
+ while (!stream.atEnd()) {
+ QString line = stream.readLine();
+ line = line.simplified();
+
+ if (line.length() > 0 && line.at(0) != QChar::fromLatin1('#')) {
+ QTextStream lineStream(&line, QIODevice::ReadOnly);
+ QString token;
+ lineStream >> token;
+
+ if (token == QStringLiteral("v")) {
+ float x, y, z;
+ lineStream >> x >> y >> z;
+ positions.append(QVector3D( x, y, z ));
+ } else if (token == QStringLiteral("vt") && m_loadTextureCoords) {
+ // Process texture coordinate
+ float s,t;
+ lineStream >> s >> t;
+ texCoords.append(QVector2D(s, t));
+ } else if (token == QStringLiteral("vn")) {
+ float x, y, z;
+ lineStream >> x >> y >> z;
+ normals.append(QVector3D( x, y, z ));
+ } else if (token == QStringLiteral("f")) {
+ // Process face
+ ++faceCount;
+ QVector<FaceIndices> face;
+ int faceVertices = 0;
+ while (!lineStream.atEnd()) {
+ QString faceString;
+ lineStream >> faceString;
+
+ FaceIndices faceIndices;
+ QStringList indices = faceString.split(QChar::fromLatin1('/'));
+ switch (indices.size()) {
+ case 3:
+ faceIndices.normalIndex = indices.at(2).toInt() - 1; // fall through
+ case 2:
+ faceIndices.texCoordIndex = indices.at(1).toInt() - 1; // fall through
+ case 1:
+ faceIndices.positionIndex = indices.at(0).toInt() - 1;
+ break;
+ default:
+ qWarning() << "Unsupported number of indices in face element";
+ }
+
+ face.append(faceIndices);
+ ++faceVertices;
+ }
+
+ // If number of edges in face is greater than 3,
+ // decompose into triangles as a triangle fan.
+ FaceIndices v0 = face[0];
+ FaceIndices v1 = face[1];
+ FaceIndices v2 = face[2];
+
+ // First face
+ addFaceVertex(v0, faceIndexVector, faceIndexMap);
+ addFaceVertex(v1, faceIndexVector, faceIndexMap);
+ addFaceVertex(v2, faceIndexVector, faceIndexMap);
+
+ for ( int i = 3; i < face.size(); ++i ) {
+ v1 = v2;
+ v2 = face[i];
+ addFaceVertex(v0, faceIndexVector, faceIndexMap);
+ addFaceVertex(v1, faceIndexVector, faceIndexMap);
+ addFaceVertex(v2, faceIndexVector, faceIndexMap);
+ }
+ } // end of face
+ } // end of input line
+ } // while (!stream.atEnd())
+
+ updateIndices(positions, normals, texCoords, faceIndexMap, faceIndexVector);
+
+ if (m_normals.isEmpty())
+ generateAveragedNormals(m_points, m_normals, m_indices);
+
+ if (m_generateTangents && !m_texCoords.isEmpty())
+ generateTangents(m_points, m_normals, m_indices, m_texCoords, m_tangents);
+
+ if (m_centerMesh)
+ center(m_points);
+
+//#if 0
+ qDebug() << "Loaded mesh:";
+ qDebug() << " " << m_points.size() << "points";
+ qDebug() << " " << faceCount << "faces";
+ qDebug() << " " << m_indices.size() / 3 << "triangles.";
+ qDebug() << " " << m_normals.size() << "normals";
+ qDebug() << " " << m_tangents.size() << "tangents ";
+ qDebug() << " " << m_texCoords.size() << "texture coordinates.";
+//#endif
+
+ return true;
+}
+
+MeshDataPtr ObjLoader::mesh() const
+{
+ MeshDataPtr mesh(new MeshData(GL_TRIANGLES));
+
+ QByteArray bufferBytes;
+ const int count = m_points.size();
+ quint32 elementSize = 3 + (hasTextureCoordinates() ? 2 : 0)
+ + (hasNormals() ? 3 : 0)
+ + (hasTangents() ? 4 : 0);
+ quint32 stride = elementSize * sizeof(float);
+ bufferBytes.resize(stride * count);
+ float* fptr = reinterpret_cast<float*>(bufferBytes.data());
+
+ for (int index = 0; index < count; ++index) {
+ *fptr++ = m_points.at(index).x();
+ *fptr++ = m_points.at(index).y();
+ *fptr++ = m_points.at(index).z();
+
+ if (hasTextureCoordinates()) {
+ *fptr++ = m_texCoords.at(index).x();
+ *fptr++ = m_texCoords.at(index).y();
+ }
+
+ if (hasNormals()) {
+ *fptr++ = m_normals.at(index).x();
+ *fptr++ = m_normals.at(index).y();
+ *fptr++ = m_normals.at(index).z();
+ }
+
+ if (hasTangents()) {
+ *fptr++ = m_tangents.at(index).x();
+ *fptr++ = m_tangents.at(index).y();
+ *fptr++ = m_tangents.at(index).z();
+ *fptr++ = m_tangents.at(index).w();
+ }
+ } // of buffer filling loop
+
+ BufferPtr buf(new Buffer(QOpenGLBuffer::VertexBuffer));
+ buf->setUsage(QOpenGLBuffer::StaticDraw);
+ buf->setData(bufferBytes);
+
+
+ mesh->addAttribute("position", new Attribute(buf, GL_FLOAT_VEC3, count, 0, stride));
+ quint32 offset = sizeof(float) * 3;
+
+ if (hasTextureCoordinates()) {
+ mesh->addAttribute("texcoord", new Attribute(buf, GL_FLOAT_VEC2, count, offset, stride));
+ offset += sizeof(float) * 2;
+ }
+
+ if (hasNormals()) {
+ mesh->addAttribute("normal", new Attribute(buf, GL_FLOAT_VEC3, count, offset, stride));
+ offset += sizeof(float) * 3;
+ }
+
+ if (hasTangents()) {
+ mesh->addAttribute("tangent", new Attribute(buf, GL_FLOAT_VEC4, count, offset, stride));
+ offset += sizeof(float) * 4;
+ }
+
+ QByteArray indexBytes;
+ GLuint ty;
+ if (m_indices.size() < 65536) {
+ // we can use USHORT
+ ty = GL_UNSIGNED_SHORT;
+ indexBytes.resize(m_indices.size() * sizeof(quint16));
+ quint16* usptr = reinterpret_cast<quint16*>(indexBytes.data());
+ for (int i=0; i<m_indices.size(); ++i)
+ *usptr++ = static_cast<quint16>(m_indices.at(i));
+ } else {
+ // use UINT - no conversion needed, but let's ensure int is 32-bit!
+ ty = GL_UNSIGNED_INT;
+ Q_ASSERT(sizeof(int) == sizeof(quint32));
+ indexBytes.resize(m_indices.size() * sizeof(quint32));
+ memcpy(indexBytes.data(), reinterpret_cast<const char*>(m_indices.data()), indexBytes.size());
+ }
+
+ BufferPtr indexBuffer(new Buffer(QOpenGLBuffer::IndexBuffer));
+ indexBuffer->setUsage(QOpenGLBuffer::StaticDraw);
+ indexBuffer->setData(indexBytes);
+ mesh->setIndexAttr(AttributePtr(new Attribute(indexBuffer, ty, m_indices.size(), 0, 0)));
+
+ mesh->computeBoundsFromAttribute("position");
+ qDebug() << "computed bounds is:" << mesh->boundingBox();
+
+ return mesh;
+}
+
+void ObjLoader::updateIndices(const QVector<QVector3D> &positions,
+ const QVector<QVector3D> &normals,
+ const QVector<QVector2D> &texCoords,
+ const QHash<FaceIndices, unsigned int> &faceIndexMap,
+ const QVector<FaceIndices> &faceIndexVector)
+{
+ // Iterate over the faceIndexMap and pull out pos, texCoord and normal data
+ // thereby generating unique vertices of data (by OpenGL definition)
+ const int vertexCount = faceIndexMap.size();
+ const bool hasTexCoords = !texCoords.isEmpty();
+ const bool hasNormals = !normals.isEmpty();
+
+ m_points.resize(vertexCount);
+ m_texCoords.clear();
+ if (hasTexCoords)
+ m_texCoords.resize(vertexCount);
+ m_normals.clear();
+ if (hasNormals)
+ m_normals.resize(vertexCount);
+
+ foreach (const FaceIndices &faceIndices, faceIndexMap.keys()) {
+ const int i = faceIndexMap.value(faceIndices);
+
+ m_points[i] = positions[faceIndices.positionIndex];
+ if (hasTexCoords)
+ m_texCoords[i] = texCoords[faceIndices.texCoordIndex];
+ if (hasNormals)
+ m_normals[i] = normals[faceIndices.normalIndex];
+ }
+
+ // Now iterate over the face indices and lookup the unique vertex index
+ const int indexCount = faceIndexVector.size();
+ m_indices.clear();
+ m_indices.reserve(indexCount);
+ foreach (const FaceIndices &faceIndices, faceIndexVector) {
+ const unsigned int i = faceIndexMap.value(faceIndices);
+ m_indices.append(i);
+ }
+}
+
+void ObjLoader::generateAveragedNormals( const QVector<QVector3D>& points,
+ QVector<QVector3D>& normals,
+ const QVector<unsigned int>& faces ) const
+{
+ for ( int i = 0; i < points.size(); ++i )
+ normals.append( QVector3D() );
+
+ for ( int i = 0; i < faces.size(); i += 3 )
+ {
+ const QVector3D& p1 = points[ faces[i] ];
+ const QVector3D& p2 = points[ faces[i+1] ];
+ const QVector3D& p3 = points[ faces[i+2] ];
+
+ QVector3D a = p2 - p1;
+ QVector3D b = p3 - p1;
+ QVector3D n = QVector3D::crossProduct( a, b ).normalized();
+
+ normals[ faces[i] ] += n;
+ normals[ faces[i+1] ] += n;
+ normals[ faces[i+2] ] += n;
+ }
+
+ for ( int i = 0; i < normals.size(); ++i )
+ normals[i].normalize();
+}
+
+void ObjLoader::generateTangents( const QVector<QVector3D>& points,
+ const QVector<QVector3D>& normals,
+ const QVector<unsigned int>& faces,
+ const QVector<QVector2D>& texCoords,
+ QVector<QVector4D>& tangents ) const
+{
+ tangents.clear();
+ QVector<QVector3D> tan1Accum;
+ QVector<QVector3D> tan2Accum;
+
+ for ( int i = 0; i < points.size(); i++ )
+ {
+ tan1Accum.append( QVector3D() );
+ tan2Accum.append( QVector3D() );
+ tangents.append( QVector4D() );
+ }
+
+ // Compute the tangent vector
+ for ( int i = 0; i < faces.size(); i += 3 )
+ {
+ const QVector3D& p1 = points[ faces[i] ];
+ const QVector3D& p2 = points[ faces[i+1] ];
+ const QVector3D& p3 = points[ faces[i+2] ];
+
+ const QVector2D& tc1 = texCoords[ faces[i] ];
+ const QVector2D& tc2 = texCoords[ faces[i+1] ];
+ const QVector2D& tc3 = texCoords[ faces[i+2] ];
+
+ QVector3D q1 = p2 - p1;
+ QVector3D q2 = p3 - p1;
+ float s1 = tc2.x() - tc1.x(), s2 = tc3.x() - tc1.x();
+ float t1 = tc2.y() - tc1.y(), t2 = tc3.y() - tc1.y();
+ float r = 1.0f / ( s1 * t2 - s2 * t1 );
+ QVector3D tan1( ( t2 * q1.x() - t1 * q2.x() ) * r,
+ ( t2 * q1.y() - t1 * q2.y() ) * r,
+ ( t2 * q1.z() - t1 * q2.z() ) * r );
+ QVector3D tan2( ( s1 * q2.x() - s2 * q1.x() ) * r,
+ ( s1 * q2.y() - s2 * q1.y() ) * r,
+ ( s1 * q2.z() - s2 * q1.z() ) * r );
+ tan1Accum[ faces[i] ] += tan1;
+ tan1Accum[ faces[i+1] ] += tan1;
+ tan1Accum[ faces[i+2] ] += tan1;
+ tan2Accum[ faces[i] ] += tan2;
+ tan2Accum[ faces[i+1] ] += tan2;
+ tan2Accum[ faces[i+2] ] += tan2;
+ }
+
+ for ( int i = 0; i < points.size(); ++i )
+ {
+ const QVector3D& n = normals[i];
+ QVector3D& t1 = tan1Accum[i];
+ QVector3D& t2 = tan2Accum[i];
+
+ // Gram-Schmidt orthogonalize
+ tangents[i] = QVector4D( QVector3D( t1 - QVector3D::dotProduct( n, t1 ) * n ).normalized(), 0.0f );
+
+ // Store handedness in w
+ tangents[i].setW( ( QVector3D::dotProduct( QVector3D::crossProduct( n, t1 ), t2 ) < 0.0f ) ? -1.0f : 1.0f );
+ }
+}
+
+void ObjLoader::center( QVector<QVector3D>& points )
+{
+ if ( points.isEmpty() )
+ return;
+
+ AxisAlignedBoundingBox bb(points);
+ QVector3D center = bb.center();
+
+ // Translate center of the AABB to the origin
+ for ( int i = 0; i < points.size(); ++i )
+ {
+ QVector3D& point = points[i];
+ point = point - center;
+ }
+}
+
+}
diff --git a/src/render/io/objloader.h b/src/render/io/objloader.h
new file mode 100644
index 000000000..6c7ae93c0
--- /dev/null
+++ b/src/render/io/objloader.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef OBJLOADER_H
+#define OBJLOADER_H
+
+#include "meshdata.h"
+
+#include <QVector>
+#include <QVector2D>
+#include <QVector3D>
+#include <QVector4D>
+
+#include <limits>
+
+class QString;
+class QIODevice;
+
+namespace Qt3D {
+
+struct FaceIndices
+{
+ FaceIndices()
+ : positionIndex(std::numeric_limits<unsigned int>::max())
+ , texCoordIndex(std::numeric_limits<unsigned int>::max())
+ , normalIndex(std::numeric_limits<unsigned int>::max())
+ {}
+
+ FaceIndices(unsigned int posIndex, unsigned int tcIndex, unsigned int nIndex)
+ : positionIndex(posIndex)
+ , texCoordIndex(tcIndex)
+ , normalIndex(nIndex)
+ {}
+
+ bool operator == (const FaceIndices &other) const
+ {
+ return positionIndex == other.positionIndex &&
+ texCoordIndex == other.texCoordIndex &&
+ normalIndex == other.normalIndex;
+ }
+
+ unsigned int positionIndex;
+ unsigned int texCoordIndex;
+ unsigned int normalIndex;
+};
+
+class ObjLoader
+{
+public:
+ ObjLoader();
+
+ void setLoadTextureCoordinatesEnabled( bool b ) { m_loadTextureCoords = b; }
+ bool isLoadTextureCoordinatesEnabled() const { return m_loadTextureCoords; }
+
+ void setTangentGenerationEnabled( bool b ) { m_generateTangents = b; }
+ bool isTangentGenerationEnabled() const { return m_generateTangents; }
+
+ void setMeshCenteringEnabled( bool b ) { m_centerMesh = b; }
+ bool isMeshCenteringEnabled() const { return m_centerMesh; }
+
+ bool hasNormals() const { return !m_normals.isEmpty(); }
+ bool hasTextureCoordinates() const { return !m_texCoords.isEmpty(); }
+ bool hasTangents() const { return !m_tangents.isEmpty(); }
+
+ bool load( const QString& fileName );
+ bool load( ::QIODevice* ioDev );
+
+ QVector<QVector3D> vertices() const { return m_points; }
+ QVector<QVector3D> normals() const { return m_normals; }
+ QVector<QVector2D> textureCoordinates() const { return m_texCoords; }
+ QVector<QVector4D> tangents() const { return m_tangents; }
+ QVector<unsigned int> indices() const { return m_indices; }
+
+ MeshDataPtr mesh() const;
+
+private:
+ void updateIndices(const QVector<QVector3D> &positions,
+ const QVector<QVector3D> &normals,
+ const QVector<QVector2D> &texCoords,
+ const QHash<FaceIndices, unsigned int> &faceIndexMap,
+ const QVector<FaceIndices> &faceIndexVector);
+ void generateAveragedNormals( const QVector<QVector3D>& points,
+ QVector<QVector3D>& normals,
+ const QVector<unsigned int>& faces ) const;
+ void generateTangents( const QVector<QVector3D>& points,
+ const QVector<QVector3D>& normals,
+ const QVector<unsigned int>& faces,
+ const QVector<QVector2D>& texCoords,
+ QVector<QVector4D>& tangents ) const;
+ void center( QVector<QVector3D>& points );
+
+ bool m_loadTextureCoords;
+ bool m_generateTangents;
+ bool m_centerMesh;
+
+ QVector<QVector3D> m_points;
+ QVector<QVector3D> m_normals;
+ QVector<QVector2D> m_texCoords;
+ QVector<QVector4D> m_tangents;
+ QVector<unsigned int> m_indices;
+};
+
+}
+
+#endif // OBJLOADER_H
diff --git a/src/render/io/render-io.pri b/src/render/io/render-io.pri
new file mode 100644
index 000000000..18e19540f
--- /dev/null
+++ b/src/render/io/render-io.pri
@@ -0,0 +1,13 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/meshdata.h \
+ $$PWD/gltfparser.h \
+ $$PWD/objloader.h \
+ $$PWD/texturedata.h
+
+SOURCES += \
+ $$PWD/meshdata.cpp \
+ $$PWD/gltfparser.cpp \
+ $$PWD/objloader.cpp \
+ $$PWD/texturedata.cpp
diff --git a/src/render/io/texturedata.cpp b/src/render/io/texturedata.cpp
new file mode 100644
index 000000000..3a1b8aa8f
--- /dev/null
+++ b/src/render/io/texturedata.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "texturedata.h"
+
+#include <QDebug>
+#include <QOpenGLTexture>
+
+namespace Qt3D {
+
+Texture::Texture() :
+ m_target(QOpenGLTexture::Target2D),
+ m_width(1),
+ m_height(1),
+ m_depth(1),
+ m_autoMipMap(false)
+{
+}
+
+void Texture::setTarget(QOpenGLTexture::Target target)
+{
+ m_target = target;
+}
+
+void Texture::setSize(int w, int h, int d)
+{
+ m_width = w;
+ m_height = h;
+ m_depth = d;
+}
+
+int Texture::width() const
+{
+ return m_width;
+}
+
+int Texture::height() const
+{
+ return m_height;
+}
+
+int Texture::depth() const
+{
+ return m_depth;
+}
+
+void Texture::setInternalFormat(QOpenGLTexture::TextureFormat format)
+{
+ m_format = format;
+}
+
+bool Texture::setFromQImage(QImage img, int layer)
+{
+ setSize(img.width(), img.height());
+
+ if ((m_target != QOpenGLTexture::Target2D) &&
+ (m_target != QOpenGLTexture::Target2DArray) &&
+ (m_target == QOpenGLTexture::TargetRectangle))
+ {
+ qWarning() << Q_FUNC_INFO << "invalid texture target";
+ return false;
+ }
+
+ TexImageDataPtr dataPtr(new TexImageData(0, layer));
+ dataPtr->setImage(img);
+ addImageData(dataPtr);
+
+ return true;
+}
+
+void Texture::addImageData(TexImageDataPtr imgData)
+{
+ m_data.append(imgData);
+}
+
+QList<TexImageDataPtr> Texture::imageData() const
+{
+ return m_data;
+}
+
+void Texture::setGenerateMipMaps(bool gen)
+{
+ m_autoMipMap = gen;
+}
+
+void Texture::setMinificationFilter(QOpenGLTexture::Filter f)
+{
+ m_minFilter = f;
+}
+
+void Texture::setMagnificationFilter(QOpenGLTexture::Filter f)
+{
+ m_magFilter = f;
+}
+
+void Texture::setWrapMode(QOpenGLTexture::WrapMode wrapMode)
+{
+ m_wrapMode = wrapMode;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+TexImageData::TexImageData(int level, int layer) :
+ m_layer(layer),
+ m_mipMapLevel(level),
+ m_cubeFace(QOpenGLTexture::CubeMapPositiveX),
+ m_isCompressed(false)
+{
+
+}
+
+void TexImageData::setImage(QImage image)
+{
+ QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
+// setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, glImage.bits(), &uploadOptions);
+
+ QByteArray imageBytes((const char*) glImage.constBits(), glImage.byteCount());
+ setData(imageBytes, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
+}
+
+void TexImageData::setData(QByteArray data, QOpenGLTexture::PixelFormat fmt, QOpenGLTexture::PixelType ptype)
+{
+ m_isCompressed = false;
+ m_data = data;
+ m_pixelFormat = fmt;
+ m_pixelType = ptype;
+}
+
+} // namespace Qt3D
diff --git a/src/render/io/texturedata.h b/src/render/io/texturedata.h
new file mode 100644
index 000000000..6ce214c26
--- /dev/null
+++ b/src/render/io/texturedata.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_TEXTUREDATA_H
+#define QT3D_TEXTUREDATA_H
+
+#include <QOpenGLTexture>
+#include <QImage>
+#include <QSharedPointer>
+
+namespace Qt3D {
+
+class TexImageData
+{
+public:
+ TexImageData(int level, int layer);
+
+ QOpenGLTexture::CubeMapFace cubeFace() const
+ { return m_cubeFace; }
+
+ void setCubeFace(QOpenGLTexture::CubeMapFace face);
+
+ int layer() const
+ { return m_layer; }
+
+ int mipMapLevel() const
+ { return m_mipMapLevel; }
+
+ bool isCompressed() const
+ { return m_isCompressed; }
+
+ void setImage(QImage);
+
+ void setData(QByteArray data,
+ QOpenGLTexture::PixelFormat fmt,
+ QOpenGLTexture::PixelType ptype);
+ void setCompressedData(QByteArray data, QOpenGLTexture::PixelFormat fmt);
+
+ QByteArray data() const
+ { return m_data; }
+
+ QOpenGLTexture::PixelFormat pixelFormat() const
+ { return m_pixelFormat; }
+
+ QOpenGLTexture::PixelType pixelType() const
+ { return m_pixelType; }
+
+private:
+ int m_layer, m_mipMapLevel;
+ QOpenGLTexture::CubeMapFace m_cubeFace;
+ QOpenGLTexture::PixelFormat m_pixelFormat;
+ QOpenGLTexture::PixelType m_pixelType;
+
+ bool m_isCompressed;
+ QByteArray m_data;
+};
+
+typedef QSharedPointer<TexImageData> TexImageDataPtr;
+
+class Texture
+{
+public:
+ Texture();
+
+ void setTarget(QOpenGLTexture::Target target);
+
+ void setInternalFormat(QOpenGLTexture::TextureFormat format);
+
+ QOpenGLTexture::TextureFormat format() const
+ { return m_format; }
+
+ QOpenGLTexture::Target target() const
+ { return m_target; }
+
+ /**
+ * @brief setFromQImage - set size and image data based upon a QImage
+ * Can optionally generate mip-map levels automatically too. Target
+ * must be Texture2D, Texture2DArray or TextureRectangle.
+ * @param img - valid QImage. If Texture2D is set, should be power-of-2
+ * dimensions.
+ */
+ bool setFromQImage(QImage img, int layer = 0);
+
+ void addImageData(TexImageDataPtr imgData);
+ QList<TexImageDataPtr> imageData() const;
+
+ void setGenerateMipMaps(bool gen);
+ bool generateMipMaps() const
+ { return m_autoMipMap; }
+
+// sampler data - in the future proxy to a Sampler helper
+ void setMinificationFilter(QOpenGLTexture::Filter f);
+ void setMagnificationFilter(QOpenGLTexture::Filter f);
+
+ QOpenGLTexture::Filter minificationFilter() const
+ { return m_minFilter; }
+
+ QOpenGLTexture::Filter magnificationFilter() const
+ { return m_magFilter; }
+
+ void setWrapMode(QOpenGLTexture::WrapMode wrapMode);
+ QOpenGLTexture::WrapMode wrapMode() const
+ { return m_wrapMode; }
+
+ void setSize(int width, int height=1, int depth=1);
+
+ int width() const;
+ int height() const;
+ int depth() const;
+
+private:
+ QOpenGLTexture::Target m_target;
+ QOpenGLTexture::TextureFormat m_format;
+ int m_width, m_height, m_depth;
+ bool m_autoMipMap;
+
+ QList<TexImageDataPtr> m_data;
+
+ QOpenGLTexture::Filter m_minFilter, m_magFilter;
+ // FIXME, store per direction
+ QOpenGLTexture::WrapMode m_wrapMode;
+};
+
+} // namespace Qt3D
+
+#endif // QT3D_TEXTUREDATA_H
diff --git a/src/render/render.pri b/src/render/render.pri
new file mode 100644
index 000000000..ea2b93bea
--- /dev/null
+++ b/src/render/render.pri
@@ -0,0 +1,3 @@
+include(backend/render-backend.pri)
+include(frontend/render-frontend.pri)
+include(io/render-io.pri)
diff --git a/src/src.pro b/src/src.pro
index ae6a3ae90..f8b0ef3bc 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -1,4 +1,6 @@
TEMPLATE = subdirs
CONFIG += ordered
-SUBDIRS = threed
-qtHaveModule(qml): SUBDIRS += quick3d imports
+SUBDIRS += core
+
+#SUBDIRS += thred
+#qtHaveModule(qml): SUBDIRS += quick3d imports
diff --git a/sync.profile b/sync.profile
index 4cc2ddca0..aec8fc637 100644
--- a/sync.profile
+++ b/sync.profile
@@ -1,4 +1,5 @@
%modules = ( # path to module name map
+ "Qt3DCore" => "$basedir/src/threed",
"Qt3D" => "$basedir/src/threed",
"Qt3DQuick" => "$basedir/src/quick3d",
);