summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2017-02-17 15:41:36 +0000
committerMike Krus <mike.krus@kdab.com>2017-05-26 09:58:08 +0000
commit53ce2c8ff026503f8a64e98cfc7110f224278dcb (patch)
treed21708a192023293af3b666150d5c57c99f66f38
parent6b9d1c0bf0fc3452d7a578003d14ee1beed1ed6b (diff)
Add support for iterating on lines
Provides base class for iterating on segments of line based geometry. Points are passed as floats along with their index and the index of the segment. Task-number: QTBUG-58071 Change-Id: I4ad08af60265d3df3547b3cb6e0dc02d89bca2f9 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r--src/render/backend/render-backend.pri4
-rw-r--r--src/render/backend/segmentsvisitor.cpp369
-rw-r--r--src/render/backend/segmentsvisitor_p.h93
-rw-r--r--tests/auto/render/render.pro1
-rw-r--r--tests/auto/render/segmentvisitor/segmentvisitor.pro12
-rw-r--r--tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp814
6 files changed, 1292 insertions, 1 deletions
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
index 6b6a89da3..3d174f637 100644
--- a/src/render/backend/render-backend.pri
+++ b/src/render/backend/render-backend.pri
@@ -42,7 +42,8 @@ HEADERS += \
$$PWD/offscreensurfacehelper_p.h \
$$PWD/resourceaccessor_p.h \
$$PWD/commandthread_p.h \
- $$PWD/visitorutils_p.h
+ $$PWD/visitorutils_p.h \
+ $$PWD/segmentsvisitor_p.h
SOURCES += \
$$PWD/renderthread.cpp \
@@ -77,6 +78,7 @@ SOURCES += \
$$PWD/renderviewbuilder.cpp \
$$PWD/offscreensurfacehelper.cpp \
$$PWD/resourceaccessor.cpp \
+ $$PWD/segmentsvisitor.cpp \
$$PWD/commandthread.cpp
include($$OUT_PWD/../core/qt3dcore-config.pri)
diff --git a/src/render/backend/segmentsvisitor.cpp b/src/render/backend/segmentsvisitor.cpp
new file mode 100644
index 000000000..96e2b3b6c
--- /dev/null
+++ b/src/render/backend/segmentsvisitor.cpp
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** 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: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 "segmentsvisitor_p.h"
+#include <Qt3DCore/qentity.h>
+#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/buffermanager_p.h>
+#include <Qt3DRender/private/geometryrenderer_p.h>
+#include <Qt3DRender/private/geometryrenderermanager_p.h>
+#include <Qt3DRender/private/geometry_p.h>
+#include <Qt3DRender/private/attribute_p.h>
+#include <Qt3DRender/private/buffer_p.h>
+#include <Qt3DRender/private/trianglesvisitor_p.h>
+#include <Qt3DRender/private/visitorutils_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+namespace {
+
+bool isSegmentBased(Qt3DRender::QGeometryRenderer::PrimitiveType type) Q_DECL_NOTHROW
+{
+ switch (type) {
+ case Qt3DRender::QGeometryRenderer::Lines:
+ case Qt3DRender::QGeometryRenderer::LineStrip:
+ case Qt3DRender::QGeometryRenderer::LineLoop:
+ case Qt3DRender::QGeometryRenderer::LinesAdjacency:
+ case Qt3DRender::QGeometryRenderer::LineStripAdjacency:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// indices, vertices are already offset
+template<typename Index, typename Vertex>
+void traverseSegmentsIndexed(Index *indices,
+ Vertex *vertices,
+ const BufferInfo &indexInfo,
+ const BufferInfo &vertexInfo,
+ SegmentsVisitor *visitor)
+{
+ uint i = 0;
+ const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
+ const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
+
+ uint ndx[2];
+ QVector3D abc[2];
+ while (i < indexInfo.count) {
+ for (uint u = 0; u < 2; ++u) {
+ ndx[u] = indices[i + u];
+ const uint idx = ndx[u] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j) {
+ abc[u][j] = vertices[idx + j];
+ }
+ }
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ i += 2;
+ }
+}
+
+// vertices are already offset
+template<typename Vertex>
+void traverseSegments(Vertex *vertices,
+ const BufferInfo &vertexInfo,
+ SegmentsVisitor *visitor)
+{
+ uint i = 0;
+
+ const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
+ const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
+
+ uint ndx[2];
+ QVector3D abc[2];
+ while (i < vertexInfo.count) {
+ for (uint u = 0; u < 2; ++u) {
+ ndx[u] = (i + u);
+ const uint idx = ndx[u] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[u][j] = vertices[idx + j];
+ }
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ i += 2;
+ }
+}
+
+// indices, vertices are already offset
+template<typename Index, typename Vertex>
+void traverseSegmentStripIndexed(Index *indices,
+ Vertex *vertices,
+ const BufferInfo &indexInfo,
+ const BufferInfo &vertexInfo,
+ SegmentsVisitor *visitor,
+ bool loop)
+{
+ uint i = 0;
+ const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
+ const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
+
+ uint ndx[2];
+ QVector3D abc[2];
+ ndx[0] = indices[0];
+ uint idx = ndx[0] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[0][j] = vertices[idx + j];
+ while (i < indexInfo.count - 1) {
+ ndx[1] = indices[i + 1];
+ if (ndx[0] != ndx[1]) {
+ idx = ndx[1] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[1][j] = vertices[idx + j];
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ }
+ ++i;
+ ndx[0] = ndx[1];
+ abc[0] = abc[1];
+ }
+ if (loop) {
+ ndx[1] = indices[0];
+ if (ndx[0] != ndx[1]) {
+ idx = ndx[1] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[1][j] = vertices[idx + j];
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ }
+ }
+}
+
+// vertices are already offset
+template<typename Vertex>
+void traverseSegmentStrip(Vertex *vertices,
+ const BufferInfo &vertexInfo,
+ SegmentsVisitor *visitor,
+ bool loop)
+{
+ uint i = 0;
+
+ const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
+ const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
+
+ uint ndx[2];
+ QVector3D abc[2];
+ ndx[0] = i;
+ uint idx = ndx[0] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[0][j] = vertices[idx + j];
+ while (i < vertexInfo.count - 1) {
+ ndx[1] = (i + 1);
+ idx = ndx[1] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[1][j] = vertices[idx + j];
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ ++i;
+ ndx[0] = ndx[1];
+ abc[0] = abc[1];
+ }
+ if (loop) {
+ ndx[1] = 0;
+ idx = ndx[1] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[1][j] = vertices[idx + j];
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ }
+}
+
+// indices, vertices are already offset
+template<typename Index, typename Vertex>
+void traverseSegmentAdjacencyIndexed(Index *indices,
+ Vertex *vertices,
+ const BufferInfo &indexInfo,
+ const BufferInfo &vertexInfo,
+ SegmentsVisitor *visitor)
+{
+ uint i = 1;
+ uint n = indexInfo.count - 1;
+ const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
+ const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
+
+ uint ndx[2];
+ QVector3D abc[2];
+ while (i < n) {
+ for (uint u = 0; u < 2; ++u) {
+ ndx[u] = indices[i + u];
+ const uint idx = ndx[u] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j) {
+ abc[u][j] = vertices[idx + j];
+ }
+ }
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ i += 2;
+ }
+}
+
+// vertices are already offset
+template<typename Vertex>
+void traverseSegmentAdjacency(Vertex *vertices,
+ const BufferInfo &vertexInfo,
+ SegmentsVisitor *visitor)
+{
+ uint i = 1;
+ uint n = vertexInfo.count - 1;
+
+ const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
+ const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
+
+ uint ndx[2];
+ QVector3D abc[2];
+ while (i < n) {
+ for (uint u = 0; u < 2; ++u) {
+ ndx[u] = (i + u);
+ const uint idx = ndx[u] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[u][j] = vertices[idx + j];
+ }
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ i += 2;
+ }
+}
+
+template<typename Index, typename Visitor>
+struct IndexedVertexExecutor
+{
+ template<typename Vertex>
+ void operator ()(const BufferInfo &vertexInfo, Vertex * vertices)
+ {
+ switch (m_primitiveType) {
+ case Qt3DRender::QGeometryRenderer::Lines:
+ traverseSegmentsIndexed(m_indices, vertices, m_indexBufferInfo, vertexInfo, m_visitor);
+ return;
+ case Qt3DRender::QGeometryRenderer::LineStrip:
+ traverseSegmentStripIndexed(m_indices, vertices, m_indexBufferInfo, vertexInfo, m_visitor, false);
+ return;
+ case Qt3DRender::QGeometryRenderer::LineLoop:
+ traverseSegmentStripIndexed(m_indices, vertices, m_indexBufferInfo, vertexInfo, m_visitor, true);
+ return;
+ case Qt3DRender::QGeometryRenderer::LinesAdjacency:
+ traverseSegmentAdjacencyIndexed(m_indices, vertices, m_indexBufferInfo, vertexInfo, m_visitor);
+ return;
+ case Qt3DRender::QGeometryRenderer::LineStripAdjacency: // fall through
+ default:
+ Q_UNREACHABLE();
+ return;
+ }
+ }
+
+ BufferInfo m_indexBufferInfo;
+ Index *m_indices;
+ Qt3DRender::QGeometryRenderer::PrimitiveType m_primitiveType;
+ Visitor* m_visitor;
+};
+
+template<typename Visitor>
+struct IndexExecutor
+{
+ template<typename Index>
+ void operator ()( const BufferInfo &indexInfo, Index *indices)
+ {
+ IndexedVertexExecutor<Index, Visitor> exec;
+ exec.m_primitiveType = m_primitiveType;
+ exec.m_indices = indices;
+ exec.m_indexBufferInfo = indexInfo;
+ exec.m_visitor = m_visitor;
+ Qt3DRender::Render::Visitor::processBuffer(m_vertexBufferInfo, exec);
+ }
+
+ BufferInfo m_vertexBufferInfo;
+ Qt3DRender::QGeometryRenderer::PrimitiveType m_primitiveType;
+ Visitor* m_visitor;
+};
+
+template<typename Visitor>
+struct VertexExecutor
+{
+ template<typename Vertex>
+ void operator ()(const BufferInfo &vertexInfo, Vertex *vertices)
+ {
+ switch (m_primitiveType) {
+ case Qt3DRender::QGeometryRenderer::Lines:
+ traverseSegments(vertices, vertexInfo, m_visitor);
+ return;
+ case Qt3DRender::QGeometryRenderer::LineStrip:
+ traverseSegmentStrip(vertices, vertexInfo, m_visitor, false);
+ return;
+ case Qt3DRender::QGeometryRenderer::LineLoop:
+ traverseSegmentStrip(vertices, vertexInfo, m_visitor, true);
+ return;
+ case Qt3DRender::QGeometryRenderer::LinesAdjacency:
+ traverseSegmentAdjacency(vertices, vertexInfo, m_visitor);
+ return;
+ case Qt3DRender::QGeometryRenderer::LineStripAdjacency: // fall through
+ default:
+ Q_UNREACHABLE();
+ return;
+ }
+ }
+
+ Qt3DRender::QGeometryRenderer::PrimitiveType m_primitiveType;
+ Visitor* m_visitor;
+};
+
+} // anonymous
+
+
+SegmentsVisitor::~SegmentsVisitor()
+{
+
+}
+
+void SegmentsVisitor::apply(const Qt3DCore::QEntity *entity)
+{
+ GeometryRenderer *renderer = m_manager->geometryRendererManager()->lookupResource(entity->id());
+ apply(renderer, entity->id());
+}
+
+void SegmentsVisitor::apply(const GeometryRenderer *renderer, const Qt3DCore::QNodeId id)
+{
+ m_nodeId = id;
+ if (renderer && renderer->instanceCount() == 1 && isSegmentBased(renderer->primitiveType())) {
+ Visitor::visitPrimitives<VertexExecutor<SegmentsVisitor>,
+ IndexExecutor<SegmentsVisitor>, SegmentsVisitor>(m_manager, renderer, this);
+ }
+}
+
+} // namespace Render
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/backend/segmentsvisitor_p.h b/src/render/backend/segmentsvisitor_p.h
new file mode 100644
index 000000000..21867b0d5
--- /dev/null
+++ b/src/render/backend/segmentsvisitor_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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: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_RENDER_SEGMENTSVISITOR_P_H
+#define QT3DRENDER_RENDER_SEGMENTSVISITOR_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 <Qt3DCore/qnodeid.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+class QEntity;
+}
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class GeometryRenderer;
+class NodeManagers;
+
+class Q_AUTOTEST_EXPORT SegmentsVisitor
+{
+public:
+ explicit SegmentsVisitor(NodeManagers *manager) : m_manager(manager) { }
+ virtual ~SegmentsVisitor();
+
+ void apply(const Qt3DCore::QEntity *entity);
+ void apply(const GeometryRenderer *renderer, const Qt3DCore::QNodeId id);
+
+ virtual void visit(uint andx, const QVector3D &a,
+ uint bndx, const QVector3D &b) = 0;
+
+protected:
+ NodeManagers *m_manager;
+ Qt3DCore::QNodeId m_nodeId;
+};
+
+} // namespace Render
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+
+#endif // QT3DRENDER_RENDER_SEGMENTSVISITOR_P_H
diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro
index 8eea3d032..a11a66c11 100644
--- a/tests/auto/render/render.pro
+++ b/tests/auto/render/render.pro
@@ -100,6 +100,7 @@ qtConfig(private_tests) {
renderviewbuilder \
filtercompatibletechniquejob \
rendercapture \
+ segmentvisitor \
trianglevisitor \
qmemorybarrier \
memorybarrier \
diff --git a/tests/auto/render/segmentvisitor/segmentvisitor.pro b/tests/auto/render/segmentvisitor/segmentvisitor.pro
new file mode 100644
index 000000000..2f650aa0b
--- /dev/null
+++ b/tests/auto/render/segmentvisitor/segmentvisitor.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+TARGET = segmentvisitor
+
+QT += 3dcore 3dcore-private 3drender 3drender-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_segmentvisitor.cpp
+
+include(../../core/common/common.pri)
+include(../commons/commons.pri)
diff --git a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp
new file mode 100644
index 000000000..d56daf159
--- /dev/null
+++ b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp
@@ -0,0 +1,814 @@
+/****************************************************************************
+**
+** 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:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <qbackendnodetester.h>
+#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/qbuffer.h>
+#include <private/segmentsvisitor_p.h>
+#include <private/nodemanagers_p.h>
+#include <private/managers_p.h>
+#include <private/geometryrenderer_p.h>
+#include <private/geometryrenderermanager_p.h>
+#include <private/buffermanager_p.h>
+#include "testrenderer.h"
+
+using namespace Qt3DRender::Render;
+
+class TestVisitor : public SegmentsVisitor
+{
+public:
+ TestVisitor(NodeManagers *manager)
+ : SegmentsVisitor(manager)
+ {
+
+ }
+
+ virtual void visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b)
+ {
+ m_segments.push_back(TestSegment(andx, a, bndx, b));
+ }
+
+ NodeManagers *nodeManagers() const
+ {
+ return m_manager;
+ }
+
+ Qt3DCore::QNodeId nodeId() const
+ {
+ return m_nodeId;
+ }
+
+ uint segmentCount() const
+ {
+ return m_segments.size();
+ }
+
+ bool verifySegment(uint segment, uint andx, uint bndx, QVector3D a, QVector3D b) const
+ {
+ if (segment >= uint(m_segments.size()))
+ return false;
+ if (andx != m_segments[segment].abcndx[0]
+ || bndx != m_segments[segment].abcndx[1])
+ return false;
+
+ if (!qFuzzyCompare(a, m_segments[segment].abc[0])
+ || !qFuzzyCompare(b, m_segments[segment].abc[1]))
+ return false;
+
+ return true;
+ }
+private:
+ struct TestSegment
+ {
+ uint abcndx[2];
+ QVector3D abc[2];
+ TestSegment()
+ {
+ abcndx[0] = abcndx[1] = uint(-1);
+ }
+
+ TestSegment(uint andx, const QVector3D &a, uint bndx, const QVector3D &b)
+ {
+ abcndx[0] = andx;
+ abcndx[1] = bndx;
+ abc[0] = a;
+ abc[1] = b;
+ }
+ };
+ QVector<TestSegment> m_segments;
+};
+
+class tst_SegmentVisitor : public Qt3DCore::QBackendNodeTester
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void checkInitialize()
+ {
+ // WHEN
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ TestVisitor visitor(nodeManagers.data());
+
+ // THEN
+ QCOMPARE(visitor.nodeManagers(), nodeManagers.data());
+ }
+
+ void checkApplyEntity()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity());
+ TestVisitor visitor(nodeManagers.data());
+
+ // WHEN
+ visitor.apply(entity.data());
+
+ // THEN
+ QCOMPARE(visitor.nodeId(), entity->id());
+ QCOMPARE(visitor.segmentCount(), uint(0));
+ }
+
+ void checkApplyGeometryRenderer()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ QScopedPointer<GeometryRenderer> geometryRenderer(new GeometryRenderer());
+ TestVisitor visitor(nodeManagers.data());
+
+ // WHEN
+ visitor.apply(geometryRenderer.data(), Qt3DCore::QNodeId());
+
+ // THEN
+ // tadaa, nothing should happen
+ }
+
+ void testVisitSegments()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry();
+ QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer());
+ QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer());
+ TestVisitor visitor(nodeManagers.data());
+ TestRenderer renderer;
+
+ QByteArray data;
+ data.resize(sizeof(float) * 3 * 2 * 3);
+ float *dataPtr = reinterpret_cast<float *>(data.data());
+ dataPtr[0] = 0;
+ dataPtr[1] = 0;
+ dataPtr[2] = 1.0f;
+ dataPtr[3] = 1.0f;
+ dataPtr[4] = 0;
+ dataPtr[5] = 0;
+
+ dataPtr[6] = 0;
+ dataPtr[7] = 1.0f;
+ dataPtr[8] = 0;
+ dataPtr[9] = 0;
+ dataPtr[10] = 0;
+ dataPtr[11] = 1.0f;
+
+ dataPtr[12] = 1.0f;
+ dataPtr[13] = 0;
+ dataPtr[14] = 0;
+ dataPtr[15] = 0;
+ dataPtr[16] = 1.0f;
+ dataPtr[17] = 0;
+
+ dataBuffer->setData(data);
+ Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
+ backendBuffer->setRenderer(&renderer);
+ backendBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(dataBuffer.data(), backendBuffer);
+
+ positionAttribute->setBuffer(dataBuffer.data());
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setCount(6);
+ positionAttribute->setByteStride(3*4);
+ positionAttribute->setByteOffset(0);
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ geometry->addAttribute(positionAttribute.data());
+
+ geometryRenderer->setGeometry(geometry);
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines);
+
+ Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
+ backendAttribute->setRenderer(&renderer);
+ simulateInitialization(positionAttribute.data(), backendAttribute);
+
+ Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
+ backendGeometry->setRenderer(&renderer);
+ simulateInitialization(geometry, backendGeometry);
+
+ GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
+ backendRenderer->setRenderer(&renderer);
+ backendRenderer->setManager(nodeManagers->geometryRendererManager());
+ simulateInitialization(geometryRenderer.data(), backendRenderer);
+
+ // WHEN
+ visitor.apply(backendRenderer, Qt3DCore::QNodeId());
+
+ // THEN
+ QCOMPARE(visitor.segmentCount(), uint(3));
+ QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,1), QVector3D(1,0,0)));
+ QVERIFY(visitor.verifySegment(1, 2,3, QVector3D(0,1,0), QVector3D(0,0,1)));
+ QVERIFY(visitor.verifySegment(2, 4,5, QVector3D(1,0,0), QVector3D(0,1,0)));
+ }
+
+ void testVisitSegmentsIndexed()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry();
+ QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer());
+ QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer());
+ QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer());
+ TestVisitor visitor(nodeManagers.data());
+ TestRenderer renderer;
+
+ QByteArray data;
+ data.resize(sizeof(float) * 3 * 4);
+ float *dataPtr = reinterpret_cast<float *>(data.data());
+ dataPtr[0] = 0;
+ dataPtr[1] = 0;
+ dataPtr[2] = 0.0f;
+ dataPtr[3] = 1.0f;
+ dataPtr[4] = 0;
+ dataPtr[5] = 0;
+ dataPtr[6] = 1.0;
+ dataPtr[7] = 1.0f;
+ dataPtr[8] = 0;
+ dataPtr[9] = 0;
+ dataPtr[10] = 1.0f;
+ dataPtr[11] = 0;
+ dataBuffer->setData(data);
+ Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
+ backendBuffer->setRenderer(&renderer);
+ backendBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(dataBuffer.data(), backendBuffer);
+
+ QByteArray indexData;
+ indexData.resize(sizeof(uint) * 2 * 5);
+ uint *iDataPtr = reinterpret_cast<uint *>(indexData.data());
+ iDataPtr[0] = 0;
+ iDataPtr[1] = 1;
+ iDataPtr[2] = 1;
+ iDataPtr[3] = 2;
+ iDataPtr[4] = 2;
+ iDataPtr[5] = 3;
+ iDataPtr[6] = 0;
+ iDataPtr[7] = 2;
+ iDataPtr[8] = 1;
+ iDataPtr[9] = 3;
+ indexDataBuffer->setData(indexData);
+
+ Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
+ backendIndexBuffer->setRenderer(&renderer);
+ backendIndexBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+
+ positionAttribute->setBuffer(dataBuffer.data());
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setCount(4);
+ positionAttribute->setByteStride(3*sizeof(float));
+ positionAttribute->setByteOffset(0);
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+
+ indexAttribute->setBuffer(indexDataBuffer.data());
+ indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
+ indexAttribute->setCount(2*5);
+ indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
+
+ geometry->addAttribute(positionAttribute.data());
+ geometry->addAttribute(indexAttribute.data());
+
+ geometryRenderer->setGeometry(geometry);
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines);
+
+ Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
+ backendAttribute->setRenderer(&renderer);
+ simulateInitialization(positionAttribute.data(), backendAttribute);
+
+ Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
+ backendIndexAttribute->setRenderer(&renderer);
+ simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+
+ Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
+ backendGeometry->setRenderer(&renderer);
+ simulateInitialization(geometry, backendGeometry);
+
+ GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
+ backendRenderer->setRenderer(&renderer);
+ backendRenderer->setManager(nodeManagers->geometryRendererManager());
+ simulateInitialization(geometryRenderer.data(), backendRenderer);
+
+ // WHEN
+ visitor.apply(backendRenderer, Qt3DCore::QNodeId());
+
+ // THEN
+ QCOMPARE(visitor.segmentCount(), uint(5));
+ QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0)));
+ QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0)));
+ QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0)));
+ QVERIFY(visitor.verifySegment(3, 0,2, QVector3D(0,0,0), QVector3D(1,1,0)));
+ QVERIFY(visitor.verifySegment(4, 1,3, QVector3D(1,0,0), QVector3D(0,1,0)));
+ }
+
+ void testVisitLineStrip()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry();
+ QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer());
+ QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer());
+ TestVisitor visitor(nodeManagers.data());
+ TestRenderer renderer;
+
+ QByteArray data;
+ data.resize(sizeof(float) * 3 * 4);
+ float *dataPtr = reinterpret_cast<float *>(data.data());
+ dataPtr[0] = 0;
+ dataPtr[1] = 0;
+ dataPtr[2] = 0.0f;
+ dataPtr[3] = 1.0f;
+ dataPtr[4] = 0;
+ dataPtr[5] = 0;
+ dataPtr[6] = 1.0f;
+ dataPtr[7] = 1.0f;
+ dataPtr[8] = 0;
+ dataPtr[9] = 0;
+ dataPtr[10] = 1.0f;
+ dataPtr[11] = 0;
+ dataBuffer->setData(data);
+ Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
+ backendBuffer->setRenderer(&renderer);
+ backendBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(dataBuffer.data(), backendBuffer);
+
+ positionAttribute->setBuffer(dataBuffer.data());
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setCount(4);
+ positionAttribute->setByteStride(3*4);
+ positionAttribute->setByteOffset(0);
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ geometry->addAttribute(positionAttribute.data());
+
+ geometryRenderer->setGeometry(geometry);
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineStrip);
+
+ Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
+ backendAttribute->setRenderer(&renderer);
+ simulateInitialization(positionAttribute.data(), backendAttribute);
+
+ Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
+ backendGeometry->setRenderer(&renderer);
+ simulateInitialization(geometry, backendGeometry);
+
+ GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
+ backendRenderer->setRenderer(&renderer);
+ backendRenderer->setManager(nodeManagers->geometryRendererManager());
+ simulateInitialization(geometryRenderer.data(), backendRenderer);
+
+ // WHEN
+ visitor.apply(backendRenderer, Qt3DCore::QNodeId());
+
+ // THEN
+ QCOMPARE(visitor.segmentCount(), uint(3));
+ QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0)));
+ QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0)));
+ QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0)));
+ }
+
+ void testVisitListStripIndexed()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry();
+ QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer());
+ QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer());
+ QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer());
+ TestVisitor visitor(nodeManagers.data());
+ TestRenderer renderer;
+
+ QByteArray data;
+ data.resize(sizeof(float) * 3 * 4);
+ float *dataPtr = reinterpret_cast<float *>(data.data());
+ dataPtr[0] = 0;
+ dataPtr[1] = 0;
+ dataPtr[2] = 0.0f;
+ dataPtr[3] = 1.0f;
+ dataPtr[4] = 0;
+ dataPtr[5] = 0;
+ dataPtr[6] = 1.0;
+ dataPtr[7] = 1.0f;
+ dataPtr[8] = 0;
+ dataPtr[9] = 0;
+ dataPtr[10] = 1.0f;
+ dataPtr[11] = 0;
+ dataBuffer->setData(data);
+ Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
+ backendBuffer->setRenderer(&renderer);
+ backendBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(dataBuffer.data(), backendBuffer);
+
+ QByteArray indexData;
+ indexData.resize(sizeof(uint) * 2 * 4);
+ uint *iDataPtr = reinterpret_cast<uint *>(indexData.data());
+ iDataPtr[0] = 0;
+ iDataPtr[1] = 1;
+ iDataPtr[2] = 2;
+ iDataPtr[3] = 3;
+ indexDataBuffer->setData(indexData);
+
+ Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
+ backendIndexBuffer->setRenderer(&renderer);
+ backendIndexBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+
+ positionAttribute->setBuffer(dataBuffer.data());
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setCount(4);
+ positionAttribute->setByteStride(3*sizeof(float));
+ positionAttribute->setByteOffset(0);
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+
+ indexAttribute->setBuffer(indexDataBuffer.data());
+ indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
+ indexAttribute->setCount(4);
+ indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
+
+ geometry->addAttribute(positionAttribute.data());
+ geometry->addAttribute(indexAttribute.data());
+
+ geometryRenderer->setGeometry(geometry);
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineStrip);
+
+ Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
+ backendAttribute->setRenderer(&renderer);
+ simulateInitialization(positionAttribute.data(), backendAttribute);
+
+ Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
+ backendIndexAttribute->setRenderer(&renderer);
+ simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+
+ Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
+ backendGeometry->setRenderer(&renderer);
+ simulateInitialization(geometry, backendGeometry);
+
+ GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
+ backendRenderer->setRenderer(&renderer);
+ backendRenderer->setManager(nodeManagers->geometryRendererManager());
+ simulateInitialization(geometryRenderer.data(), backendRenderer);
+
+ // WHEN
+ visitor.apply(backendRenderer, Qt3DCore::QNodeId());
+
+ // THEN
+ QCOMPARE(visitor.segmentCount(), uint(3));
+ QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0)));
+ QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0)));
+ QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0)));
+ }
+
+ void testVisitLineLoop()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry();
+ QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer());
+ QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer());
+ TestVisitor visitor(nodeManagers.data());
+ TestRenderer renderer;
+
+ QByteArray data;
+ data.resize(sizeof(float) * 3 * 4);
+ float *dataPtr = reinterpret_cast<float *>(data.data());
+ dataPtr[0] = 0;
+ dataPtr[1] = 0;
+ dataPtr[2] = 0.0f;
+ dataPtr[3] = 1.0f;
+ dataPtr[4] = 0;
+ dataPtr[5] = 0;
+ dataPtr[6] = 1.0f;
+ dataPtr[7] = 1.0f;
+ dataPtr[8] = 0;
+ dataPtr[9] = 0;
+ dataPtr[10] = 1.0f;
+ dataPtr[11] = 0;
+ dataBuffer->setData(data);
+ Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
+ backendBuffer->setRenderer(&renderer);
+ backendBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(dataBuffer.data(), backendBuffer);
+
+ positionAttribute->setBuffer(dataBuffer.data());
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setCount(4);
+ positionAttribute->setByteStride(3*4);
+ positionAttribute->setByteOffset(0);
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ geometry->addAttribute(positionAttribute.data());
+
+ geometryRenderer->setGeometry(geometry);
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop);
+
+ Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
+ backendAttribute->setRenderer(&renderer);
+ simulateInitialization(positionAttribute.data(), backendAttribute);
+
+ Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
+ backendGeometry->setRenderer(&renderer);
+ simulateInitialization(geometry, backendGeometry);
+
+ GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
+ backendRenderer->setRenderer(&renderer);
+ backendRenderer->setManager(nodeManagers->geometryRendererManager());
+ simulateInitialization(geometryRenderer.data(), backendRenderer);
+
+ // WHEN
+ visitor.apply(backendRenderer, Qt3DCore::QNodeId());
+
+ // THEN
+ QCOMPARE(visitor.segmentCount(), uint(4));
+ QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0)));
+ QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0)));
+ QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0)));
+ QVERIFY(visitor.verifySegment(3, 3,0, QVector3D(0,1,0), QVector3D(0,0,0)));
+ }
+
+ void testVisitLineLoopIndexed()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry();
+ QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer());
+ QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer());
+ QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer());
+ TestVisitor visitor(nodeManagers.data());
+ TestRenderer renderer;
+
+ QByteArray data;
+ data.resize(sizeof(float) * 3 * 4);
+ float *dataPtr = reinterpret_cast<float *>(data.data());
+ dataPtr[0] = 0;
+ dataPtr[1] = 0;
+ dataPtr[2] = 0.0f;
+ dataPtr[3] = 1.0f;
+ dataPtr[4] = 0;
+ dataPtr[5] = 0;
+ dataPtr[6] = 1.0;
+ dataPtr[7] = 1.0f;
+ dataPtr[8] = 0;
+ dataPtr[9] = 0;
+ dataPtr[10] = 1.0f;
+ dataPtr[11] = 0;
+ dataBuffer->setData(data);
+ Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
+ backendBuffer->setRenderer(&renderer);
+ backendBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(dataBuffer.data(), backendBuffer);
+
+ QByteArray indexData;
+ indexData.resize(sizeof(uint) * 2 * 4);
+ uint *iDataPtr = reinterpret_cast<uint *>(indexData.data());
+ iDataPtr[0] = 0;
+ iDataPtr[1] = 1;
+ iDataPtr[2] = 2;
+ iDataPtr[3] = 3;
+ indexDataBuffer->setData(indexData);
+
+ Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
+ backendIndexBuffer->setRenderer(&renderer);
+ backendIndexBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+
+ positionAttribute->setBuffer(dataBuffer.data());
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setCount(4);
+ positionAttribute->setByteStride(3*sizeof(float));
+ positionAttribute->setByteOffset(0);
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+
+ indexAttribute->setBuffer(indexDataBuffer.data());
+ indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
+ indexAttribute->setCount(4);
+ indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
+
+ geometry->addAttribute(positionAttribute.data());
+ geometry->addAttribute(indexAttribute.data());
+
+ geometryRenderer->setGeometry(geometry);
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop);
+
+ Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
+ backendAttribute->setRenderer(&renderer);
+ simulateInitialization(positionAttribute.data(), backendAttribute);
+
+ Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
+ backendIndexAttribute->setRenderer(&renderer);
+ simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+
+ Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
+ backendGeometry->setRenderer(&renderer);
+ simulateInitialization(geometry, backendGeometry);
+
+ GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
+ backendRenderer->setRenderer(&renderer);
+ backendRenderer->setManager(nodeManagers->geometryRendererManager());
+ simulateInitialization(geometryRenderer.data(), backendRenderer);
+
+ // WHEN
+ visitor.apply(backendRenderer, Qt3DCore::QNodeId());
+
+ // THEN
+ QCOMPARE(visitor.segmentCount(), uint(4));
+ QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0)));
+ QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0)));
+ QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0)));
+ QVERIFY(visitor.verifySegment(3, 3,0, QVector3D(0,1,0), QVector3D(0,0,0)));
+ }
+
+ void testVisitLineAdjacency()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry();
+ QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer());
+ QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer());
+ TestVisitor visitor(nodeManagers.data());
+ TestRenderer renderer;
+
+ QByteArray data;
+ data.resize(sizeof(float) * 3 * 2 * 2);
+ float *dataPtr = reinterpret_cast<float *>(data.data());
+ dataPtr[0] = 0;
+ dataPtr[1] = 0;
+ dataPtr[2] = 1.0f;
+ dataPtr[3] = 1.0f;
+ dataPtr[4] = 0;
+ dataPtr[5] = 0;
+
+ dataPtr[6] = 0;
+ dataPtr[7] = 1.0f;
+ dataPtr[8] = 0;
+ dataPtr[9] = 1.0f;
+ dataPtr[10] = 0;
+ dataPtr[12] = 0;
+ dataBuffer->setData(data);
+ Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
+ backendBuffer->setRenderer(&renderer);
+ backendBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(dataBuffer.data(), backendBuffer);
+
+ positionAttribute->setBuffer(dataBuffer.data());
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setCount(4);
+ positionAttribute->setByteStride(3*4);
+ positionAttribute->setByteOffset(0);
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ geometry->addAttribute(positionAttribute.data());
+
+ geometryRenderer->setGeometry(geometry);
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LinesAdjacency);
+
+ Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
+ backendAttribute->setRenderer(&renderer);
+ simulateInitialization(positionAttribute.data(), backendAttribute);
+
+ Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
+ backendGeometry->setRenderer(&renderer);
+ simulateInitialization(geometry, backendGeometry);
+
+ GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
+ backendRenderer->setRenderer(&renderer);
+ backendRenderer->setManager(nodeManagers->geometryRendererManager());
+ simulateInitialization(geometryRenderer.data(), backendRenderer);
+
+ // WHEN
+ visitor.apply(backendRenderer, Qt3DCore::QNodeId());
+
+ // THEN
+ QCOMPARE(visitor.segmentCount(), uint(1));
+ QVERIFY(visitor.verifySegment(0, 1, 2, QVector3D(1,0,0), QVector3D(0,1,0)));
+ }
+
+ void testVisitLinesAdjacencyIndexed()
+ {
+ QScopedPointer<NodeManagers> nodeManagers(new NodeManagers());
+ Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry();
+ QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer());
+ QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute());
+ QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer());
+ QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer());
+ TestVisitor visitor(nodeManagers.data());
+ TestRenderer renderer;
+
+ QByteArray data;
+ data.resize(sizeof(float) * 3 * 2 * 2);
+ float *dataPtr = reinterpret_cast<float *>(data.data());
+ dataPtr[0] = 0;
+ dataPtr[1] = 0;
+ dataPtr[2] = 1.0f;
+ dataPtr[3] = 1.0f;
+ dataPtr[4] = 0;
+ dataPtr[5] = 0;
+
+ dataPtr[6] = 0;
+ dataPtr[7] = 1.0f;
+ dataPtr[8] = 0;
+ dataPtr[9] = 1.0f;
+ dataPtr[10] = 0;
+ dataPtr[12] = 0;
+ dataBuffer->setData(data);
+ Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
+ backendBuffer->setRenderer(&renderer);
+ backendBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(dataBuffer.data(), backendBuffer);
+
+ QByteArray indexData;
+ indexData.resize(sizeof(uint) * 2);
+ uint *iDataPtr = reinterpret_cast<uint *>(indexData.data());
+ iDataPtr[0] = 0;
+ iDataPtr[1] = 1;
+ iDataPtr[2] = 2;
+ iDataPtr[3] = 3;
+ indexDataBuffer->setData(indexData);
+
+ Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
+ backendIndexBuffer->setRenderer(&renderer);
+ backendIndexBuffer->setManager(nodeManagers->bufferManager());
+ simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+
+ positionAttribute->setBuffer(dataBuffer.data());
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setCount(4);
+ positionAttribute->setByteStride(3*sizeof(float));
+ positionAttribute->setByteOffset(0);
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+
+ indexAttribute->setBuffer(indexDataBuffer.data());
+ indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
+ indexAttribute->setCount(4);
+ indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
+
+ geometry->addAttribute(positionAttribute.data());
+ geometry->addAttribute(indexAttribute.data());
+
+ geometryRenderer->setGeometry(geometry);
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LinesAdjacency);
+
+ Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
+ backendAttribute->setRenderer(&renderer);
+ simulateInitialization(positionAttribute.data(), backendAttribute);
+
+ Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
+ backendIndexAttribute->setRenderer(&renderer);
+ simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+
+ Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
+ backendGeometry->setRenderer(&renderer);
+ simulateInitialization(geometry, backendGeometry);
+
+ GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
+ backendRenderer->setRenderer(&renderer);
+ backendRenderer->setManager(nodeManagers->geometryRendererManager());
+ simulateInitialization(geometryRenderer.data(), backendRenderer);
+
+ // WHEN
+ visitor.apply(backendRenderer, Qt3DCore::QNodeId());
+
+ // THEN
+ QCOMPARE(visitor.segmentCount(), uint(1));
+ QVERIFY(visitor.verifySegment(0, 1, 2, QVector3D(1,0,0), QVector3D(0,1,0)));
+ }
+};
+
+QTEST_MAIN(tst_SegmentVisitor)
+
+#include "tst_segmentvisitor.moc"