diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2017-01-20 09:10:54 +0000 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-01-20 09:11:38 +0000 |
commit | 97d8a7bff44af94b4a92624e9431e6e49505432e (patch) | |
tree | fb256758cbab4ec79ee5f0bfa196a761c8aefa65 | |
parent | 28236a292be0f26b2f46b58249e498e153f286dc (diff) | |
parent | cef6d5406267787d22deee75600ee9d3653a3109 (diff) |
Merge branch 'dev' into wip/qtquickintegration
Change-Id: Ic0ba8234860bf6a020a3ffae3d3e45b38e286ab5
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 } |