From 50457f2025f3d38234bd4b27b086e75e4267f68e Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Thu, 12 Jan 2017 12:28:41 +0000 Subject: Don't recreate window very rapidly in test case Something in the QPA or with hardware GL in macOS must have changed that now makes this scenario crash at random. Let's bypass it by just creating a single context and window for the whole set of tests. Task-number: QTBUG-58107 Change-Id: Ib9a9daf2fe8502ab99c280edf46c007d44a5a1b7 Reviewed-by: Liang Qi Reviewed-by: Paul Lemire --- tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp | 7 ++++++- tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp | 7 ++++++- tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp | 7 ++++++- tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp | 7 ++++++- 4 files changed, 24 insertions(+), 4 deletions(-) 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) -- cgit v1.2.3 From 030906b16f569a58ee5490e7a12c191b60160715 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 23 Nov 2016 18:40:37 +0100 Subject: Quick3DBuffer: add helper method to read binary file Change-Id: Ib96806720171cddc990f4b0df59a8690d56bc605 Reviewed-by: Sean Harmer --- src/quick3d/quick3drender/items/quick3dbuffer.cpp | 21 +++++++++++++++++++++ src/quick3d/quick3drender/items/quick3dbuffer_p.h | 2 ++ 2 files changed, 23 insertions(+) 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 #include #include +#include +#include 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); -- cgit v1.2.3 From 42ac66b9346977f2d19afd7a5a2a543f60059fe5 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 12 Dec 2016 15:09:14 +0100 Subject: Add unit tests for Quick3DBuffer::readBinaryFile Change-Id: I8a4b14bd830774ac15d7d77efdb26797b197ba70 Reviewed-by: Sean Harmer --- tests/auto/quick3d/quick3d.pro | 3 +- tests/auto/quick3d/quick3dbuffer/quick3dbuffer.pro | 9 +++ .../quick3d/quick3dbuffer/tst_quick3dbuffer.cpp | 94 ++++++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 tests/auto/quick3d/quick3dbuffer/quick3dbuffer.pro create mode 100644 tests/auto/quick3d/quick3dbuffer/tst_quick3dbuffer.cpp 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 +#include +#include +#include + +namespace { + +bool writeBinaryFile(const QString filePath, const void *data, int byteSize) +{ + QFile f(filePath); + if (f.open(QIODevice::WriteOnly)) + return f.write(reinterpret_cast(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(QVariant::ByteArray)); + QVERIFY(data.value().isEmpty()); + } + + void checkValidBinaryFile() + { + // GIVEN + Qt3DRender::Render::Quick::Quick3DBuffer buf; + QVector dataArray = QVector() + << 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(QVariant::ByteArray)); + const QByteArray byteArray = data.value(); + QCOMPARE(byteArray.size(), bufferByteSize); + QVERIFY(memcmp(byteArray, dataArray.constData(), bufferByteSize) == 0); + } + +}; + +QTEST_MAIN(tst_Quick3DBuffer) + +#include "tst_quick3dbuffer.moc" -- cgit v1.2.3 From d2e692bb74b3ca3f37b79a076bac1e06d78ee8f6 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 3 Oct 2016 12:41:20 +0200 Subject: QBuffer: add enum value for DrawIndirectBuffer Needed for rendering the particles as a result of dispatch compute calls. Change-Id: Iba6759d55677ff0064b203674dc16f99998ad3f7 Reviewed-by: Paul Lemire --- src/render/geometry/qbuffer.cpp | 2 ++ src/render/geometry/qbuffer.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) 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 -- cgit v1.2.3 From d97652b443350f59181f8e13dbb075ed8fdfa700 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 3 Oct 2016 12:43:54 +0200 Subject: GLBuffer: add enum value for DrawIndirectBuffer Change-Id: I262a9a58358027cd6179ffbfe54cb6a115608e7e Reviewed-by: Paul Lemire --- src/render/io/glbuffer.cpp | 6 +++++- src/render/io/glbuffer_p.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/render/io/glbuffer.cpp b/src/render/io/glbuffer.cpp index 23b8483fd..dbcf62dc4 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,7 +79,8 @@ 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 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); -- cgit v1.2.3 From f627926f48f29739a3f765cea46f5c82ccc93e04 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 3 Oct 2016 12:45:31 +0200 Subject: GLBuffer: make the default buffer id be 0 This is safer than it being the max uint value since 0 will be recognized as a valid GL value. Change-Id: Ic78f38e6b830dad1e041cb0097767ac5842bd9a5 Reviewed-by: Paul Lemire --- src/render/io/glbuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/io/glbuffer.cpp b/src/render/io/glbuffer.cpp index dbcf62dc4..074868528 100644 --- a/src/render/io/glbuffer.cpp +++ b/src/render/io/glbuffer.cpp @@ -86,7 +86,7 @@ GLenum glBufferTypes[] = { } // anonymous GLBuffer::GLBuffer() - : m_bufferId(~0) + : m_bufferId(0) , m_isCreated(false) , m_bound(false) , m_lastTarget(GL_ARRAY_BUFFER) -- cgit v1.2.3 From 0f32b7dc62b214e369a902067c467ec7ae6481b5 Mon Sep 17 00:00:00 2001 From: Sven Erdem Date: Wed, 21 Dec 2016 17:55:21 +0100 Subject: 3D Text: created 3d text geometry and mesh - Allows to extrude a 3D mesh from a text string - Added 3d-text example Triangulation fixes provided by Remi Faitout Task-number: QTBUG-19234 Change-Id: I767ffa11092d30945e3fc19f90f72a5965f5a776 Reviewed-by: Paul Lemire --- examples/qt3d/3d-text/3d-text.pro | 8 + examples/qt3d/3d-text/main.cpp | 124 ++++++++ examples/qt3d/qt3d.pro | 3 +- src/extras/3dtext/3dtext.pri | 11 + src/extras/3dtext/qtext3dgeometry.cpp | 525 ++++++++++++++++++++++++++++++++++ src/extras/3dtext/qtext3dgeometry.h | 117 ++++++++ src/extras/3dtext/qtext3dgeometry_p.h | 106 +++++++ src/extras/3dtext/qtext3dmesh.cpp | 179 ++++++++++++ src/extras/3dtext/qtext3dmesh.h | 97 +++++++ src/extras/extras.pro | 1 + 10 files changed, 1170 insertions(+), 1 deletion(-) create mode 100644 examples/qt3d/3d-text/3d-text.pro create mode 100644 examples/qt3d/3d-text/main.cpp create mode 100644 src/extras/3dtext/3dtext.pri create mode 100644 src/extras/3dtext/qtext3dgeometry.cpp create mode 100644 src/extras/3dtext/qtext3dgeometry.h create mode 100644 src/extras/3dtext/qtext3dgeometry_p.h create mode 100644 src/extras/3dtext/qtext3dmesh.cpp create mode 100644 src/extras/3dtext/qtext3dmesh.h 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 +#include +#include +#include +#include + +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(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(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 +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +namespace { + +using IndexType = unsigned short; + +struct TriangulationData { + struct Outline { + int begin; + int end; + }; + + QVector vertices; + QVector indices; + QVector outlines; + QVector 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 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 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::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 indices; + QVector 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 +#include +#include +#include + +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 +#include + +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(geometry())->setText(text); +} + +void QText3DMesh::setFont(QFont font) +{ + static_cast(geometry())->setFont(font); +} + +void QText3DMesh::setDepth(float depth) +{ + static_cast(geometry())->setDepth(depth); +} + +void QText3DMesh::setEdgeSplitAngle(float smoothAngle) +{ + static_cast(geometry())->setEdgeSplitAngle(smoothAngle); +} + +/*! + * \property QString QText3DMesh::text + * + * Holds the text used for the mesh. + */ +QString QText3DMesh::text() +{ + return static_cast(geometry())->text(); +} + +/*! + * \property QFont QText3DMesh::font + * + * Holds the font of the text. + */ +QFont QText3DMesh::font() +{ + return static_cast(geometry())->font(); +} + +/*! + * \property float QText3DMesh::depth + * + * Holds the extrusion depth of the text. + */ +float QText3DMesh::depth() +{ + return static_cast(geometry())->depth(); +} + +/*! + * \property float QText3DMesh::edgeSplitAngle + * + * Holds the threshold angle for smooth normals. + */ +float QText3DMesh::edgeSplitAngle() +{ + return static_cast(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 +#include +#include +#include + +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 += \ -- cgit v1.2.3 From c1ca7155c2083c502be7e62981d75362a3178c13 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Tue, 10 Jan 2017 15:11:49 +0100 Subject: Quick3DExtras: register Text3DGeometry, Text3DMesh Change-Id: I27d66b8585c3cbacb246d692969fa67ac808244e Reviewed-by: Paul Lemire --- src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp | 5 +++++ 1 file changed, 5 insertions(+) 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 #include #include +#include +#include #include QT_BEGIN_NAMESPACE @@ -98,6 +100,9 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri) qmlRegisterType(uri, 2, 0, "SphereMesh"); qmlRegisterType(uri, 2, 0, "SphereGeometry"); + // 3D Text + qmlRegisterType(uri, 2, 2, "Text3DGeometry"); + qmlRegisterType(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++) { -- cgit v1.2.3 From c952363512761d2664d2b83c900c1cfc0d14d864 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 3 Oct 2016 14:24:44 +0200 Subject: GraphicsHelpers: add support for indirect drawing Change-Id: I9c2fb4e35b9685d1585e4c7b8bd2910aa95224be Reviewed-by: Paul Lemire --- src/render/graphicshelpers/graphicshelperes2.cpp | 10 ++++++++++ src/render/graphicshelpers/graphicshelperes2_p.h | 2 ++ src/render/graphicshelpers/graphicshelpergl2.cpp | 10 ++++++++++ src/render/graphicshelpers/graphicshelpergl2_p.h | 2 ++ src/render/graphicshelpers/graphicshelpergl3_2.cpp | 10 ++++++++++ src/render/graphicshelpers/graphicshelpergl3_2_p.h | 2 ++ src/render/graphicshelpers/graphicshelpergl3_3.cpp | 10 ++++++++++ src/render/graphicshelpers/graphicshelpergl3_3_p.h | 2 ++ src/render/graphicshelpers/graphicshelpergl4.cpp | 13 +++++++++++++ src/render/graphicshelpers/graphicshelpergl4_p.h | 2 ++ src/render/graphicshelpers/graphicshelperinterface_p.h | 5 ++++- 11 files changed, 67 insertions(+), 1 deletion(-) 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; -- cgit v1.2.3 From beb138bb3e3cb13a049e317cf6e56cdd5479ec0d Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 3 Oct 2016 14:51:54 +0200 Subject: GraphicsContext: add indirect draw methods Change-Id: Ibcb7f629ede86d3808451ee09c0b7f5016492a00 Reviewed-by: Paul Lemire --- src/render/graphicshelpers/graphicscontext.cpp | 12 ++++++++++++ src/render/graphicshelpers/graphicscontext_p.h | 2 ++ 2 files changed, 14 insertions(+) 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); -- cgit v1.2.3 From b539b79b08a00e2c29b028ae31659c9a4fc187bb Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 3 Oct 2016 15:53:49 +0200 Subject: Add QMemoryBarrier frontend FrameGraph node Change-Id: I8a3157644453af864275d73f5f2e12019d85a33d Reviewed-by: Paul Lemire --- src/render/framegraph/framegraph.pri | 7 +- src/render/framegraph/qframegraphnode.cpp | 6 ++ src/render/framegraph/qmemorybarrier.cpp | 160 ++++++++++++++++++++++++++++++ src/render/framegraph/qmemorybarrier.h | 101 +++++++++++++++++++ src/render/framegraph/qmemorybarrier_p.h | 77 ++++++++++++++ 5 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 src/render/framegraph/qmemorybarrier.cpp create mode 100644 src/render/framegraph/qmemorybarrier.h create mode 100644 src/render/framegraph/qmemorybarrier_p.h 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 + +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::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 + +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 +#include + +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 -- cgit v1.2.3 From d7fb7425775d4e9191626fcf62f4198c84843090 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 3 Oct 2016 16:39:20 +0200 Subject: Unit tests for QMemoryBarrier Change-Id: I8194a0aa6b1d2251cba8e536d317a520fd31e59a Reviewed-by: Paul Lemire --- .../auto/render/qmemorybarrier/qmemorybarrier.pro | 12 ++ .../render/qmemorybarrier/tst_qmemorybarrier.cpp | 175 +++++++++++++++++++++ tests/auto/render/render.pro | 3 +- 3 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 tests/auto/render/qmemorybarrier/qmemorybarrier.pro create mode 100644 tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp 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 +** 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 +#include +#include +#include +#include +#include +#include +#include +#include "testpostmanarbiter.h" + +class tst_QMemoryBarrier : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void initTestCase() + { + qRegisterMetaType("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 creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&memoryBarrier); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast>(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>(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(); + QCOMPARE(change->propertyName(), "barrierTypes"); + QCOMPARE(change->value().value(), 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 } -- cgit v1.2.3 From cef6d5406267787d22deee75600ee9d3653a3109 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 11 Jan 2017 14:10:24 +0200 Subject: GLTF Export QCamera properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QCamera position, upVector, and viewCenter properties were not properly preserved when doing GLTF export/import. Change-Id: I6d81633cf29d6e347935c56605b46923d3e1aa03 Reviewed-by: Tomi Korpipää Reviewed-by: Antti Määttä --- src/plugins/sceneparsers/gltf/gltfimporter.cpp | 26 ++++++++++++++++------ src/plugins/sceneparsers/gltf/gltfimporter.h | 2 +- .../sceneparsers/gltfexport/gltfexporter.cpp | 13 ++++++++++- src/plugins/sceneparsers/gltfexport/gltfexporter.h | 3 +++ tests/auto/render/gltfplugins/tst_gltfplugins.cpp | 12 ++++++++++ 5 files changed, 47 insertions(+), 9 deletions(-) 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 entities = camera->entities(); + if (entities.size() == 1) + cameraEntity = qobject_cast(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/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(exportedEntity); + if (exportedCamera) { + Qt3DRender::QCamera *importedCamera = + qobject_cast(importedEntity); + QVERIFY(importedCamera != nullptr); + QCOMPARE(exportedCamera->position(), importedCamera->position()); + QCOMPARE(exportedCamera->upVector(), importedCamera->upVector()); + QCOMPARE(exportedCamera->viewCenter(), importedCamera->viewCenter()); + } } } -- cgit v1.2.3