diff options
author | Sven Erdem <sven.erdem@kdab.com> | 2016-12-21 17:55:21 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2017-01-13 09:41:17 +0000 |
commit | 0f32b7dc62b214e369a902067c467ec7ae6481b5 (patch) | |
tree | 6c017d189819cdfcfebd8bb8399b252057cdad85 | |
parent | f627926f48f29739a3f765cea46f5c82ccc93e04 (diff) |
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 <paul.lemire@kdab.com>
-rw-r--r-- | examples/qt3d/3d-text/3d-text.pro | 8 | ||||
-rw-r--r-- | examples/qt3d/3d-text/main.cpp | 124 | ||||
-rw-r--r-- | examples/qt3d/qt3d.pro | 3 | ||||
-rw-r--r-- | src/extras/3dtext/3dtext.pri | 11 | ||||
-rw-r--r-- | src/extras/3dtext/qtext3dgeometry.cpp | 525 | ||||
-rw-r--r-- | src/extras/3dtext/qtext3dgeometry.h | 117 | ||||
-rw-r--r-- | src/extras/3dtext/qtext3dgeometry_p.h | 106 | ||||
-rw-r--r-- | src/extras/3dtext/qtext3dmesh.cpp | 179 | ||||
-rw-r--r-- | src/extras/3dtext/qtext3dmesh.h | 97 | ||||
-rw-r--r-- | src/extras/extras.pro | 1 |
10 files changed, 1170 insertions, 1 deletions
diff --git a/examples/qt3d/3d-text/3d-text.pro b/examples/qt3d/3d-text/3d-text.pro new file mode 100644 index 000000000..7fa771df4 --- /dev/null +++ b/examples/qt3d/3d-text/3d-text.pro @@ -0,0 +1,8 @@ +!include( ../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +QT += core gui 3dcore 3drender 3dinput 3dextras 3drender-private + +SOURCES += main.cpp + diff --git a/examples/qt3d/3d-text/main.cpp b/examples/qt3d/3d-text/main.cpp new file mode 100644 index 000000000..40ae8b80a --- /dev/null +++ b/examples/qt3d/3d-text/main.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QCoreApplication> +#include <Qt3DCore/Qt3DCore> +#include <Qt3DExtras/Qt3DExtras> +#include <qtext3dmesh.h> +#include <qtext3dgeometry.h> + +int main(int argc, char *argv[]) +{ + QGuiApplication a(argc, argv); + Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow(); + view->setTitle(QStringLiteral("3D Text CPP")); + view->defaultFrameGraph()->setClearColor(QColor(210, 210, 220)); + + auto *root = new Qt3DCore::QEntity(); + + { // plane + auto *plane = new Qt3DCore::QEntity(root); + auto *planeMesh = new Qt3DExtras::QPlaneMesh(); + auto *planeTransform = new Qt3DCore::QTransform(); + auto *planeMaterial = new Qt3DExtras::QPhongMaterial(root); + planeMesh->setWidth(10); planeMesh->setHeight(10); + planeTransform->setTranslation(QVector3D(0, 0, 0)); + planeMaterial->setDiffuse(QColor(150, 150, 150)); + + plane->addComponent(planeMaterial); + plane->addComponent(planeMesh); + plane->addComponent(planeTransform); + } + + auto *textMaterial = new Qt3DExtras::QPhongMaterial(root); + { // text + int i = 0; + QStringList fonts = QFontDatabase().families(); + + for (QString family : fonts) + { + auto *text = new Qt3DCore::QEntity(root); + auto *textMesh = new Qt3DExtras::QText3DMesh(); + Qt3DExtras::QText3DGeometry *textGeometry = static_cast<Qt3DExtras::QText3DGeometry*>(textMesh->geometry()); + + auto *textTransform = new Qt3DCore::QTransform(); + QFont font(family, 32, -1, false); + textTransform->setTranslation(QVector3D(-2.45f, i * .5f, 0)); + textTransform->setScale(.2f); + textGeometry->setDepth(.45f); + textGeometry->setFont(font); + textGeometry->setEdgeSplitAngle(90.f * .15f); + textGeometry->setText(QString(family)); + textMaterial->setDiffuse(QColor(111, 150, 255)); + + text->addComponent(textMaterial); + text->addComponent(textMesh); + text->addComponent(textTransform); + + i++; + } + } + + { // camera + float aspect = static_cast<float>(view->screen()->size().width()) / view->screen()->size().height(); + Qt3DRender::QCamera *camera = view->camera(); + camera->lens()->setPerspectiveProjection(65.f, aspect, 0.1f, 100.f); + camera->setPosition(QVector3D(0, 5, 3)); + camera->setViewCenter(QVector3D(0, 5, 0)); + + auto *cameraController = new Qt3DExtras::QOrbitCameraController(root); + cameraController->setCamera(camera); + } + + view->setRootEntity(root); + view->show(); + + return a.exec(); +} diff --git a/examples/qt3d/qt3d.pro b/examples/qt3d/qt3d.pro index d6d7437d1..7d0545404 100644 --- a/examples/qt3d/qt3d.pro +++ b/examples/qt3d/qt3d.pro @@ -15,7 +15,8 @@ SUBDIRS += \ planets-qml \ instanced-arrays-qml \ lights \ - compute-particles + compute-particles \ + 3d-text qtHaveModule(multimedia): SUBDIRS += audio-visualizer-qml diff --git a/src/extras/3dtext/3dtext.pri b/src/extras/3dtext/3dtext.pri new file mode 100644 index 000000000..bcf2ce948 --- /dev/null +++ b/src/extras/3dtext/3dtext.pri @@ -0,0 +1,11 @@ + +SOURCES += \ + $$PWD/qtext3dgeometry.cpp \ + $$PWD/qtext3dmesh.cpp + +HEADERS += \ + $$PWD/qtext3dgeometry.h \ + $$PWD/qtext3dgeometry_p.h \ + $$PWD/qtext3dmesh.h + +INCLUDEPATH += $$PWD diff --git a/src/extras/3dtext/qtext3dgeometry.cpp b/src/extras/3dtext/qtext3dgeometry.cpp new file mode 100644 index 000000000..529c93b79 --- /dev/null +++ b/src/extras/3dtext/qtext3dgeometry.cpp @@ -0,0 +1,525 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtext3dgeometry.h" +#include "qtext3dgeometry_p.h" +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <Qt3DRender/qattribute.h> +#include <private/qtriangulator_p.h> +#include <qmath.h> +#include <QVector3D> +#include <QTextLayout> +#include <QTime> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +namespace { + +using IndexType = unsigned short; + +struct TriangulationData { + struct Outline { + int begin; + int end; + }; + + QVector<QVector3D> vertices; + QVector<IndexType> indices; + QVector<Outline> outlines; + QVector<IndexType> outlineIndices; + bool inverted; +}; + +TriangulationData triangulate(const QString &text, const QFont &font) +{ + TriangulationData result; + int beginOutline = 0; + + // Initialize path with text and extract polygons + QPainterPath path; + path.setFillRule(Qt::WindingFill); + path.addText(0, 0, font, text); + QList<QPolygonF> polygons = path.toSubpathPolygons(QTransform().scale(1.f, -1.f)); + + // maybe glyph has no geometry + if (polygons.size() == 0) + return result; + + const int prevNumIndices = result.indices.size(); + + // Reset path and add previously extracted polygons (which where spatially transformed) + path = QPainterPath(); + path.setFillRule(Qt::WindingFill); + for (QPolygonF &p : polygons) + path.addPolygon(p); + + // Extract polylines out of the path, this allows us to retrive indicies for each glyph outline + QPolylineSet polylines = qPolyline(path); + QVector<IndexType> tmpIndices; + tmpIndices.resize(polylines.indices.size()); + memcpy(tmpIndices.data(), polylines.indices.data(), polylines.indices.size() * sizeof(IndexType)); + + int lastIndex = 0; + for (const IndexType idx : tmpIndices) { + if (idx == std::numeric_limits<IndexType>::max()) { + const int endOutline = lastIndex; + result.outlines.push_back({beginOutline, endOutline}); + beginOutline = endOutline; + } else { + result.outlineIndices.push_back(idx); + ++lastIndex; + } + } + + // Triangulate path + const QTriangleSet triangles = qTriangulate(path); + + // Append new indices to result.indices buffer + result.indices.resize(result.indices.size() + triangles.indices.size()); + memcpy(&result.indices[prevNumIndices], triangles.indices.data(), triangles.indices.size() * sizeof(IndexType)); + for (int i = prevNumIndices, m = result.indices.size(); i < m; ++i) + result.indices[i] += result.vertices.size(); + + // Append new triangles to result.vertices + result.vertices.reserve(triangles.vertices.size() / 2); + for (int i = 0, m = triangles.vertices.size(); i < m; i += 2) + result.vertices.push_back(QVector3D(triangles.vertices[i] / font.pointSizeF(), triangles.vertices[i + 1] / font.pointSizeF(), 0.0f)); + + return result; +} + +inline QVector3D mix(const QVector3D &a, const QVector3D &b, float ratio) +{ + return a + (b - a) * ratio; +} + +} // anonymous namespace + +QText3DGeometryPrivate::QText3DGeometryPrivate() + : QGeometryPrivate() + , m_font(QFont(QStringLiteral("Arial"))) + , m_depth(1.f) + , m_edgeSplitAngle(90.f * 0.1f) + , m_positionAttribute(nullptr) + , m_normalAttribute(nullptr) + , m_indexAttribute(nullptr) + , m_vertexBuffer(nullptr) + , m_indexBuffer(nullptr) +{ + m_font.setPointSize(4); +} + +void QText3DGeometryPrivate::init() +{ + Q_Q(QText3DGeometry); + m_positionAttribute = new Qt3DRender::QAttribute(q); + m_normalAttribute = new Qt3DRender::QAttribute(q); + m_indexAttribute = new Qt3DRender::QAttribute(q); + m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); + m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + + const quint32 elementSize = 3 + 3; + const quint32 stride = elementSize * sizeof(float); + + m_positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + m_positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + m_positionAttribute->setVertexSize(3); + m_positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + m_positionAttribute->setBuffer(m_vertexBuffer); + m_positionAttribute->setByteStride(stride); + m_positionAttribute->setByteOffset(0); + m_positionAttribute->setCount(0); + + m_normalAttribute->setName(Qt3DRender::QAttribute::defaultNormalAttributeName()); + m_normalAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + m_normalAttribute->setVertexSize(3); + m_normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + m_normalAttribute->setBuffer(m_vertexBuffer); + m_normalAttribute->setByteStride(stride); + m_normalAttribute->setByteOffset(3 * sizeof(float)); + m_normalAttribute->setCount(0); + + m_indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + m_indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedShort); + m_indexAttribute->setBuffer(m_indexBuffer); + m_indexAttribute->setCount(0); + + q->addAttribute(m_positionAttribute); + q->addAttribute(m_normalAttribute); + q->addAttribute(m_indexAttribute); + + update(); +} + +/*! + * \qmltype Text3DGeometry + * \instantiates Qt3DExtras::QText3DGeometry + * \inqmlmodule Qt3D.Extras + * \brief Text3DGeometry allows creation of a 3D text in 3D space. + * + * The Text3DGeometry type is most commonly used internally by the Text3DMesh type + * but can also be used in custom GeometryRenderer types. + */ + +/*! + * \qmlproperty QString Text3DGeometry::text + * + * Holds the text used for the mesh. + */ + +/*! + * \qmlproperty QFont Text3DGeometry::font + * + * Holds the font of the text. + */ + +/*! + * \qmlproperty float Text3DGeometry::depth + * + * Holds the extrusion depth of the text. + */ + +/*! + * \qmlproperty float Text3DGeometry::edgeSplitAngle + * + * Holds the threshold angle for smooth normals. + */ + +/*! + * \qmlproperty Attribute Text3DGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ + +/*! + * \qmlproperty Attribute Text3DGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ + +/*! + * \qmlproperty Attribute Text3DGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ + +/*! + * \class Qt3DExtras::QText3DGeometry + * \inheaderfile Qt3DExtras/QText3DGeometry + * \inmodule Qt3DExtras + * \brief The QText3DGeometry class allows creation of a 3D text in 3D space. + * \since 5.8 + * \ingroup geometries + * \inherits Qt3DRender::QGeometry + * + * The QText3DGeometry class is most commonly used internally by the QText3DMesh + * but can also be used in custom Qt3DRender::QGeometryRenderer subclasses. + */ + +/*! + * Constructs a new QText3DGeometry with \a parent. + */ +QText3DGeometry::QText3DGeometry(Qt3DCore::QNode *parent) + : QGeometry(*new QText3DGeometryPrivate(), parent) +{ + Q_D(QText3DGeometry); + d->init(); +} + +/*! + * \internal + */ +QText3DGeometry::QText3DGeometry(QText3DGeometryPrivate &dd, Qt3DCore::QNode *parent) + : QGeometry(dd, parent) +{ + Q_D(QText3DGeometry); + d->init(); +} + +/*! + * \internal + */ +QText3DGeometry::~QText3DGeometry() +{} + +/*! + * \internal + * Updates vertices based on text, font, depth and smoothAngle properties. + */ +void QText3DGeometryPrivate::update() +{ + if (m_text.trimmed().isEmpty()) // save enough? + return; + + TriangulationData data = triangulate(m_text, m_font); + + const int numVertices = data.vertices.size(); + const int numIndices = data.indices.size(); + + struct Vertex { + QVector3D position; + QVector3D normal; + }; + + QVector<IndexType> indices; + QVector<Vertex> vertices; + + // TODO: keep 'vertices.size()' small when extruding + vertices.reserve(data.vertices.size() * 2); + for (QVector3D &v : data.vertices) // front face + vertices.push_back({ v, // vertex + QVector3D(0.0f, 0.0f, -1.0f) }); // normal + for (QVector3D &v : data.vertices) // front face + vertices.push_back({ QVector3D(v.x(), v.y(), m_depth), // vertex + QVector3D(0.0f, 0.0f, 1.0f) }); // normal + + for (int i = 0, verticesIndex = vertices.size(); i < data.outlines.size(); ++i) { + const int begin = data.outlines[i].begin; + const int end = data.outlines[i].end; + const int verticesIndexBegin = verticesIndex; + + QVector3D prevNormal = QVector3D::crossProduct( + vertices[data.outlineIndices[end - 1] + numVertices].position - vertices[data.outlineIndices[end - 1]].position, + vertices[data.outlineIndices[begin]].position - vertices[data.outlineIndices[end - 1]].position).normalized(); + + for (int j = begin; j < end; ++j) { + const bool isLastIndex = (j == end - 1); + const IndexType cur = data.outlineIndices[j]; + const IndexType next = data.outlineIndices[((j - begin + 1) % (end - begin)) + begin]; // normalize, bring in range and adjust + const QVector3D normal = QVector3D::crossProduct(vertices[cur + numVertices].position - vertices[cur].position, vertices[next].position - vertices[cur].position).normalized(); + + // use smooth normals in case of a short angle + const bool smooth = QVector3D::dotProduct(prevNormal, normal) > (90.0f - m_edgeSplitAngle) / 90.0f; + const QVector3D resultNormal = smooth ? mix(prevNormal, normal, 0.5f) : normal; + if (!smooth) { + vertices.push_back({vertices[cur].position, prevNormal}); + vertices.push_back({vertices[cur + numVertices].position, prevNormal}); + verticesIndex += 2; + } + + vertices.push_back({vertices[cur].position, resultNormal}); + vertices.push_back({vertices[cur + numVertices].position, resultNormal}); + + const int v0 = verticesIndex; + const int v1 = verticesIndex + 1; + const int v2 = isLastIndex ? verticesIndexBegin : verticesIndex + 2; + const int v3 = isLastIndex ? verticesIndexBegin + 1 : verticesIndex + 3; + + indices.push_back(v0); + indices.push_back(v1); + indices.push_back(v2); + indices.push_back(v2); + indices.push_back(v1); + indices.push_back(v3); + + verticesIndex += 2; + prevNormal = normal; + } + } + + { // upload vertices + QByteArray data; + data.resize(vertices.size() * sizeof(Vertex)); + memcpy(data.data(), vertices.data(), vertices.size() * sizeof(Vertex)); + + m_vertexBuffer->setData(data); + m_positionAttribute->setCount(vertices.size()); + m_normalAttribute->setCount(vertices.size()); + } + + // resize for following insertions + const int indicesOffset = indices.size(); + indices.resize(indices.size() + numIndices * 2); + + // copy values for back faces + IndexType *indicesFaces = indices.data() + indicesOffset; + memcpy(indicesFaces, data.indices.data(), numIndices * sizeof(IndexType)); + + // insert values for front face and flip triangles + for (int j = 0; j < numIndices; j += 3) + { + indicesFaces[numIndices + j ] = indicesFaces[j ] + numVertices; + indicesFaces[numIndices + j + 1] = indicesFaces[j + 2] + numVertices; + indicesFaces[numIndices + j + 2] = indicesFaces[j + 1] + numVertices; + } + + { // upload indices + QByteArray data; + data.resize(indices.size() * sizeof(IndexType)); + memcpy(data.data(), indices.data(), indices.size() * sizeof(IndexType)); + + m_indexBuffer->setData(data); + m_indexAttribute->setCount(indices.size()); + } +} + +void QText3DGeometry::setText(QString text) +{ + Q_D(QText3DGeometry); + if (d->m_text != text) { + d->m_text = text; + d->update(); + emit textChanged(text); + } +} + +void QText3DGeometry::setFont(QFont font) +{ + Q_D(QText3DGeometry); + if (d->m_font != font) { + d->m_font = font; + d->update(); + emit fontChanged(font); + } +} + +void QText3DGeometry::setDepth(float depth) +{ + Q_D(QText3DGeometry); + if (d->m_depth != depth) { + d->m_depth = depth; + d->update(); + emit depthChanged(depth); + } +} + +void QText3DGeometry::setEdgeSplitAngle(float smoothAngle) +{ + Q_D(QText3DGeometry); + if (d->m_edgeSplitAngle != smoothAngle) { + d->m_edgeSplitAngle = smoothAngle; + d->update(); + emit edgeSplitAngleChanged(smoothAngle); + } +} + +/*! + * \property QString Text3DGeometry::text + * + * Holds the text used for the mesh. + */ +QString QText3DGeometry::text() const +{ + Q_D(const QText3DGeometry); + return d->m_text; +} + +/*! + * \property QFont Text3DGeometry::font + * + * Holds the font of the text. + */ +QFont QText3DGeometry::font() const +{ + Q_D(const QText3DGeometry); + return d->m_font; +} + +/*! + * \property float Text3DGeometry::depth + * + * Holds the extrusion depth of the text. + */ +float QText3DGeometry::depth() const +{ + Q_D(const QText3DGeometry); + return d->m_depth; +} + +/*! + * \property float Text3DGeometry::edgeSplitAngle + * + * Holds the threshold angle for smooth normals. + */ +float QText3DGeometry::edgeSplitAngle() const +{ + Q_D(const QText3DGeometry); + return d->m_edgeSplitAngle; +} + +/*! + * \property Text3DGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ +Qt3DRender::QAttribute *QText3DGeometry::positionAttribute() const +{ + Q_D(const QText3DGeometry); + return d->m_positionAttribute; +} + +/*! + * \property Text3DGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ +Qt3DRender::QAttribute *QText3DGeometry::normalAttribute() const +{ + Q_D(const QText3DGeometry); + return d->m_normalAttribute; +} + +/*! + * \property Text3DGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ +Qt3DRender::QAttribute *QText3DGeometry::indexAttribute() const +{ + Q_D(const QText3DGeometry); + return d->m_indexAttribute; +} + +} // Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/3dtext/qtext3dgeometry.h b/src/extras/3dtext/qtext3dgeometry.h new file mode 100644 index 000000000..4cd89b112 --- /dev/null +++ b/src/extras/3dtext/qtext3dgeometry.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QTEXT3DGEOMETRY_H +#define QT3DEXTRAS_QTEXT3DGEOMETRY_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometry.h> +#include <QString> +#include <QFont> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; + +} // namespace Qt3DRender + +namespace Qt3DExtras { + +class QText3DGeometryPrivate; + +class QT3DEXTRASSHARED_EXPORT QText3DGeometry : public Qt3DRender::QGeometry +{ + Q_OBJECT + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) + Q_PROPERTY(float depth READ depth WRITE setDepth NOTIFY depthChanged) + Q_PROPERTY(float edgeSplitAngle READ edgeSplitAngle WRITE setEdgeSplitAngle NOTIFY edgeSplitAngleChanged) + Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT) + +public: + explicit QText3DGeometry(Qt3DCore::QNode *parent = nullptr); + ~QText3DGeometry(); + + Qt3DRender::QAttribute *positionAttribute() const; + Qt3DRender::QAttribute *normalAttribute() const; + Qt3DRender::QAttribute *indexAttribute() const; + QString text() const; + QFont font() const; + float depth() const; + float edgeSplitAngle() const; + +public Q_SLOTS: + void setText(QString text); + void setFont(QFont font); + void setDepth(float depth); + void setEdgeSplitAngle(float edgeSplitAngle); + +Q_SIGNALS: + void textChanged(QString text); + void fontChanged(QFont font); + void depthChanged(float depth); + void edgeSplitAngleChanged(float edgeSplitAngle); + +protected: + QText3DGeometry(QText3DGeometryPrivate &dd, QNode *parent = nullptr); + +private: + Q_DECLARE_PRIVATE(QText3DGeometry) +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QTEXT3DGEOMETRY_H diff --git a/src/extras/3dtext/qtext3dgeometry_p.h b/src/extras/3dtext/qtext3dgeometry_p.h new file mode 100644 index 000000000..dc5e2f6a7 --- /dev/null +++ b/src/extras/3dtext/qtext3dgeometry_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QTEXT3DGEOMETRY_P_H +#define QT3DEXTRAS_QTEXT3DGEOMETRY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DRender/private/qgeometry_p.h> +#include <QFont> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; +class QBuffer; + +} // namespace Qt3DRender + +namespace Qt3DExtras { + +class QText3DGeometry; + +class QText3DGeometryPrivate : public Qt3DRender::QGeometryPrivate +{ +public: + QText3DGeometryPrivate(); + void init(); + void update(); + + QString m_text; + QFont m_font; + float m_depth; + float m_edgeSplitAngle; + + Qt3DRender::QAttribute *m_positionAttribute; + Qt3DRender::QAttribute *m_normalAttribute; + Qt3DRender::QAttribute *m_indexAttribute; + Qt3DRender::QBuffer *m_vertexBuffer; + Qt3DRender::QBuffer *m_indexBuffer; + + Q_DECLARE_PUBLIC(QText3DGeometry) +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QTEXT3DGEOMETRY_P_H diff --git a/src/extras/3dtext/qtext3dmesh.cpp b/src/extras/3dtext/qtext3dmesh.cpp new file mode 100644 index 000000000..a89c01a4d --- /dev/null +++ b/src/extras/3dtext/qtext3dmesh.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtext3dmesh.h" +#include "qtext3dgeometry.h" + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +/*! + * \qmltype Text3DMesh + * \instantiates Qt3DExtras::QText3DMesh + * \inqmlmodule Qt3D.Extras + * \brief A 3D Text mesh. + */ + +/*! + * \qmlproperty QString Text3DMesh::text + * + * Holds the text used for the mesh. + */ + +/*! + * \qmlproperty QFont Text3DMesh::font + * + * Holds the font of the text. + */ + +/*! + * \qmlproperty float Text3DMesh::depth + * + * Holds the extrusion depth of the text. + */ + +/*! + * \qmlproperty float Text3DMesh::edgeSplitAngle + * + * Holds the threshold angle for smooth normals. + */ + +/*! + * \class Qt3DExtras::QText3DMesh + * \inheaderfile Qt3DExtras/QText3DMesh + * \inmodule Qt3DExtras + * + * \inherits Qt3DRender::QGeometryRenderer + * + * \brief A 3D Text mesh. + */ + +/*! + * Constructs a new QText3DMesh with \a parent. + */ +QText3DMesh::QText3DMesh(Qt3DCore::QNode *parent) + : QGeometryRenderer(parent) +{ + QText3DGeometry *geometry = new QText3DGeometry(); + QObject::connect(geometry, &QText3DGeometry::depthChanged, this, &QText3DMesh::depthChanged); + QObject::connect(geometry, &QText3DGeometry::textChanged, this, &QText3DMesh::textChanged); + QObject::connect(geometry, &QText3DGeometry::fontChanged, this, &QText3DMesh::fontChanged); + QObject::connect(geometry, &QText3DGeometry::edgeSplitAngleChanged, this, &QText3DMesh::edgeSplitAngleChanged); + QGeometryRenderer::setGeometry(geometry); +} + +/*! \internal */ +QText3DMesh::~QText3DMesh() +{} + +void QText3DMesh::setText(QString text) +{ + static_cast<QText3DGeometry*>(geometry())->setText(text); +} + +void QText3DMesh::setFont(QFont font) +{ + static_cast<QText3DGeometry*>(geometry())->setFont(font); +} + +void QText3DMesh::setDepth(float depth) +{ + static_cast<QText3DGeometry*>(geometry())->setDepth(depth); +} + +void QText3DMesh::setEdgeSplitAngle(float smoothAngle) +{ + static_cast<QText3DGeometry*>(geometry())->setEdgeSplitAngle(smoothAngle); +} + +/*! + * \property QString QText3DMesh::text + * + * Holds the text used for the mesh. + */ +QString QText3DMesh::text() +{ + return static_cast<QText3DGeometry*>(geometry())->text(); +} + +/*! + * \property QFont QText3DMesh::font + * + * Holds the font of the text. + */ +QFont QText3DMesh::font() +{ + return static_cast<QText3DGeometry*>(geometry())->font(); +} + +/*! + * \property float QText3DMesh::depth + * + * Holds the extrusion depth of the text. + */ +float QText3DMesh::depth() +{ + return static_cast<QText3DGeometry*>(geometry())->depth(); +} + +/*! + * \property float QText3DMesh::edgeSplitAngle + * + * Holds the threshold angle for smooth normals. + */ +float QText3DMesh::edgeSplitAngle() +{ + return static_cast<QText3DGeometry*>(geometry())->edgeSplitAngle(); +} + +} // namespace Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/3dtext/qtext3dmesh.h b/src/extras/3dtext/qtext3dmesh.h new file mode 100644 index 000000000..6bb546675 --- /dev/null +++ b/src/extras/3dtext/qtext3dmesh.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QTEXT3DMESH_H +#define QT3DEXTRAS_QTEXT3DMESH_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometryrenderer.h> +#include <QString> +#include <QFont> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +class QT3DEXTRASSHARED_EXPORT QText3DMesh : public Qt3DRender::QGeometryRenderer +{ + Q_OBJECT + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) + Q_PROPERTY(float depth READ depth WRITE setDepth NOTIFY depthChanged) + Q_PROPERTY(float edgeSplitAngle READ edgeSplitAngle WRITE setEdgeSplitAngle NOTIFY edgeSplitAngleChanged) + +public: + QText3DMesh(Qt3DCore::QNode *parent = nullptr); + ~QText3DMesh(); + + QString text(); + QFont font(); + float depth(); + float edgeSplitAngle(); + +public Q_SLOTS: + void setText(QString text); + void setFont(QFont font); + void setDepth(float depth); + void setEdgeSplitAngle(float edgeSplitAngle); + +Q_SIGNALS: + void textChanged(QString text); + void fontChanged(QFont font); + void depthChanged(float depth); + void edgeSplitAngleChanged(float edgeSplitAngle); +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QTEXT3DMESH_H diff --git a/src/extras/extras.pro b/src/extras/extras.pro index a7bbc7f66..d723554ca 100644 --- a/src/extras/extras.pro +++ b/src/extras/extras.pro @@ -10,6 +10,7 @@ DEFINES += QT_NO_FOREACH load(qt_module) include (geometries/geometries.pri) +include (3dtext/3dtext.pri) include (defaults/defaults.pri) HEADERS += \ |