summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2017-01-20 09:10:54 +0000
committerSean Harmer <sean.harmer@kdab.com>2017-01-20 09:11:38 +0000
commit97d8a7bff44af94b4a92624e9431e6e49505432e (patch)
treefb256758cbab4ec79ee5f0bfa196a761c8aefa65
parent28236a292be0f26b2f46b58249e498e153f286dc (diff)
parentcef6d5406267787d22deee75600ee9d3653a3109 (diff)
Merge branch 'dev' into wip/qtquickintegration
-rw-r--r--examples/qt3d/3d-text/3d-text.pro8
-rw-r--r--examples/qt3d/3d-text/main.cpp124
-rw-r--r--examples/qt3d/qt3d.pro3
-rw-r--r--src/extras/3dtext/3dtext.pri11
-rw-r--r--src/extras/3dtext/qtext3dgeometry.cpp525
-rw-r--r--src/extras/3dtext/qtext3dgeometry.h117
-rw-r--r--src/extras/3dtext/qtext3dgeometry_p.h106
-rw-r--r--src/extras/3dtext/qtext3dmesh.cpp179
-rw-r--r--src/extras/3dtext/qtext3dmesh.h97
-rw-r--r--src/extras/extras.pro1
-rw-r--r--src/plugins/sceneparsers/gltf/gltfimporter.cpp26
-rw-r--r--src/plugins/sceneparsers/gltf/gltfimporter.h2
-rw-r--r--src/plugins/sceneparsers/gltfexport/gltfexporter.cpp13
-rw-r--r--src/plugins/sceneparsers/gltfexport/gltfexporter.h3
-rw-r--r--src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp5
-rw-r--r--src/quick3d/quick3drender/items/quick3dbuffer.cpp21
-rw-r--r--src/quick3d/quick3drender/items/quick3dbuffer_p.h2
-rw-r--r--src/render/framegraph/framegraph.pri7
-rw-r--r--src/render/framegraph/qframegraphnode.cpp6
-rw-r--r--src/render/framegraph/qmemorybarrier.cpp160
-rw-r--r--src/render/framegraph/qmemorybarrier.h101
-rw-r--r--src/render/framegraph/qmemorybarrier_p.h77
-rw-r--r--src/render/geometry/qbuffer.cpp2
-rw-r--r--src/render/geometry/qbuffer.h3
-rw-r--r--src/render/graphicshelpers/graphicscontext.cpp12
-rw-r--r--src/render/graphicshelpers/graphicscontext_p.h2
-rw-r--r--src/render/graphicshelpers/graphicshelperes2.cpp10
-rw-r--r--src/render/graphicshelpers/graphicshelperes2_p.h2
-rw-r--r--src/render/graphicshelpers/graphicshelpergl2.cpp10
-rw-r--r--src/render/graphicshelpers/graphicshelpergl2_p.h2
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_2.cpp10
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_2_p.h2
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_3.cpp10
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_3_p.h2
-rw-r--r--src/render/graphicshelpers/graphicshelpergl4.cpp13
-rw-r--r--src/render/graphicshelpers/graphicshelpergl4_p.h2
-rw-r--r--src/render/graphicshelpers/graphicshelperinterface_p.h5
-rw-r--r--src/render/io/glbuffer.cpp8
-rw-r--r--src/render/io/glbuffer_p.h3
-rw-r--r--tests/auto/quick3d/quick3d.pro3
-rw-r--r--tests/auto/quick3d/quick3dbuffer/quick3dbuffer.pro9
-rw-r--r--tests/auto/quick3d/quick3dbuffer/tst_quick3dbuffer.cpp94
-rw-r--r--tests/auto/render/gltfplugins/tst_gltfplugins.cpp12
-rw-r--r--tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp7
-rw-r--r--tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp7
-rw-r--r--tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp7
-rw-r--r--tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp7
-rw-r--r--tests/auto/render/qmemorybarrier/qmemorybarrier.pro12
-rw-r--r--tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp175
-rw-r--r--tests/auto/render/render.pro3
50 files changed, 2005 insertions, 23 deletions
diff --git a/examples/qt3d/3d-text/3d-text.pro b/examples/qt3d/3d-text/3d-text.pro
new file mode 100644
index 000000000..7fa771df4
--- /dev/null
+++ b/examples/qt3d/3d-text/3d-text.pro
@@ -0,0 +1,8 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+QT += core gui 3dcore 3drender 3dinput 3dextras 3drender-private
+
+SOURCES += main.cpp
+
diff --git a/examples/qt3d/3d-text/main.cpp b/examples/qt3d/3d-text/main.cpp
new file mode 100644
index 000000000..40ae8b80a
--- /dev/null
+++ b/examples/qt3d/3d-text/main.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QCoreApplication>
+#include <Qt3DCore/Qt3DCore>
+#include <Qt3DExtras/Qt3DExtras>
+#include <qtext3dmesh.h>
+#include <qtext3dgeometry.h>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication a(argc, argv);
+ Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
+ view->setTitle(QStringLiteral("3D Text CPP"));
+ view->defaultFrameGraph()->setClearColor(QColor(210, 210, 220));
+
+ auto *root = new Qt3DCore::QEntity();
+
+ { // plane
+ auto *plane = new Qt3DCore::QEntity(root);
+ auto *planeMesh = new Qt3DExtras::QPlaneMesh();
+ auto *planeTransform = new Qt3DCore::QTransform();
+ auto *planeMaterial = new Qt3DExtras::QPhongMaterial(root);
+ planeMesh->setWidth(10); planeMesh->setHeight(10);
+ planeTransform->setTranslation(QVector3D(0, 0, 0));
+ planeMaterial->setDiffuse(QColor(150, 150, 150));
+
+ plane->addComponent(planeMaterial);
+ plane->addComponent(planeMesh);
+ plane->addComponent(planeTransform);
+ }
+
+ auto *textMaterial = new Qt3DExtras::QPhongMaterial(root);
+ { // text
+ int i = 0;
+ QStringList fonts = QFontDatabase().families();
+
+ for (QString family : fonts)
+ {
+ auto *text = new Qt3DCore::QEntity(root);
+ auto *textMesh = new Qt3DExtras::QText3DMesh();
+ Qt3DExtras::QText3DGeometry *textGeometry = static_cast<Qt3DExtras::QText3DGeometry*>(textMesh->geometry());
+
+ auto *textTransform = new Qt3DCore::QTransform();
+ QFont font(family, 32, -1, false);
+ textTransform->setTranslation(QVector3D(-2.45f, i * .5f, 0));
+ textTransform->setScale(.2f);
+ textGeometry->setDepth(.45f);
+ textGeometry->setFont(font);
+ textGeometry->setEdgeSplitAngle(90.f * .15f);
+ textGeometry->setText(QString(family));
+ textMaterial->setDiffuse(QColor(111, 150, 255));
+
+ text->addComponent(textMaterial);
+ text->addComponent(textMesh);
+ text->addComponent(textTransform);
+
+ i++;
+ }
+ }
+
+ { // camera
+ float aspect = static_cast<float>(view->screen()->size().width()) / view->screen()->size().height();
+ Qt3DRender::QCamera *camera = view->camera();
+ camera->lens()->setPerspectiveProjection(65.f, aspect, 0.1f, 100.f);
+ camera->setPosition(QVector3D(0, 5, 3));
+ camera->setViewCenter(QVector3D(0, 5, 0));
+
+ auto *cameraController = new Qt3DExtras::QOrbitCameraController(root);
+ cameraController->setCamera(camera);
+ }
+
+ view->setRootEntity(root);
+ view->show();
+
+ return a.exec();
+}
diff --git a/examples/qt3d/qt3d.pro b/examples/qt3d/qt3d.pro
index d6d7437d1..7d0545404 100644
--- a/examples/qt3d/qt3d.pro
+++ b/examples/qt3d/qt3d.pro
@@ -15,7 +15,8 @@ SUBDIRS += \
planets-qml \
instanced-arrays-qml \
lights \
- compute-particles
+ compute-particles \
+ 3d-text
qtHaveModule(multimedia): SUBDIRS += audio-visualizer-qml
diff --git a/src/extras/3dtext/3dtext.pri b/src/extras/3dtext/3dtext.pri
new file mode 100644
index 000000000..bcf2ce948
--- /dev/null
+++ b/src/extras/3dtext/3dtext.pri
@@ -0,0 +1,11 @@
+
+SOURCES += \
+ $$PWD/qtext3dgeometry.cpp \
+ $$PWD/qtext3dmesh.cpp
+
+HEADERS += \
+ $$PWD/qtext3dgeometry.h \
+ $$PWD/qtext3dgeometry_p.h \
+ $$PWD/qtext3dmesh.h
+
+INCLUDEPATH += $$PWD
diff --git a/src/extras/3dtext/qtext3dgeometry.cpp b/src/extras/3dtext/qtext3dgeometry.cpp
new file mode 100644
index 000000000..529c93b79
--- /dev/null
+++ b/src/extras/3dtext/qtext3dgeometry.cpp
@@ -0,0 +1,525 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtext3dgeometry.h"
+#include "qtext3dgeometry_p.h"
+#include <Qt3DRender/qbuffer.h>
+#include <Qt3DRender/qbufferdatagenerator.h>
+#include <Qt3DRender/qattribute.h>
+#include <private/qtriangulator_p.h>
+#include <qmath.h>
+#include <QVector3D>
+#include <QTextLayout>
+#include <QTime>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+namespace {
+
+using IndexType = unsigned short;
+
+struct TriangulationData {
+ struct Outline {
+ int begin;
+ int end;
+ };
+
+ QVector<QVector3D> vertices;
+ QVector<IndexType> indices;
+ QVector<Outline> outlines;
+ QVector<IndexType> outlineIndices;
+ bool inverted;
+};
+
+TriangulationData triangulate(const QString &text, const QFont &font)
+{
+ TriangulationData result;
+ int beginOutline = 0;
+
+ // Initialize path with text and extract polygons
+ QPainterPath path;
+ path.setFillRule(Qt::WindingFill);
+ path.addText(0, 0, font, text);
+ QList<QPolygonF> polygons = path.toSubpathPolygons(QTransform().scale(1.f, -1.f));
+
+ // maybe glyph has no geometry
+ if (polygons.size() == 0)
+ return result;
+
+ const int prevNumIndices = result.indices.size();
+
+ // Reset path and add previously extracted polygons (which where spatially transformed)
+ path = QPainterPath();
+ path.setFillRule(Qt::WindingFill);
+ for (QPolygonF &p : polygons)
+ path.addPolygon(p);
+
+ // Extract polylines out of the path, this allows us to retrive indicies for each glyph outline
+ QPolylineSet polylines = qPolyline(path);
+ QVector<IndexType> tmpIndices;
+ tmpIndices.resize(polylines.indices.size());
+ memcpy(tmpIndices.data(), polylines.indices.data(), polylines.indices.size() * sizeof(IndexType));
+
+ int lastIndex = 0;
+ for (const IndexType idx : tmpIndices) {
+ if (idx == std::numeric_limits<IndexType>::max()) {
+ const int endOutline = lastIndex;
+ result.outlines.push_back({beginOutline, endOutline});
+ beginOutline = endOutline;
+ } else {
+ result.outlineIndices.push_back(idx);
+ ++lastIndex;
+ }
+ }
+
+ // Triangulate path
+ const QTriangleSet triangles = qTriangulate(path);
+
+ // Append new indices to result.indices buffer
+ result.indices.resize(result.indices.size() + triangles.indices.size());
+ memcpy(&result.indices[prevNumIndices], triangles.indices.data(), triangles.indices.size() * sizeof(IndexType));
+ for (int i = prevNumIndices, m = result.indices.size(); i < m; ++i)
+ result.indices[i] += result.vertices.size();
+
+ // Append new triangles to result.vertices
+ result.vertices.reserve(triangles.vertices.size() / 2);
+ for (int i = 0, m = triangles.vertices.size(); i < m; i += 2)
+ result.vertices.push_back(QVector3D(triangles.vertices[i] / font.pointSizeF(), triangles.vertices[i + 1] / font.pointSizeF(), 0.0f));
+
+ return result;
+}
+
+inline QVector3D mix(const QVector3D &a, const QVector3D &b, float ratio)
+{
+ return a + (b - a) * ratio;
+}
+
+} // anonymous namespace
+
+QText3DGeometryPrivate::QText3DGeometryPrivate()
+ : QGeometryPrivate()
+ , m_font(QFont(QStringLiteral("Arial")))
+ , m_depth(1.f)
+ , m_edgeSplitAngle(90.f * 0.1f)
+ , m_positionAttribute(nullptr)
+ , m_normalAttribute(nullptr)
+ , m_indexAttribute(nullptr)
+ , m_vertexBuffer(nullptr)
+ , m_indexBuffer(nullptr)
+{
+ m_font.setPointSize(4);
+}
+
+void QText3DGeometryPrivate::init()
+{
+ Q_Q(QText3DGeometry);
+ m_positionAttribute = new Qt3DRender::QAttribute(q);
+ m_normalAttribute = new Qt3DRender::QAttribute(q);
+ m_indexAttribute = new Qt3DRender::QAttribute(q);
+ m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q);
+ m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q);
+
+ const quint32 elementSize = 3 + 3;
+ const quint32 stride = elementSize * sizeof(float);
+
+ m_positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ m_positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ m_positionAttribute->setVertexSize(3);
+ m_positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ m_positionAttribute->setBuffer(m_vertexBuffer);
+ m_positionAttribute->setByteStride(stride);
+ m_positionAttribute->setByteOffset(0);
+ m_positionAttribute->setCount(0);
+
+ m_normalAttribute->setName(Qt3DRender::QAttribute::defaultNormalAttributeName());
+ m_normalAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ m_normalAttribute->setVertexSize(3);
+ m_normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ m_normalAttribute->setBuffer(m_vertexBuffer);
+ m_normalAttribute->setByteStride(stride);
+ m_normalAttribute->setByteOffset(3 * sizeof(float));
+ m_normalAttribute->setCount(0);
+
+ m_indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
+ m_indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedShort);
+ m_indexAttribute->setBuffer(m_indexBuffer);
+ m_indexAttribute->setCount(0);
+
+ q->addAttribute(m_positionAttribute);
+ q->addAttribute(m_normalAttribute);
+ q->addAttribute(m_indexAttribute);
+
+ update();
+}
+
+/*!
+ * \qmltype Text3DGeometry
+ * \instantiates Qt3DExtras::QText3DGeometry
+ * \inqmlmodule Qt3D.Extras
+ * \brief Text3DGeometry allows creation of a 3D text in 3D space.
+ *
+ * The Text3DGeometry type is most commonly used internally by the Text3DMesh type
+ * but can also be used in custom GeometryRenderer types.
+ */
+
+/*!
+ * \qmlproperty QString Text3DGeometry::text
+ *
+ * Holds the text used for the mesh.
+ */
+
+/*!
+ * \qmlproperty QFont Text3DGeometry::font
+ *
+ * Holds the font of the text.
+ */
+
+/*!
+ * \qmlproperty float Text3DGeometry::depth
+ *
+ * Holds the extrusion depth of the text.
+ */
+
+/*!
+ * \qmlproperty float Text3DGeometry::edgeSplitAngle
+ *
+ * Holds the threshold angle for smooth normals.
+ */
+
+/*!
+ * \qmlproperty Attribute Text3DGeometry::positionAttribute
+ *
+ * Holds the geometry position attribute.
+ */
+
+/*!
+ * \qmlproperty Attribute Text3DGeometry::normalAttribute
+ *
+ * Holds the geometry normal attribute.
+ */
+
+/*!
+ * \qmlproperty Attribute Text3DGeometry::indexAttribute
+ *
+ * Holds the geometry index attribute.
+ */
+
+/*!
+ * \class Qt3DExtras::QText3DGeometry
+ * \inheaderfile Qt3DExtras/QText3DGeometry
+ * \inmodule Qt3DExtras
+ * \brief The QText3DGeometry class allows creation of a 3D text in 3D space.
+ * \since 5.8
+ * \ingroup geometries
+ * \inherits Qt3DRender::QGeometry
+ *
+ * The QText3DGeometry class is most commonly used internally by the QText3DMesh
+ * but can also be used in custom Qt3DRender::QGeometryRenderer subclasses.
+ */
+
+/*!
+ * Constructs a new QText3DGeometry with \a parent.
+ */
+QText3DGeometry::QText3DGeometry(Qt3DCore::QNode *parent)
+ : QGeometry(*new QText3DGeometryPrivate(), parent)
+{
+ Q_D(QText3DGeometry);
+ d->init();
+}
+
+/*!
+ * \internal
+ */
+QText3DGeometry::QText3DGeometry(QText3DGeometryPrivate &dd, Qt3DCore::QNode *parent)
+ : QGeometry(dd, parent)
+{
+ Q_D(QText3DGeometry);
+ d->init();
+}
+
+/*!
+ * \internal
+ */
+QText3DGeometry::~QText3DGeometry()
+{}
+
+/*!
+ * \internal
+ * Updates vertices based on text, font, depth and smoothAngle properties.
+ */
+void QText3DGeometryPrivate::update()
+{
+ if (m_text.trimmed().isEmpty()) // save enough?
+ return;
+
+ TriangulationData data = triangulate(m_text, m_font);
+
+ const int numVertices = data.vertices.size();
+ const int numIndices = data.indices.size();
+
+ struct Vertex {
+ QVector3D position;
+ QVector3D normal;
+ };
+
+ QVector<IndexType> indices;
+ QVector<Vertex> vertices;
+
+ // TODO: keep 'vertices.size()' small when extruding
+ vertices.reserve(data.vertices.size() * 2);
+ for (QVector3D &v : data.vertices) // front face
+ vertices.push_back({ v, // vertex
+ QVector3D(0.0f, 0.0f, -1.0f) }); // normal
+ for (QVector3D &v : data.vertices) // front face
+ vertices.push_back({ QVector3D(v.x(), v.y(), m_depth), // vertex
+ QVector3D(0.0f, 0.0f, 1.0f) }); // normal
+
+ for (int i = 0, verticesIndex = vertices.size(); i < data.outlines.size(); ++i) {
+ const int begin = data.outlines[i].begin;
+ const int end = data.outlines[i].end;
+ const int verticesIndexBegin = verticesIndex;
+
+ QVector3D prevNormal = QVector3D::crossProduct(
+ vertices[data.outlineIndices[end - 1] + numVertices].position - vertices[data.outlineIndices[end - 1]].position,
+ vertices[data.outlineIndices[begin]].position - vertices[data.outlineIndices[end - 1]].position).normalized();
+
+ for (int j = begin; j < end; ++j) {
+ const bool isLastIndex = (j == end - 1);
+ const IndexType cur = data.outlineIndices[j];
+ const IndexType next = data.outlineIndices[((j - begin + 1) % (end - begin)) + begin]; // normalize, bring in range and adjust
+ const QVector3D normal = QVector3D::crossProduct(vertices[cur + numVertices].position - vertices[cur].position, vertices[next].position - vertices[cur].position).normalized();
+
+ // use smooth normals in case of a short angle
+ const bool smooth = QVector3D::dotProduct(prevNormal, normal) > (90.0f - m_edgeSplitAngle) / 90.0f;
+ const QVector3D resultNormal = smooth ? mix(prevNormal, normal, 0.5f) : normal;
+ if (!smooth) {
+ vertices.push_back({vertices[cur].position, prevNormal});
+ vertices.push_back({vertices[cur + numVertices].position, prevNormal});
+ verticesIndex += 2;
+ }
+
+ vertices.push_back({vertices[cur].position, resultNormal});
+ vertices.push_back({vertices[cur + numVertices].position, resultNormal});
+
+ const int v0 = verticesIndex;
+ const int v1 = verticesIndex + 1;
+ const int v2 = isLastIndex ? verticesIndexBegin : verticesIndex + 2;
+ const int v3 = isLastIndex ? verticesIndexBegin + 1 : verticesIndex + 3;
+
+ indices.push_back(v0);
+ indices.push_back(v1);
+ indices.push_back(v2);
+ indices.push_back(v2);
+ indices.push_back(v1);
+ indices.push_back(v3);
+
+ verticesIndex += 2;
+ prevNormal = normal;
+ }
+ }
+
+ { // upload vertices
+ QByteArray data;
+ data.resize(vertices.size() * sizeof(Vertex));
+ memcpy(data.data(), vertices.data(), vertices.size() * sizeof(Vertex));
+
+ m_vertexBuffer->setData(data);
+ m_positionAttribute->setCount(vertices.size());
+ m_normalAttribute->setCount(vertices.size());
+ }
+
+ // resize for following insertions
+ const int indicesOffset = indices.size();
+ indices.resize(indices.size() + numIndices * 2);
+
+ // copy values for back faces
+ IndexType *indicesFaces = indices.data() + indicesOffset;
+ memcpy(indicesFaces, data.indices.data(), numIndices * sizeof(IndexType));
+
+ // insert values for front face and flip triangles
+ for (int j = 0; j < numIndices; j += 3)
+ {
+ indicesFaces[numIndices + j ] = indicesFaces[j ] + numVertices;
+ indicesFaces[numIndices + j + 1] = indicesFaces[j + 2] + numVertices;
+ indicesFaces[numIndices + j + 2] = indicesFaces[j + 1] + numVertices;
+ }
+
+ { // upload indices
+ QByteArray data;
+ data.resize(indices.size() * sizeof(IndexType));
+ memcpy(data.data(), indices.data(), indices.size() * sizeof(IndexType));
+
+ m_indexBuffer->setData(data);
+ m_indexAttribute->setCount(indices.size());
+ }
+}
+
+void QText3DGeometry::setText(QString text)
+{
+ Q_D(QText3DGeometry);
+ if (d->m_text != text) {
+ d->m_text = text;
+ d->update();
+ emit textChanged(text);
+ }
+}
+
+void QText3DGeometry::setFont(QFont font)
+{
+ Q_D(QText3DGeometry);
+ if (d->m_font != font) {
+ d->m_font = font;
+ d->update();
+ emit fontChanged(font);
+ }
+}
+
+void QText3DGeometry::setDepth(float depth)
+{
+ Q_D(QText3DGeometry);
+ if (d->m_depth != depth) {
+ d->m_depth = depth;
+ d->update();
+ emit depthChanged(depth);
+ }
+}
+
+void QText3DGeometry::setEdgeSplitAngle(float smoothAngle)
+{
+ Q_D(QText3DGeometry);
+ if (d->m_edgeSplitAngle != smoothAngle) {
+ d->m_edgeSplitAngle = smoothAngle;
+ d->update();
+ emit edgeSplitAngleChanged(smoothAngle);
+ }
+}
+
+/*!
+ * \property QString Text3DGeometry::text
+ *
+ * Holds the text used for the mesh.
+ */
+QString QText3DGeometry::text() const
+{
+ Q_D(const QText3DGeometry);
+ return d->m_text;
+}
+
+/*!
+ * \property QFont Text3DGeometry::font
+ *
+ * Holds the font of the text.
+ */
+QFont QText3DGeometry::font() const
+{
+ Q_D(const QText3DGeometry);
+ return d->m_font;
+}
+
+/*!
+ * \property float Text3DGeometry::depth
+ *
+ * Holds the extrusion depth of the text.
+ */
+float QText3DGeometry::depth() const
+{
+ Q_D(const QText3DGeometry);
+ return d->m_depth;
+}
+
+/*!
+ * \property float Text3DGeometry::edgeSplitAngle
+ *
+ * Holds the threshold angle for smooth normals.
+ */
+float QText3DGeometry::edgeSplitAngle() const
+{
+ Q_D(const QText3DGeometry);
+ return d->m_edgeSplitAngle;
+}
+
+/*!
+ * \property Text3DGeometry::positionAttribute
+ *
+ * Holds the geometry position attribute.
+ */
+Qt3DRender::QAttribute *QText3DGeometry::positionAttribute() const
+{
+ Q_D(const QText3DGeometry);
+ return d->m_positionAttribute;
+}
+
+/*!
+ * \property Text3DGeometry::normalAttribute
+ *
+ * Holds the geometry normal attribute.
+ */
+Qt3DRender::QAttribute *QText3DGeometry::normalAttribute() const
+{
+ Q_D(const QText3DGeometry);
+ return d->m_normalAttribute;
+}
+
+/*!
+ * \property Text3DGeometry::indexAttribute
+ *
+ * Holds the geometry index attribute.
+ */
+Qt3DRender::QAttribute *QText3DGeometry::indexAttribute() const
+{
+ Q_D(const QText3DGeometry);
+ return d->m_indexAttribute;
+}
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/3dtext/qtext3dgeometry.h b/src/extras/3dtext/qtext3dgeometry.h
new file mode 100644
index 000000000..4cd89b112
--- /dev/null
+++ b/src/extras/3dtext/qtext3dgeometry.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXT3DGEOMETRY_H
+#define QT3DEXTRAS_QTEXT3DGEOMETRY_H
+
+#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DRender/qgeometry.h>
+#include <QString>
+#include <QFont>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QAttribute;
+
+} // namespace Qt3DRender
+
+namespace Qt3DExtras {
+
+class QText3DGeometryPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QText3DGeometry : public Qt3DRender::QGeometry
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(float depth READ depth WRITE setDepth NOTIFY depthChanged)
+ Q_PROPERTY(float edgeSplitAngle READ edgeSplitAngle WRITE setEdgeSplitAngle NOTIFY edgeSplitAngleChanged)
+ Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT)
+ Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT)
+ Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT)
+
+public:
+ explicit QText3DGeometry(Qt3DCore::QNode *parent = nullptr);
+ ~QText3DGeometry();
+
+ Qt3DRender::QAttribute *positionAttribute() const;
+ Qt3DRender::QAttribute *normalAttribute() const;
+ Qt3DRender::QAttribute *indexAttribute() const;
+ QString text() const;
+ QFont font() const;
+ float depth() const;
+ float edgeSplitAngle() const;
+
+public Q_SLOTS:
+ void setText(QString text);
+ void setFont(QFont font);
+ void setDepth(float depth);
+ void setEdgeSplitAngle(float edgeSplitAngle);
+
+Q_SIGNALS:
+ void textChanged(QString text);
+ void fontChanged(QFont font);
+ void depthChanged(float depth);
+ void edgeSplitAngleChanged(float edgeSplitAngle);
+
+protected:
+ QText3DGeometry(QText3DGeometryPrivate &dd, QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QText3DGeometry)
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXT3DGEOMETRY_H
diff --git a/src/extras/3dtext/qtext3dgeometry_p.h b/src/extras/3dtext/qtext3dgeometry_p.h
new file mode 100644
index 000000000..dc5e2f6a7
--- /dev/null
+++ b/src/extras/3dtext/qtext3dgeometry_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXT3DGEOMETRY_P_H
+#define QT3DEXTRAS_QTEXT3DGEOMETRY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qgeometry_p.h>
+#include <QFont>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QAttribute;
+class QBuffer;
+
+} // namespace Qt3DRender
+
+namespace Qt3DExtras {
+
+class QText3DGeometry;
+
+class QText3DGeometryPrivate : public Qt3DRender::QGeometryPrivate
+{
+public:
+ QText3DGeometryPrivate();
+ void init();
+ void update();
+
+ QString m_text;
+ QFont m_font;
+ float m_depth;
+ float m_edgeSplitAngle;
+
+ Qt3DRender::QAttribute *m_positionAttribute;
+ Qt3DRender::QAttribute *m_normalAttribute;
+ Qt3DRender::QAttribute *m_indexAttribute;
+ Qt3DRender::QBuffer *m_vertexBuffer;
+ Qt3DRender::QBuffer *m_indexBuffer;
+
+ Q_DECLARE_PUBLIC(QText3DGeometry)
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXT3DGEOMETRY_P_H
diff --git a/src/extras/3dtext/qtext3dmesh.cpp b/src/extras/3dtext/qtext3dmesh.cpp
new file mode 100644
index 000000000..a89c01a4d
--- /dev/null
+++ b/src/extras/3dtext/qtext3dmesh.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtext3dmesh.h"
+#include "qtext3dgeometry.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+/*!
+ * \qmltype Text3DMesh
+ * \instantiates Qt3DExtras::QText3DMesh
+ * \inqmlmodule Qt3D.Extras
+ * \brief A 3D Text mesh.
+ */
+
+/*!
+ * \qmlproperty QString Text3DMesh::text
+ *
+ * Holds the text used for the mesh.
+ */
+
+/*!
+ * \qmlproperty QFont Text3DMesh::font
+ *
+ * Holds the font of the text.
+ */
+
+/*!
+ * \qmlproperty float Text3DMesh::depth
+ *
+ * Holds the extrusion depth of the text.
+ */
+
+/*!
+ * \qmlproperty float Text3DMesh::edgeSplitAngle
+ *
+ * Holds the threshold angle for smooth normals.
+ */
+
+/*!
+ * \class Qt3DExtras::QText3DMesh
+ * \inheaderfile Qt3DExtras/QText3DMesh
+ * \inmodule Qt3DExtras
+ *
+ * \inherits Qt3DRender::QGeometryRenderer
+ *
+ * \brief A 3D Text mesh.
+ */
+
+/*!
+ * Constructs a new QText3DMesh with \a parent.
+ */
+QText3DMesh::QText3DMesh(Qt3DCore::QNode *parent)
+ : QGeometryRenderer(parent)
+{
+ QText3DGeometry *geometry = new QText3DGeometry();
+ QObject::connect(geometry, &QText3DGeometry::depthChanged, this, &QText3DMesh::depthChanged);
+ QObject::connect(geometry, &QText3DGeometry::textChanged, this, &QText3DMesh::textChanged);
+ QObject::connect(geometry, &QText3DGeometry::fontChanged, this, &QText3DMesh::fontChanged);
+ QObject::connect(geometry, &QText3DGeometry::edgeSplitAngleChanged, this, &QText3DMesh::edgeSplitAngleChanged);
+ QGeometryRenderer::setGeometry(geometry);
+}
+
+/*! \internal */
+QText3DMesh::~QText3DMesh()
+{}
+
+void QText3DMesh::setText(QString text)
+{
+ static_cast<QText3DGeometry*>(geometry())->setText(text);
+}
+
+void QText3DMesh::setFont(QFont font)
+{
+ static_cast<QText3DGeometry*>(geometry())->setFont(font);
+}
+
+void QText3DMesh::setDepth(float depth)
+{
+ static_cast<QText3DGeometry*>(geometry())->setDepth(depth);
+}
+
+void QText3DMesh::setEdgeSplitAngle(float smoothAngle)
+{
+ static_cast<QText3DGeometry*>(geometry())->setEdgeSplitAngle(smoothAngle);
+}
+
+/*!
+ * \property QString QText3DMesh::text
+ *
+ * Holds the text used for the mesh.
+ */
+QString QText3DMesh::text()
+{
+ return static_cast<QText3DGeometry*>(geometry())->text();
+}
+
+/*!
+ * \property QFont QText3DMesh::font
+ *
+ * Holds the font of the text.
+ */
+QFont QText3DMesh::font()
+{
+ return static_cast<QText3DGeometry*>(geometry())->font();
+}
+
+/*!
+ * \property float QText3DMesh::depth
+ *
+ * Holds the extrusion depth of the text.
+ */
+float QText3DMesh::depth()
+{
+ return static_cast<QText3DGeometry*>(geometry())->depth();
+}
+
+/*!
+ * \property float QText3DMesh::edgeSplitAngle
+ *
+ * Holds the threshold angle for smooth normals.
+ */
+float QText3DMesh::edgeSplitAngle()
+{
+ return static_cast<QText3DGeometry*>(geometry())->edgeSplitAngle();
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/3dtext/qtext3dmesh.h b/src/extras/3dtext/qtext3dmesh.h
new file mode 100644
index 000000000..6bb546675
--- /dev/null
+++ b/src/extras/3dtext/qtext3dmesh.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXT3DMESH_H
+#define QT3DEXTRAS_QTEXT3DMESH_H
+
+#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DRender/qgeometryrenderer.h>
+#include <QString>
+#include <QFont>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QT3DEXTRASSHARED_EXPORT QText3DMesh : public Qt3DRender::QGeometryRenderer
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(float depth READ depth WRITE setDepth NOTIFY depthChanged)
+ Q_PROPERTY(float edgeSplitAngle READ edgeSplitAngle WRITE setEdgeSplitAngle NOTIFY edgeSplitAngleChanged)
+
+public:
+ QText3DMesh(Qt3DCore::QNode *parent = nullptr);
+ ~QText3DMesh();
+
+ QString text();
+ QFont font();
+ float depth();
+ float edgeSplitAngle();
+
+public Q_SLOTS:
+ void setText(QString text);
+ void setFont(QFont font);
+ void setDepth(float depth);
+ void setEdgeSplitAngle(float edgeSplitAngle);
+
+Q_SIGNALS:
+ void textChanged(QString text);
+ void fontChanged(QFont font);
+ void depthChanged(float depth);
+ void edgeSplitAngleChanged(float edgeSplitAngle);
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXT3DMESH_H
diff --git a/src/extras/extras.pro b/src/extras/extras.pro
index a7bbc7f66..d723554ca 100644
--- a/src/extras/extras.pro
+++ b/src/extras/extras.pro
@@ -10,6 +10,7 @@ DEFINES += QT_NO_FOREACH
load(qt_module)
include (geometries/geometries.pri)
+include (3dtext/3dtext.pri)
include (defaults/defaults.pri)
HEADERS += \
diff --git a/src/plugins/sceneparsers/gltf/gltfimporter.cpp b/src/plugins/sceneparsers/gltf/gltfimporter.cpp
index e5434da3f..c026594bf 100644
--- a/src/plugins/sceneparsers/gltf/gltfimporter.cpp
+++ b/src/plugins/sceneparsers/gltf/gltfimporter.cpp
@@ -213,6 +213,9 @@
#define KEY_EFFECT QLatin1String("effect")
#define KEY_EFFECTS QLatin1String("effects")
#define KEY_PROPERTIES QLatin1String("properties")
+#define KEY_POSITION QLatin1String("position")
+#define KEY_UPVECTOR QLatin1String("upVector")
+#define KEY_VIEW_CENTER QLatin1String("viewCenter")
QT_BEGIN_NAMESPACE
@@ -380,7 +383,8 @@ Qt3DCore::QEntity* GLTFImporter::node(const QString &id)
const auto translation = jsonObj.value(KEY_TRANSLATION);
const auto scale = jsonObj.value(KEY_SCALE);
Qt3DCore::QTransform *trans = nullptr;
- QCameraLens* cameraLens = nullptr;
+ QCameraLens *cameraLens = nullptr;
+ QCamera *cameraEntity = nullptr;
// If the node contains no meshes, results will still be null here.
// If the node has camera and transform, promote it to QCamera, as that makes it more
@@ -389,10 +393,10 @@ Qt3DCore::QEntity* GLTFImporter::node(const QString &id)
if (!cameraVal.isUndefined()
&& (!matrix.isUndefined() || !rotation.isUndefined() || !translation.isUndefined()
|| !scale.isUndefined())) {
- auto camera = new QCamera;
- trans = camera->transform();
- cameraLens = camera->lens();
- result = camera;
+ cameraEntity = new QCamera;
+ trans = cameraEntity->transform();
+ cameraLens = cameraEntity->lens();
+ result = cameraEntity;
} else {
result = new QEntity;
}
@@ -460,7 +464,7 @@ Qt3DCore::QEntity* GLTFImporter::node(const QString &id)
const bool newLens = cameraLens == nullptr;
if (newLens)
cameraLens = new QCameraLens;
- if (!fillCameraLens(*cameraLens, cameraVal.toString())) {
+ if (!fillCamera(*cameraLens, cameraEntity, cameraVal.toString())) {
qCWarning(GLTFImporterLog, "failed to build camera: %ls on node %ls",
qUtf16PrintableImpl(cameraVal.toString()), qUtf16PrintableImpl(id));
} else if (newLens) {
@@ -925,7 +929,7 @@ QMaterial* GLTFImporter::material(const QString &id)
return mat;
}
-bool GLTFImporter::fillCameraLens(QCameraLens &lens, const QString &id) const
+bool GLTFImporter::fillCamera(QCameraLens &lens, QCamera *cameraEntity, const QString &id) const
{
const auto jsonVal = m_json.object().value(KEY_CAMERAS).toObject().value(id);
if (Q_UNLIKELY(jsonVal.isUndefined())) {
@@ -973,6 +977,14 @@ bool GLTFImporter::fillCameraLens(QCameraLens &lens, const QString &id) const
qUtf16PrintableImpl(id), qUtf16PrintableImpl(camTy));
return false;
}
+ if (cameraEntity) {
+ if (jsonObj.contains(KEY_POSITION))
+ cameraEntity->setPosition(jsonArrToVec3(jsonObj.value(KEY_POSITION).toArray()));
+ if (jsonObj.contains(KEY_UPVECTOR))
+ cameraEntity->setUpVector(jsonArrToVec3(jsonObj.value(KEY_UPVECTOR).toArray()));
+ if (jsonObj.contains(KEY_VIEW_CENTER))
+ cameraEntity->setViewCenter(jsonArrToVec3(jsonObj.value(KEY_VIEW_CENTER).toArray()));
+ }
renameFromJson(jsonObj, &lens);
return true;
}
diff --git a/src/plugins/sceneparsers/gltf/gltfimporter.h b/src/plugins/sceneparsers/gltf/gltfimporter.h
index 8f6b9b356..e97148600 100644
--- a/src/plugins/sceneparsers/gltf/gltfimporter.h
+++ b/src/plugins/sceneparsers/gltf/gltfimporter.h
@@ -147,7 +147,7 @@ private:
Qt3DCore::QEntity *defaultScene();
QMaterial *material(const QString &id);
- bool fillCameraLens(QCameraLens &lens, const QString &id) const;
+ bool fillCamera(QCameraLens &lens, QCamera *cameraEntity, const QString &id) const;
void parse();
void cleanup();
diff --git a/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp b/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp
index befe7770d..7332fa6b5 100644
--- a/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp
+++ b/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp
@@ -961,6 +961,7 @@ void GLTFExporter::parseCameras()
{
qCDebug(GLTFExporterLog, "Parsing cameras...");
int cameraCount = 0;
+
for (auto it = m_cameraMap.constBegin(); it != m_cameraMap.constEnd(); ++it) {
QCameraLens *camera = it.value();
CameraInfo c;
@@ -984,7 +985,12 @@ void GLTFExporter::parseCameras()
c.zfar = camera->farPlane();
// GLTF cameras point in -Z by default, the rest is in the
- // node matrix, so no separate look-at params given here.
+ // node matrix, so no separate look-at params given here, unless it's actually QCamera.
+ QCamera *cameraEntity = nullptr;
+ const QVector<QEntity *> entities = camera->entities();
+ if (entities.size() == 1)
+ cameraEntity = qobject_cast<QCamera *>(entities.at(0));
+ c.cameraEntity = cameraEntity;
m_cameraInfo.insert(camera, c);
if (GLTFExporterLog().isDebugEnabled()) {
@@ -1259,6 +1265,11 @@ bool GLTFExporter::saveScene()
camera["type"] = QStringLiteral("orthographic");
camera["orthographic"] = proj;
}
+ if (camInfo.cameraEntity) {
+ camera["position"] = vec2jsvec(camInfo.cameraEntity->position());
+ camera["upVector"] = vec2jsvec(camInfo.cameraEntity->upVector());
+ camera["viewCenter"] = vec2jsvec(camInfo.cameraEntity->viewCenter());
+ }
camera["name"] = camInfo.originalName;
cameras[camInfo.name] = camera;
}
diff --git a/src/plugins/sceneparsers/gltfexport/gltfexporter.h b/src/plugins/sceneparsers/gltfexport/gltfexporter.h
index e43bfe29c..07d852fd4 100644
--- a/src/plugins/sceneparsers/gltfexport/gltfexporter.h
+++ b/src/plugins/sceneparsers/gltfexport/gltfexporter.h
@@ -72,6 +72,7 @@ class QTransform;
namespace Qt3DRender {
+class QCamera;
class QCameraLens;
class QMaterial;
class QGeometryRenderer;
@@ -196,6 +197,8 @@ private:
// Orthographic properties
float xmag;
float ymag;
+
+ QCamera *cameraEntity;
};
struct LightInfo {
diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
index 2746c62b2..b20e416c2 100644
--- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
+++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
@@ -50,6 +50,8 @@
#include <Qt3DExtras/qplanegeometry.h>
#include <Qt3DExtras/qconegeometry.h>
#include <Qt3DExtras/qcylindergeometry.h>
+#include <Qt3DExtras/qtext3dgeometry.h>
+#include <Qt3DExtras/qtext3dmesh.h>
#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
@@ -98,6 +100,9 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DExtras::QSphereMesh>(uri, 2, 0, "SphereMesh");
qmlRegisterType<Qt3DExtras::QSphereGeometry>(uri, 2, 0, "SphereGeometry");
+ // 3D Text
+ qmlRegisterType<Qt3DExtras::QText3DGeometry>(uri, 2, 2, "Text3DGeometry");
+ qmlRegisterType<Qt3DExtras::QText3DMesh>(uri, 2, 2, "Text3DMesh");
// Register types provided as QML files compiled into the plugin
for (int i = 0; i < int(sizeof(qmldir) / sizeof(qmldir[0])); i++) {
diff --git a/src/quick3d/quick3drender/items/quick3dbuffer.cpp b/src/quick3d/quick3drender/items/quick3dbuffer.cpp
index 5701adf07..d36ce8341 100644
--- a/src/quick3d/quick3drender/items/quick3dbuffer.cpp
+++ b/src/quick3d/quick3drender/items/quick3dbuffer.cpp
@@ -45,6 +45,8 @@
#include <QtQml/private/qjsvalue_p.h>
#include <QtQml/private/qv4typedarray_p.h>
#include <QtQml/private/qv4arraybuffer_p.h>
+#include <Qt3DRender/private/qurlhelper_p.h>
+#include <QtCore/qfile.h>
QT_BEGIN_NAMESPACE
@@ -107,6 +109,25 @@ void Quick3DBuffer::updateData(int offset, const QVariant &bufferData)
}
}
+/*!
+ \qmlmethod string Quick3DBuffer::readBinaryFile(url &fileUrl)
+
+ Reads the binary at \a fileUrl and return it as a QByteArray wrapped in a
+ QVariant
+
+ \note this is provided as convenience for QML where reading files and creating
+ QByteArray is not possible
+ */
+QVariant Quick3DBuffer::readBinaryFile(const QUrl &fileUrl)
+{
+ QFile f(Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(fileUrl));
+ QByteArray data;
+
+ if (f.open(QIODevice::ReadOnly))
+ data = f.readAll();
+ return QVariant(data);
+}
+
void Quick3DBuffer::initEngines()
{
if (m_engine == nullptr) {
diff --git a/src/quick3d/quick3drender/items/quick3dbuffer_p.h b/src/quick3d/quick3drender/items/quick3dbuffer_p.h
index c5cb39cdf..d8dbafcb2 100644
--- a/src/quick3d/quick3drender/items/quick3dbuffer_p.h
+++ b/src/quick3d/quick3drender/items/quick3dbuffer_p.h
@@ -79,6 +79,8 @@ public:
QVariant bufferData() const;
void setBufferData(const QVariant &bufferData);
+ Q_INVOKABLE QVariant readBinaryFile(const QUrl &fileUrl);
+
public Q_SLOTS:
void updateData(int offset, const QVariant &bytes);
diff --git a/src/render/framegraph/framegraph.pri b/src/render/framegraph/framegraph.pri
index 523fecd05..622ca9fb9 100644
--- a/src/render/framegraph/framegraph.pri
+++ b/src/render/framegraph/framegraph.pri
@@ -46,7 +46,9 @@ HEADERS += \
$$PWD/qrendercapture_p.h \
$$PWD/rendercapture_p.h \
$$PWD/qframegraphnodecreatedchange.h \
- $$PWD/qframegraphnodecreatedchange_p.h
+ $$PWD/qframegraphnodecreatedchange_p.h \
+ $$PWD/qmemorybarrier.h \
+ $$PWD/qmemorybarrier_p.h
SOURCES += \
$$PWD/cameraselectornode.cpp \
@@ -80,4 +82,5 @@ SOURCES += \
$$PWD/rendersurfaceselector.cpp \
$$PWD/qrendercapture.cpp \
$$PWD/rendercapture.cpp \
- $$PWD/qframegraphnodecreatedchange.cpp
+ $$PWD/qframegraphnodecreatedchange.cpp \
+ $$PWD/qmemorybarrier.cpp
diff --git a/src/render/framegraph/qframegraphnode.cpp b/src/render/framegraph/qframegraphnode.cpp
index 92f07ad06..0a60edef7 100644
--- a/src/render/framegraph/qframegraphnode.cpp
+++ b/src/render/framegraph/qframegraphnode.cpp
@@ -106,6 +106,9 @@ QFrameGraphNodePrivate::QFrameGraphNodePrivate()
\row
\li Qt3DRender::QViewport
\li Specify viewport
+ \row
+ \li Qt3DRender::QMemoryBarrier
+ \li Places a memory barrier
\endtable
*/
@@ -167,6 +170,9 @@ QFrameGraphNodePrivate::QFrameGraphNodePrivate()
\row
\li Viewport
\li Specify viewport
+ \row
+ \li MemoryBarrier
+ \li Places a memory barrier
\endtable
*/
diff --git a/src/render/framegraph/qmemorybarrier.cpp b/src/render/framegraph/qmemorybarrier.cpp
new file mode 100644
index 000000000..37df337a5
--- /dev/null
+++ b/src/render/framegraph/qmemorybarrier.cpp
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmemorybarrier.h"
+#include "qmemorybarrier_p.h"
+#include <Qt3DRender/qframegraphnodecreatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+/*!
+ \class Qt3DRender::QMemoryBarrier
+ \inmodule Qt3DRender
+ \since 5.9
+ \ingroup framegraph
+ \brief Class to emplace a memory barrier
+
+ A Qt3DRender::QMemoryBarrier FrameGraph node is used to emplace a specific
+ memory barrier at a specific time of the rendering. This is required to
+ properly synchronize drawing and compute commands on the GPU.
+
+ The barrier defines the ordering of memory operations issued by a prior
+ command. This means that if command1 is manipulating a buffer that is to be
+ used as a vertex attribute buffer in a following command2, then the memory
+ barrier should be placed after command1 and setting the appropriate barrier
+ type for vertex attribute buffer.
+
+ For OpenGL rendering, this page gives more info about the
+ \l {https://www.opengl.org/wiki/Memory_Model}{Memory Model}
+ */
+
+/*!
+ \qmltype MemoryBarrier
+ \inqmlmodule Qt3D.Render
+ \instantiates Qt3DRender::QMemoryBarrier
+ \inherits FrameGraphNode
+ \since 5.9
+ \brief Class to place a memory barrier
+
+ A MemoryBarrier FrameGraph node is used to emplace a specific
+ memory barrier at a specific time of the rendering. This is required to
+ properly synchronize drawing and compute commands on the GPU.
+
+ The barrier defines the ordering of memory operations issued by a prior
+ command. This means that if command1 is manipulating a buffer that is to be
+ used as a vertex attribute buffer in a following command2, then the memory
+ barrier should be placed after command1 and setting the appropriate barrier
+ type for vertex attribute buffer.
+
+ For OpenGL rendering, this page gives more info about the
+ \l {https://www.opengl.org/wiki/Memory_Model}{Memory Model}
+*/
+
+/*!
+ \enum QMemoryBarrier::BarrierType
+
+ This enum type describes types of buffer to be cleared.
+ \value None
+ \value ElementArrayBarrier
+ \value UniformBarrier
+ \value TextureFetchBarrier
+ \value ShaderImageAccessBarrier
+ \value CommandBarrier
+ \value PixelBufferBarrier
+ \value TextureUpdateBarrier
+ \value BufferUpdateBarrier
+ \value FrameBufferBarrier
+ \value TransformFeedbackBarrier
+ \value AtomicCounterBarrier
+ \value ShaderStorageBarrier
+ \value QueryBufferBarrier
+ \value AllBarrier
+*/
+
+
+QMemoryBarrierPrivate::QMemoryBarrierPrivate()
+ : QFrameGraphNodePrivate()
+ , m_barrierTypes(QMemoryBarrier::None)
+{
+}
+
+QMemoryBarrier::QMemoryBarrier(Qt3DCore::QNode *parent)
+ : QFrameGraphNode(*new QMemoryBarrierPrivate(), parent)
+{
+}
+
+QMemoryBarrier::~QMemoryBarrier()
+{
+}
+
+void QMemoryBarrier::setBarrierTypes(QMemoryBarrier::BarrierTypes barrierTypes)
+{
+ Q_D(QMemoryBarrier);
+ if (barrierTypes != d->m_barrierTypes) {
+ d->m_barrierTypes = barrierTypes;
+ emit barrierTypesChanged(barrierTypes);
+ }
+}
+
+QMemoryBarrier::BarrierTypes QMemoryBarrier::barrierTypes() const
+{
+ Q_D(const QMemoryBarrier);
+ return d->m_barrierTypes;
+}
+
+QMemoryBarrier::QMemoryBarrier(QMemoryBarrierPrivate &dd, Qt3DCore::QNode *parent)
+ : QFrameGraphNode(dd, parent)
+{
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QMemoryBarrier::createNodeCreationChange() const
+{
+ auto creationChange = QFrameGraphNodeCreatedChangePtr<QMemoryBarrierData>::create(this);
+ QMemoryBarrierData &data = creationChange->data;
+ Q_D(const QMemoryBarrier);
+ data.barrierTypes = d->m_barrierTypes;
+ return creationChange;
+}
+
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/framegraph/qmemorybarrier.h b/src/render/framegraph/qmemorybarrier.h
new file mode 100644
index 000000000..8ad7d6232
--- /dev/null
+++ b/src/render/framegraph/qmemorybarrier.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QMEMORYBARRIER_H
+#define QT3DRENDER_QMEMORYBARRIER_H
+
+#include <Qt3DRender/qframegraphnode.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QMemoryBarrierPrivate;
+
+class QT3DRENDERSHARED_EXPORT QMemoryBarrier : public QFrameGraphNode
+{
+ Q_OBJECT
+ Q_PROPERTY(QMemoryBarrier::BarrierTypes barrierTypes READ barrierTypes WRITE setBarrierTypes NOTIFY barrierTypesChanged)
+public:
+ explicit QMemoryBarrier(Qt3DCore::QNode *parent = nullptr);
+ ~QMemoryBarrier();
+
+ enum BarrierType {
+ None = 0,
+ VertexAttributeArrayBarrier = (1 << 0),
+ ElementArrayBarrier = (1 << 1),
+ UniformBarrier = (1 << 2),
+ TextureFetchBarrier = (1 << 3),
+ ShaderImageAccessBarrier = (1 << 4),
+ CommandBarrier = (1 << 5),
+ PixelBufferBarrier = (1 << 6),
+ TextureUpdateBarrier = (1 << 7),
+ BufferUpdateBarrier = (1 << 8),
+ FrameBufferBarrier = (1 << 9),
+ TransformFeedbackBarrier = (1 << 10),
+ AtomicCounterBarrier = (1 << 11),
+ ShaderStorageBarrier = (1 << 12),
+ QueryBufferBarrier = (1 << 13),
+ AllBarrier = (1 << 14)
+ };
+ Q_ENUM(BarrierType)
+ Q_DECLARE_FLAGS(BarrierTypes, BarrierType)
+
+public Q_SLOTS:
+ void setBarrierTypes(QMemoryBarrier::BarrierTypes barrierTypes);
+ BarrierTypes barrierTypes() const;
+
+Q_SIGNALS:
+ void barrierTypesChanged(QMemoryBarrier::BarrierTypes barrierTypes);
+
+protected:
+ explicit QMemoryBarrier(QMemoryBarrierPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QMemoryBarrier)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+};
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DRender::QMemoryBarrier::BarrierTypes)
+
+#endif // QT3DRENDER_QMEMORYBARRIER_H
diff --git a/src/render/framegraph/qmemorybarrier_p.h b/src/render/framegraph/qmemorybarrier_p.h
new file mode 100644
index 000000000..09df0c89c
--- /dev/null
+++ b/src/render/framegraph/qmemorybarrier_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QMEMORYBARRIER_P_H
+#define QT3DRENDER_QMEMORYBARRIER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qframegraphnode_p.h>
+#include <Qt3DRender/qmemorybarrier.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QMemoryBarrierPrivate : public QFrameGraphNodePrivate
+{
+public:
+ QMemoryBarrierPrivate();
+
+ Q_DECLARE_PUBLIC(QMemoryBarrier)
+ QMemoryBarrier::BarrierTypes m_barrierTypes;
+};
+
+struct QMemoryBarrierData
+{
+ QMemoryBarrier::BarrierTypes barrierTypes;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+#endif // QT3DRENDER_QMEMORYBARRIER_P_H
diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp
index 02417f978..0d3be8fdd 100644
--- a/src/render/geometry/qbuffer.cpp
+++ b/src/render/geometry/qbuffer.cpp
@@ -214,6 +214,8 @@ QBufferPrivate::QBufferPrivate()
* GL_UNIFORM_BUFFER
* \value ShaderStorageBuffer
* GL_SHADER_STORAGE_BUFFER
+ * \value DrawIndirectBuffer
+ * GL_DRAW_INDIRECT_BUFFER
*/
/*!
diff --git a/src/render/geometry/qbuffer.h b/src/render/geometry/qbuffer.h
index 3827b04c9..8b47de918 100644
--- a/src/render/geometry/qbuffer.h
+++ b/src/render/geometry/qbuffer.h
@@ -68,7 +68,8 @@ public:
PixelPackBuffer = 0x88EB, // GL_PIXEL_PACK_BUFFER
PixelUnpackBuffer = 0x88EC, // GL_PIXEL_UNPACK_BUFFER
UniformBuffer = 0x8A11, // GL_UNIFORM_BUFFER
- ShaderStorageBuffer = 0x90D2 // GL_SHADER_STORAGE_BUFFER
+ ShaderStorageBuffer = 0x90D2, // GL_SHADER_STORAGE_BUFFER
+ DrawIndirectBuffer = 0x8F3F // GL_DRAW_INDIRECT_BUFFER
};
Q_ENUM(BufferType) // LCOV_EXCL_LINE
diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp
index 4a9d16e89..f7ba5c3c4 100644
--- a/src/render/graphicshelpers/graphicscontext.cpp
+++ b/src/render/graphicshelpers/graphicscontext.cpp
@@ -858,6 +858,13 @@ void GraphicsContext::drawElements(GLenum primitiveType,
baseVertex);
}
+void GraphicsContext::drawElementsIndirect(GLenum mode,
+ GLenum type,
+ void *indirect)
+{
+ m_glHelper->drawElementsIndirect(mode, type, indirect);
+}
+
/*!
* Wraps an OpenGL call to glDrawArrays.
*/
@@ -870,6 +877,11 @@ void GraphicsContext::drawArrays(GLenum primitiveType,
count);
}
+void GraphicsContext::drawArraysIndirect(GLenum mode, void *indirect)
+{
+ m_glHelper->drawArraysIndirect(mode, indirect);
+}
+
void GraphicsContext::setVerticesPerPatch(GLint verticesPerPatch)
{
m_glHelper->setVerticesPerPatch(verticesPerPatch);
diff --git a/src/render/graphicshelpers/graphicscontext_p.h b/src/render/graphicshelpers/graphicscontext_p.h
index 8067bb8b8..65830bf09 100644
--- a/src/render/graphicshelpers/graphicscontext_p.h
+++ b/src/render/graphicshelpers/graphicscontext_p.h
@@ -206,9 +206,11 @@ public:
void disablePrimitiveRestart();
void dispatchCompute(int x, int y, int z);
void drawArrays(GLenum primitiveType, GLint first, GLsizei count);
+ void drawArraysIndirect(GLenum mode,void *indirect);
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances);
void drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseinstance);
void drawElements(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void * indices, GLint baseVertex);
+ void drawElementsIndirect(GLenum mode, GLenum type, void *indirect);
void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void * indices, GLsizei instances, GLint baseVertex, GLint baseInstance);
void enableClipPlane(int clipPlane);
void enablei(GLenum cap, GLuint index);
diff --git a/src/render/graphicshelpers/graphicshelperes2.cpp b/src/render/graphicshelpers/graphicshelperes2.cpp
index 1335b250f..9fe44cc2f 100644
--- a/src/render/graphicshelpers/graphicshelperes2.cpp
+++ b/src/render/graphicshelpers/graphicshelperes2.cpp
@@ -156,6 +156,16 @@ void GraphicsHelperES2::drawArrays(GLenum primitiveType,
count);
}
+void GraphicsHelperES2::drawElementsIndirect(GLenum, GLenum, void *)
+{
+ qWarning() << "Indirect Drawing is not supported with OpenGL ES 2";
+}
+
+void GraphicsHelperES2::drawArraysIndirect(GLenum , void *)
+{
+ qWarning() << "Indirect Drawing is not supported with OpenGL ES 2";
+}
+
void GraphicsHelperES2::setVerticesPerPatch(GLint verticesPerPatch)
{
Q_UNUSED(verticesPerPatch);
diff --git a/src/render/graphicshelpers/graphicshelperes2_p.h b/src/render/graphicshelpers/graphicshelperes2_p.h
index 17249ef23..263d04055 100644
--- a/src/render/graphicshelpers/graphicshelperes2_p.h
+++ b/src/render/graphicshelpers/graphicshelperes2_p.h
@@ -90,10 +90,12 @@ public:
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
+ void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
void drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseInstance) Q_DECL_OVERRIDE;
void drawBuffers(GLsizei n, const int *bufs) Q_DECL_OVERRIDE;
void drawElements(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLint baseVertex = 0) Q_DECL_OVERRIDE;
+ void drawElementsIndirect(GLenum mode, GLenum type, void *indirect) Q_DECL_OVERRIDE;
void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) Q_DECL_OVERRIDE;
void enableClipPlane(int clipPlane) Q_DECL_OVERRIDE;
void enablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
diff --git a/src/render/graphicshelpers/graphicshelpergl2.cpp b/src/render/graphicshelpers/graphicshelpergl2.cpp
index 8ee0c020b..10cfb1051 100644
--- a/src/render/graphicshelpers/graphicshelpergl2.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl2.cpp
@@ -139,6 +139,16 @@ void GraphicsHelperGL2::drawArrays(GLenum primitiveType,
count);
}
+void GraphicsHelperGL2::drawElementsIndirect(GLenum, GLenum, void *)
+{
+ qWarning() << "Indirect Drawing is not supported with OpenGL 2";
+}
+
+void GraphicsHelperGL2::drawArraysIndirect(GLenum , void *)
+{
+ qWarning() << "Indirect Drawing is not supported with OpenGL 2";
+}
+
void GraphicsHelperGL2::setVerticesPerPatch(GLint verticesPerPatch)
{
Q_UNUSED(verticesPerPatch);
diff --git a/src/render/graphicshelpers/graphicshelpergl2_p.h b/src/render/graphicshelpers/graphicshelpergl2_p.h
index cfd90eab7..09ac1e8ca 100644
--- a/src/render/graphicshelpers/graphicshelpergl2_p.h
+++ b/src/render/graphicshelpers/graphicshelpergl2_p.h
@@ -92,10 +92,12 @@ public:
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
+ void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
void drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseInstance) Q_DECL_OVERRIDE;
void drawBuffers(GLsizei n, const int *bufs) Q_DECL_OVERRIDE;
void drawElements(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLint baseVertex = 0) Q_DECL_OVERRIDE;
+ void drawElementsIndirect(GLenum mode, GLenum type, void *indirect) Q_DECL_OVERRIDE;
void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) Q_DECL_OVERRIDE;
void enableClipPlane(int clipPlane) Q_DECL_OVERRIDE;
void enablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
diff --git a/src/render/graphicshelpers/graphicshelpergl3_2.cpp b/src/render/graphicshelpers/graphicshelpergl3_2.cpp
index 47e9414ca..08850f3b8 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_2.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl3_2.cpp
@@ -159,6 +159,16 @@ void GraphicsHelperGL3_2::drawArrays(GLenum primitiveType,
count);
}
+void GraphicsHelperGL3_2::drawElementsIndirect(GLenum, GLenum, void *)
+{
+ qWarning() << "Indirect Drawing is not supported with OpenGL 3.2";
+}
+
+void GraphicsHelperGL3_2::drawArraysIndirect(GLenum , void *)
+{
+ qWarning() << "Indirect Drawing is not supported with OpenGL 3.2";
+}
+
void GraphicsHelperGL3_2::setVerticesPerPatch(GLint verticesPerPatch)
{
#if defined(QT_OPENGL_4)
diff --git a/src/render/graphicshelpers/graphicshelpergl3_2_p.h b/src/render/graphicshelpers/graphicshelpergl3_2_p.h
index 1ee716a76..3a51c848a 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_2_p.h
+++ b/src/render/graphicshelpers/graphicshelpergl3_2_p.h
@@ -94,10 +94,12 @@ public:
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
+ void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
void drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseInstance) Q_DECL_OVERRIDE;
void drawBuffers(GLsizei n, const int *bufs) Q_DECL_OVERRIDE;
void drawElements(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLint baseVertex = 0) Q_DECL_OVERRIDE;
+ void drawElementsIndirect(GLenum mode, GLenum type, void *indirect) Q_DECL_OVERRIDE;
void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) Q_DECL_OVERRIDE;
void enableClipPlane(int clipPlane) Q_DECL_OVERRIDE;
void enablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
diff --git a/src/render/graphicshelpers/graphicshelpergl3_3.cpp b/src/render/graphicshelpers/graphicshelpergl3_3.cpp
index 7f0223af2..ed27ee186 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_3.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl3_3.cpp
@@ -149,6 +149,11 @@ void GraphicsHelperGL3_3::drawElements(GLenum primitiveType,
baseVertex);
}
+void GraphicsHelperGL3_3::drawElementsIndirect(GLenum, GLenum, void *)
+{
+ qWarning() << "Indirect Drawing is not supported with OpenGL 3";
+}
+
void GraphicsHelperGL3_3::drawArrays(GLenum primitiveType,
GLint first,
GLsizei count)
@@ -158,6 +163,11 @@ void GraphicsHelperGL3_3::drawArrays(GLenum primitiveType,
count);
}
+void GraphicsHelperGL3_3::drawArraysIndirect(GLenum , void *)
+{
+ qWarning() << "Indirect Drawing is not supported with OpenGL 3";
+}
+
void GraphicsHelperGL3_3::setVerticesPerPatch(GLint verticesPerPatch)
{
#if defined(QT_OPENGL_4)
diff --git a/src/render/graphicshelpers/graphicshelpergl3_3_p.h b/src/render/graphicshelpers/graphicshelpergl3_3_p.h
index b2ea8abca..eb749e742 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_3_p.h
+++ b/src/render/graphicshelpers/graphicshelpergl3_3_p.h
@@ -94,10 +94,12 @@ public:
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
+ void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
void drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseInstance) Q_DECL_OVERRIDE;
void drawBuffers(GLsizei n, const int *bufs) Q_DECL_OVERRIDE;
void drawElements(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLint baseVertex = 0) Q_DECL_OVERRIDE;
+ void drawElementsIndirect(GLenum mode, GLenum type, void *indirect) Q_DECL_OVERRIDE;
void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) Q_DECL_OVERRIDE;
void enableClipPlane(int clipPlane) Q_DECL_OVERRIDE;
void enablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
diff --git a/src/render/graphicshelpers/graphicshelpergl4.cpp b/src/render/graphicshelpers/graphicshelpergl4.cpp
index 81a6846e0..dd2f5121c 100644
--- a/src/render/graphicshelpers/graphicshelpergl4.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl4.cpp
@@ -140,6 +140,13 @@ void GraphicsHelperGL4::drawElements(GLenum primitiveType,
baseVertex);
}
+void GraphicsHelperGL4::drawElementsIndirect(GLenum mode,
+ GLenum type,
+ void *indirect)
+{
+ m_funcs->glDrawElementsIndirect(mode, type, indirect);
+}
+
void GraphicsHelperGL4::drawArrays(GLenum primitiveType,
GLint first,
GLsizei count)
@@ -149,6 +156,11 @@ void GraphicsHelperGL4::drawArrays(GLenum primitiveType,
count);
}
+void GraphicsHelperGL4::drawArraysIndirect(GLenum mode, void *indirect)
+{
+ m_funcs->glDrawArraysIndirect(mode, indirect);
+}
+
void GraphicsHelperGL4::setVerticesPerPatch(GLint verticesPerPatch)
{
m_funcs->glPatchParameteri(GL_PATCH_VERTICES, verticesPerPatch);
@@ -587,6 +599,7 @@ bool GraphicsHelperGL4::supportsFeature(GraphicsHelperInterface::Feature feature
case Compute:
case DrawBuffersBlend:
case BlitFramebuffer:
+ case IndirectDrawing:
return true;
default:
return false;
diff --git a/src/render/graphicshelpers/graphicshelpergl4_p.h b/src/render/graphicshelpers/graphicshelpergl4_p.h
index 1f2111419..ea098ab97 100644
--- a/src/render/graphicshelpers/graphicshelpergl4_p.h
+++ b/src/render/graphicshelpers/graphicshelpergl4_p.h
@@ -92,10 +92,12 @@ public:
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
+ void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
void drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseInstance) Q_DECL_OVERRIDE;
void drawBuffers(GLsizei n, const int *bufs) Q_DECL_OVERRIDE;
void drawElements(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLint baseVertex = 0) Q_DECL_OVERRIDE;
+ void drawElementsIndirect(GLenum mode, GLenum type, void *indirect) Q_DECL_OVERRIDE;
void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) Q_DECL_OVERRIDE;
void enableClipPlane(int clipPlane) Q_DECL_OVERRIDE;
void enablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
diff --git a/src/render/graphicshelpers/graphicshelperinterface_p.h b/src/render/graphicshelpers/graphicshelperinterface_p.h
index a22ea0274..224583d1e 100644
--- a/src/render/graphicshelpers/graphicshelperinterface_p.h
+++ b/src/render/graphicshelpers/graphicshelperinterface_p.h
@@ -78,7 +78,8 @@ public:
ShaderStorageObject,
Compute,
DrawBuffersBlend,
- BlitFramebuffer
+ BlitFramebuffer,
+ IndirectDrawing
};
virtual ~GraphicsHelperInterface() {}
@@ -105,10 +106,12 @@ public:
virtual void disablePrimitiveRestart() = 0;
virtual void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) = 0;
virtual void drawArrays(GLenum primitiveType, GLint first, GLsizei count) = 0;
+ virtual void drawArraysIndirect(GLenum mode,void *indirect) = 0;
virtual void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) = 0;
virtual void drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseinstance) = 0;
virtual void drawBuffers(GLsizei n, const int *bufs) = 0;
virtual void drawElements(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void * indices, GLint baseVertex) = 0;
+ virtual void drawElementsIndirect(GLenum mode, GLenum type, void *indirect) = 0;
virtual void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void * indices, GLsizei instances, GLint baseVertex, GLint baseInstance) = 0;
virtual void enableClipPlane(int clipPlane) = 0;
virtual void enablei(GLenum cap, GLuint index) = 0;
diff --git a/src/render/io/glbuffer.cpp b/src/render/io/glbuffer.cpp
index 23b8483fd..074868528 100644
--- a/src/render/io/glbuffer.cpp
+++ b/src/render/io/glbuffer.cpp
@@ -58,6 +58,9 @@
#if !defined(GL_PIXEL_UNPACK_BUFFER)
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
#endif
+#if !defined(GL_DRAW_INDIRECT_BUFFER)
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#endif
QT_BEGIN_NAMESPACE
@@ -76,13 +79,14 @@ GLenum glBufferTypes[] = {
GL_ELEMENT_ARRAY_BUFFER,
GL_SHADER_STORAGE_BUFFER,
GL_PIXEL_PACK_BUFFER,
- GL_PIXEL_UNPACK_BUFFER
+ GL_PIXEL_UNPACK_BUFFER,
+ GL_DRAW_INDIRECT_BUFFER
};
} // anonymous
GLBuffer::GLBuffer()
- : m_bufferId(~0)
+ : m_bufferId(0)
, m_isCreated(false)
, m_bound(false)
, m_lastTarget(GL_ARRAY_BUFFER)
diff --git a/src/render/io/glbuffer_p.h b/src/render/io/glbuffer_p.h
index 7939f6a83..e800d2bc4 100644
--- a/src/render/io/glbuffer_p.h
+++ b/src/render/io/glbuffer_p.h
@@ -74,7 +74,8 @@ public:
IndexBuffer,
ShaderStorageBuffer,
PixelPackBuffer,
- PixelUnpackBuffer
+ PixelUnpackBuffer,
+ DrawIndirectBuffer
};
bool bind(GraphicsContext *ctx, Type t);
diff --git a/tests/auto/quick3d/quick3d.pro b/tests/auto/quick3d/quick3d.pro
index d5ed1ab5f..8abe04550 100644
--- a/tests/auto/quick3d/quick3d.pro
+++ b/tests/auto/quick3d/quick3d.pro
@@ -6,5 +6,6 @@ qtConfig(private_tests) {
dynamicnodecreation \
3drender \
3dinput \
- 3dcore
+ 3dcore \
+ quick3dbuffer
}
diff --git a/tests/auto/quick3d/quick3dbuffer/quick3dbuffer.pro b/tests/auto/quick3d/quick3dbuffer/quick3dbuffer.pro
new file mode 100644
index 000000000..f36e42ff5
--- /dev/null
+++ b/tests/auto/quick3d/quick3dbuffer/quick3dbuffer.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+
+TARGET = tst_quick3dbuffer
+
+QT += 3dcore 3dcore-private 3drender 3drender-private 3dquick 3dquick-private 3dquickrender-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_quick3dbuffer.cpp
diff --git a/tests/auto/quick3d/quick3dbuffer/tst_quick3dbuffer.cpp b/tests/auto/quick3d/quick3dbuffer/tst_quick3dbuffer.cpp
new file mode 100644
index 000000000..0392c0402
--- /dev/null
+++ b/tests/auto/quick3d/quick3dbuffer/tst_quick3dbuffer.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QTest>
+#include <Qt3DQuickRender/private/quick3dbuffer_p.h>
+#include <QObject>
+#include <QVector3D>
+
+namespace {
+
+bool writeBinaryFile(const QString filePath, const void *data, int byteSize)
+{
+ QFile f(filePath);
+ if (f.open(QIODevice::WriteOnly))
+ return f.write(reinterpret_cast<const char *>(data), byteSize) == byteSize;
+ return false;
+}
+
+} // anonymous
+
+class tst_Quick3DBuffer : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void checkInvalidBinaryFile()
+ {
+ // GIVEN
+ Qt3DRender::Render::Quick::Quick3DBuffer buf;
+
+ // WHEN
+ QVariant data = buf.readBinaryFile(QUrl::fromLocalFile(QLatin1String("this_should_not_exist.bin")));
+
+ // THEN
+ QCOMPARE(data.userType(), static_cast<int>(QVariant::ByteArray));
+ QVERIFY(data.value<QByteArray>().isEmpty());
+ }
+
+ void checkValidBinaryFile()
+ {
+ // GIVEN
+ Qt3DRender::Render::Quick::Quick3DBuffer buf;
+ QVector<QVector3D> dataArray = QVector<QVector3D>()
+ << QVector3D(327.0f, 350.0f, 355.0f)
+ << QVector3D(383.0f, 427.0f, 454.0f);
+
+ const int bufferByteSize = dataArray.size() * sizeof(QVector3D);
+ const QLatin1String filePath("binary_data.bin");
+ const bool writingSucceeded = writeBinaryFile(filePath, dataArray.constData(), bufferByteSize);
+ Q_ASSERT(writingSucceeded);
+
+ // WHEN
+ const QUrl path = QUrl::fromLocalFile(filePath);
+ QVariant data = buf.readBinaryFile(path);
+
+ // THEN
+ QCOMPARE(data.userType(), static_cast<int>(QVariant::ByteArray));
+ const QByteArray byteArray = data.value<QByteArray>();
+ QCOMPARE(byteArray.size(), bufferByteSize);
+ QVERIFY(memcmp(byteArray, dataArray.constData(), bufferByteSize) == 0);
+ }
+
+};
+
+QTEST_MAIN(tst_Quick3DBuffer)
+
+#include "tst_quick3dbuffer.moc"
diff --git a/tests/auto/render/gltfplugins/tst_gltfplugins.cpp b/tests/auto/render/gltfplugins/tst_gltfplugins.cpp
index 3ab10f17a..a800fc1fa 100644
--- a/tests/auto/render/gltfplugins/tst_gltfplugins.cpp
+++ b/tests/auto/render/gltfplugins/tst_gltfplugins.cpp
@@ -241,6 +241,7 @@ void tst_gltfPlugins::createTestScene()
camera->lens()->setObjectName(QStringLiteral("Main camera lens"));
camera->setFieldOfView(30.0f);
camera->setAspectRatio(1.0f);
+ m_entityMap.insert(camera->objectName(), camera);
}
// Ortho camera
{
@@ -263,6 +264,7 @@ void tst_gltfPlugins::createTestScene()
lens->setObjectName(QStringLiteral("Ortho camera lens"));
camera->addComponent(lens);
+ m_entityMap.insert(camera->objectName(), camera);
#ifdef VISUAL_CHECK
m_view1->defaultFrameGraph()->setCamera(camera);
#endif
@@ -1208,6 +1210,16 @@ void tst_gltfPlugins::exportAndImport()
meshComponent(importedEntity));
compareComponents(materialComponent(exportedEntity),
materialComponent(importedEntity));
+ Qt3DRender::QCamera *exportedCamera =
+ qobject_cast<Qt3DRender::QCamera *>(exportedEntity);
+ if (exportedCamera) {
+ Qt3DRender::QCamera *importedCamera =
+ qobject_cast<Qt3DRender::QCamera *>(importedEntity);
+ QVERIFY(importedCamera != nullptr);
+ QCOMPARE(exportedCamera->position(), importedCamera->position());
+ QCOMPARE(exportedCamera->upVector(), importedCamera->upVector());
+ QCOMPARE(exportedCamera->viewCenter(), importedCamera->viewCenter());
+ }
}
}
diff --git a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp
index 5c413b0d0..9bc234c50 100644
--- a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp
+++ b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp
@@ -124,7 +124,7 @@ class tst_GraphicsHelperGL2 : public QObject
Q_OBJECT
private Q_SLOTS:
- void init()
+ void initTestCase()
{
m_window.reset(new QWindow);
m_window->setSurfaceType(QWindow::OpenGLSurface);
@@ -160,6 +160,11 @@ private Q_SLOTS:
}
}
+ void cleanupTestCase()
+ {
+ m_glContext.doneCurrent();
+ }
+
void alphaTest()
{
if (!m_initializationSuccessful)
diff --git a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp
index 2a67012ec..fb0265427 100644
--- a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp
+++ b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp
@@ -177,7 +177,7 @@ class tst_GraphicsHelperGL3_2 : public QObject
Q_OBJECT
private Q_SLOTS:
- void init()
+ void initTestCase()
{
m_window.reset(new QWindow);
m_window->setSurfaceType(QWindow::OpenGLSurface);
@@ -209,6 +209,11 @@ private Q_SLOTS:
}
}
+ void cleanupTestCase()
+ {
+ m_glContext.doneCurrent();
+ }
+
void alphaTest()
{
if (!m_initializationSuccessful)
diff --git a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp
index 19dd23863..293750dbf 100644
--- a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp
+++ b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp
@@ -176,7 +176,7 @@ class tst_GraphicsHelperGL3_3 : public QObject
Q_OBJECT
private Q_SLOTS:
- void init()
+ void initTestCase()
{
m_window.reset(new QWindow);
m_window->setSurfaceType(QWindow::OpenGLSurface);
@@ -209,6 +209,11 @@ private Q_SLOTS:
}
}
+ void cleanupTestCase()
+ {
+ m_glContext.doneCurrent();
+ }
+
void alphaTest()
{
if (!m_initializationSuccessful)
diff --git a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp
index 193856cb9..c6a306910 100644
--- a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp
+++ b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp
@@ -201,7 +201,7 @@ class tst_GraphicsHelperGL4 : public QObject
{
Q_OBJECT
private Q_SLOTS:
- void init()
+ void initTestCase()
{
m_window.reset(new QWindow);
m_window->setSurfaceType(QWindow::OpenGLSurface);
@@ -234,6 +234,11 @@ private Q_SLOTS:
}
}
+ void cleanupTestCase()
+ {
+ m_glContext.doneCurrent();
+ }
+
void alphaTest()
{
if (!m_initializationSuccessful)
diff --git a/tests/auto/render/qmemorybarrier/qmemorybarrier.pro b/tests/auto/render/qmemorybarrier/qmemorybarrier.pro
new file mode 100644
index 000000000..35b6c46a8
--- /dev/null
+++ b/tests/auto/render/qmemorybarrier/qmemorybarrier.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+TARGET = tst_qmemorybarrier
+
+QT += 3dcore 3dcore-private 3drender 3drender-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_qmemorybarrier.cpp
+
+include(../../core/common/common.pri)
+include(../commons/commons.pri)
diff --git a/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp b/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp
new file mode 100644
index 000000000..87c813a03
--- /dev/null
+++ b/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QTest>
+#include <Qt3DRender/qmemorybarrier.h>
+#include <Qt3DRender/private/qmemorybarrier_p.h>
+#include <QObject>
+#include <QSignalSpy>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/qnodecreatedchange.h>
+#include "testpostmanarbiter.h"
+
+class tst_QMemoryBarrier : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ qRegisterMetaType<Qt3DRender::QMemoryBarrier::BarrierTypes>("QMemoryBarrier::BarrierTypes");
+ }
+
+ void checkDefaultConstruction()
+ {
+ // GIVEN
+ Qt3DRender::QMemoryBarrier memoryBarrier;
+
+ // THEN
+ QCOMPARE(memoryBarrier.barrierTypes(), Qt3DRender::QMemoryBarrier::None);
+ }
+
+ void checkPropertyChanges()
+ {
+ // GIVEN
+ Qt3DRender::QMemoryBarrier memoryBarrier;
+
+ {
+ // WHEN
+ QSignalSpy spy(&memoryBarrier, SIGNAL(barrierTypesChanged(QMemoryBarrier::BarrierTypes)));
+ const Qt3DRender::QMemoryBarrier::BarrierTypes newValue(Qt3DRender::QMemoryBarrier::ShaderStorageBarrier|Qt3DRender::QMemoryBarrier::VertexAttributeArrayBarrier);
+ memoryBarrier.setBarrierTypes(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(memoryBarrier.barrierTypes(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ memoryBarrier.setBarrierTypes(newValue);
+
+ // THEN
+ QCOMPARE(memoryBarrier.barrierTypes(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ }
+
+ void checkCreationData()
+ {
+ // GIVEN
+ Qt3DRender::QMemoryBarrier memoryBarrier;
+
+ memoryBarrier.setBarrierTypes(Qt3DRender::QMemoryBarrier::CommandBarrier);
+
+ // WHEN
+ QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&memoryBarrier);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QMemoryBarrierData>>(creationChanges.first());
+ const Qt3DRender::QMemoryBarrierData cloneData = creationChangeData->data;
+
+ QCOMPARE(memoryBarrier.barrierTypes(), cloneData.barrierTypes);
+ QCOMPARE(memoryBarrier.id(), creationChangeData->subjectId());
+ QCOMPARE(memoryBarrier.isEnabled(), true);
+ QCOMPARE(memoryBarrier.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(memoryBarrier.metaObject(), creationChangeData->metaObject());
+ }
+
+ // WHEN
+ memoryBarrier.setEnabled(false);
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&memoryBarrier);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QMemoryBarrierData>>(creationChanges.first());
+ const Qt3DRender::QMemoryBarrierData cloneData = creationChangeData->data;
+
+ QCOMPARE(memoryBarrier.barrierTypes(), cloneData.barrierTypes);
+ QCOMPARE(memoryBarrier.id(), creationChangeData->subjectId());
+ QCOMPARE(memoryBarrier.isEnabled(), false);
+ QCOMPARE(memoryBarrier.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(memoryBarrier.metaObject(), creationChangeData->metaObject());
+ }
+ }
+
+ void checkTypesUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QMemoryBarrier memoryBarrier;
+ arbiter.setArbiterOnNode(&memoryBarrier);
+
+ {
+ // WHEN
+ memoryBarrier.setBarrierTypes(Qt3DRender::QMemoryBarrier::ShaderStorageBarrier);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "barrierTypes");
+ QCOMPARE(change->value().value<Qt3DRender::QMemoryBarrier::BarrierTypes>(), memoryBarrier.barrierTypes());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ memoryBarrier.setBarrierTypes(Qt3DRender::QMemoryBarrier::ShaderStorageBarrier);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+};
+
+QTEST_MAIN(tst_QMemoryBarrier)
+
+#include "tst_qmemorybarrier.moc"
diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro
index 2e37c0d80..bb24205e4 100644
--- a/tests/auto/render/render.pro
+++ b/tests/auto/render/render.pro
@@ -95,7 +95,8 @@ qtConfig(private_tests) {
renderviewbuilder \
filtercompatibletechniquejob \
rendercapture \
- trianglevisitor
+ trianglevisitor \
+ qmemorybarrier
!macos: SUBDIRS += graphicshelpergl4
}