diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2015-11-13 16:16:27 +0100 |
---|---|---|
committer | Andy Nichols <andy.nichols@theqtcompany.com> | 2015-11-24 14:55:16 +0000 |
commit | dee5562b22034702e2555f08271d9fc09fd458dc (patch) | |
tree | 42ad18708fc151372f965da0aa0d152ce052eb12 /tests/auto | |
parent | f24e3d00ccf5e1e495a2c19a3eaaa4c26a25a7a6 (diff) |
Unit tests for TriangleExtractor
Change-Id: Iab3c5690a18edc652f314b6bf758eea7f73a1c50
Reviewed-by: Andy Nichols <andy.nichols@theqtcompany.com>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/render/render.pro | 3 | ||||
-rw-r--r-- | tests/auto/render/trianglesextractor/trianglesextractor.pro | 9 | ||||
-rw-r--r-- | tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp | 403 |
3 files changed, 414 insertions, 1 deletions
diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index ac9633618..2aa837edb 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -40,5 +40,6 @@ contains(QT_CONFIG, private_tests) { picking \ qboundingvolumedebug \ boundingvolumedebug \ - qdefaultmeshes + qdefaultmeshes \ + trianglesextractor } diff --git a/tests/auto/render/trianglesextractor/trianglesextractor.pro b/tests/auto/render/trianglesextractor/trianglesextractor.pro new file mode 100644 index 000000000..d10d6c708 --- /dev/null +++ b/tests/auto/render/trianglesextractor/trianglesextractor.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +TARGET = tst_trianglesextractor + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_trianglesextractor.cpp diff --git a/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp b/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp new file mode 100644 index 000000000..0dd06dc20 --- /dev/null +++ b/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/private/shader_p.h> +#include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DRender/private/renderer_p.h> +#include <Qt3DRender/private/qrenderaspect_p.h> +#include <Qt3DRender/qrenderaspect.h> +#include <Qt3DRender/private/geometryrenderermanager_p.h> +#include <Qt3DRender/private/buffermanager_p.h> +#include <Qt3DRender/private/geometryrenderer_p.h> +#include <Qt3DRender/private/geometry_p.h> +#include <Qt3DRender/private/buffer_p.h> +#include <Qt3DRender/private/attribute_p.h> +#include <Qt3DRender/private/triangleboundingvolume_p.h> +#include <Qt3DRender/private/trianglesextractor_p.h> +#include <Qt3DRender/qattribute.h> +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qgeometry.h> +#include <Qt3DRender/qgeometryrenderer.h> +#include <Qt3DCore/qnodevisitor.h> + +Qt3DRender::QGeometryRenderer *customIndexedGeometryRenderer() +{ + Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer; + Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer); + + Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry); + Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, customGeometry); + + // vec3 for position + // vec3 for colors + // vec3 for normals + + /* 2 + /|\ + / | \ + / /3\ \ + 0/___\ 1 + */ + + // 4 distinct vertices + QByteArray vertexBufferData; + vertexBufferData.resize(4 * (3 + 3 + 3) * sizeof(float)); + + // Vertices + QVector3D v0(-1.0f, 0.0f, -1.0f); + QVector3D v1(1.0f, 0.0f, -1.0f); + QVector3D v2(0.0f, 1.0f, 0.0f); + QVector3D v3(0.0f, 0.0f, 1.0f); + + // Faces Normals + QVector3D n023 = QVector3D::normal(v0, v2, v3); + QVector3D n012 = QVector3D::normal(v0, v1, v2); + QVector3D n310 = QVector3D::normal(v3, v1, v0); + QVector3D n132 = QVector3D::normal(v1, v3, v2); + + // Vector Normals + QVector3D n0 = QVector3D(n023 + n012 + n310).normalized(); + QVector3D n1 = QVector3D(n132 + n012 + n310).normalized(); + QVector3D n2 = QVector3D(n132 + n012 + n023).normalized(); + QVector3D n3 = QVector3D(n132 + n310 + n023).normalized(); + + // Colors + QVector3D red(1.0f, 0.0f, 0.0f); + QVector3D green(0.0f, 1.0f, 0.0f); + QVector3D blue(0.0f, 0.0f, 1.0f); + QVector3D white(1.0f, 1.0f, 1.0f); + + QVector<QVector3D> vertices = QVector<QVector3D>() + << v0 << n0 << red + << v1 << n1 << blue + << v2 << n2 << green + << v3 << n3 << white; + + float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data()); + int idx = 0; + + Q_FOREACH (const QVector3D &v, vertices) { + rawVertexArray[idx++] = v.x(); + rawVertexArray[idx++] = v.y(); + rawVertexArray[idx++] = v.z(); + } + + // Indices (12) + QByteArray indexBufferData; + indexBufferData.resize(4 * 3 * sizeof(ushort)); + ushort *rawIndexArray = reinterpret_cast<ushort *>(indexBufferData.data()); + + // Front + rawIndexArray[0] = 0; + rawIndexArray[1] = 1; + rawIndexArray[2] = 2; + // Bottom + rawIndexArray[3] = 3; + rawIndexArray[4] = 1; + rawIndexArray[5] = 0; + // Left + rawIndexArray[6] = 0; + rawIndexArray[7] = 2; + rawIndexArray[8] = 3; + // Right + rawIndexArray[9] = 1; + rawIndexArray[10] = 3; + rawIndexArray[11] = 2; + + vertexDataBuffer->setData(vertexBufferData); + indexDataBuffer->setData(indexBufferData); + + // Attributes + Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute(); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + positionAttribute->setBuffer(vertexDataBuffer); + positionAttribute->setDataType(Qt3DRender::QAttribute::Float); + positionAttribute->setDataSize(3); + positionAttribute->setByteOffset(0); + positionAttribute->setByteStride(9 * sizeof(float)); + positionAttribute->setCount(4); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + + Qt3DRender::QAttribute *normalAttribute = new Qt3DRender::QAttribute(); + normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + normalAttribute->setBuffer(vertexDataBuffer); + normalAttribute->setDataType(Qt3DRender::QAttribute::Float); + normalAttribute->setDataSize(3); + normalAttribute->setByteOffset(3 * sizeof(float)); + normalAttribute->setByteStride(9 * sizeof(float)); + normalAttribute->setCount(4); + normalAttribute->setName(Qt3DRender::QAttribute::defaultNormalAttributeName()); + + Qt3DRender::QAttribute *colorAttribute = new Qt3DRender::QAttribute(); + colorAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + colorAttribute->setBuffer(vertexDataBuffer); + colorAttribute->setDataType(Qt3DRender::QAttribute::Float); + colorAttribute->setDataSize(3); + colorAttribute->setByteOffset(6 * sizeof(float)); + colorAttribute->setByteStride(9 * sizeof(float)); + colorAttribute->setCount(4); + colorAttribute->setName(Qt3DRender::QAttribute::defaultColorAttributeName()); + + Qt3DRender::QAttribute *indexAttribute = new Qt3DRender::QAttribute(); + indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + indexAttribute->setBuffer(indexDataBuffer); + indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedShort); + indexAttribute->setDataSize(1); + indexAttribute->setByteOffset(0); + indexAttribute->setByteStride(0); + indexAttribute->setCount(12); + + customGeometry->addAttribute(positionAttribute); + customGeometry->addAttribute(normalAttribute); + customGeometry->addAttribute(colorAttribute); + customGeometry->addAttribute(indexAttribute); + + customMeshRenderer->setInstanceCount(1); + customMeshRenderer->setBaseVertex(0); + customMeshRenderer->setBaseInstance(0); + customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); + customMeshRenderer->setGeometry(customGeometry); + // 4 faces of 3 points + customMeshRenderer->setPrimitiveCount(12); + + return customMeshRenderer; +} + +Qt3DRender::QGeometryRenderer *customNonIndexedGeometryRenderer() +{ + Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer; + Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer); + + Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry); + + // vec3 for position + // vec3 for colors + // vec3 for normals + + /* 2 + /|\ + / | \ + / /3\ \ + 0/___\ 1 + */ + + // 12 distinct vertices formaing 4 triangles + QByteArray vertexBufferData; + vertexBufferData.resize(4 * 3 * (3 + 3 + 3) * sizeof(float)); + + // Vertices + QVector3D v0(-1.0f, 0.0f, -1.0f); + QVector3D v1(1.0f, 0.0f, -1.0f); + QVector3D v2(0.0f, 1.0f, 0.0f); + QVector3D v3(0.0f, 0.0f, 1.0f); + + // Faces Normals + QVector3D n023 = QVector3D::normal(v0, v2, v3); + QVector3D n012 = QVector3D::normal(v0, v1, v2); + QVector3D n310 = QVector3D::normal(v3, v1, v0); + QVector3D n132 = QVector3D::normal(v1, v3, v2); + + // Vector Normals + QVector3D n0 = QVector3D(n023 + n012 + n310).normalized(); + QVector3D n1 = QVector3D(n132 + n012 + n310).normalized(); + QVector3D n2 = QVector3D(n132 + n012 + n023).normalized(); + QVector3D n3 = QVector3D(n132 + n310 + n023).normalized(); + + // Colors + QVector3D red(1.0f, 0.0f, 0.0f); + QVector3D green(0.0f, 1.0f, 0.0f); + QVector3D blue(0.0f, 0.0f, 1.0f); + QVector3D white(1.0f, 1.0f, 1.0f); + + QVector<QVector3D> vertices = QVector<QVector3D>() + << v0 << n0 << red + << v1 << n1 << blue + << v2 << n2 << green + + << v3 << n3 << white + << v1 << n1 << blue + << v0 << n0 << red + + << v0 << n0 << red + << v2 << n2 << green + << v3 << n3 << white + + << v1 << n1 << blue + << v3 << n3 << white + << v2 << n2 << green; + + + float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data()); + int idx = 0; + + Q_FOREACH (const QVector3D &v, vertices) { + rawVertexArray[idx++] = v.x(); + rawVertexArray[idx++] = v.y(); + rawVertexArray[idx++] = v.z(); + } + + vertexDataBuffer->setData(vertexBufferData); + + // Attributes + Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute(); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + positionAttribute->setBuffer(vertexDataBuffer); + positionAttribute->setDataType(Qt3DRender::QAttribute::Float); + positionAttribute->setDataSize(3); + positionAttribute->setByteOffset(0); + positionAttribute->setByteStride(9 * sizeof(float)); + positionAttribute->setCount(12); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + + Qt3DRender::QAttribute *normalAttribute = new Qt3DRender::QAttribute(); + normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + normalAttribute->setBuffer(vertexDataBuffer); + normalAttribute->setDataType(Qt3DRender::QAttribute::Float); + normalAttribute->setDataSize(3); + normalAttribute->setByteOffset(3 * sizeof(float)); + normalAttribute->setByteStride(9 * sizeof(float)); + normalAttribute->setCount(12); + normalAttribute->setName(Qt3DRender::QAttribute::defaultNormalAttributeName()); + + Qt3DRender::QAttribute *colorAttribute = new Qt3DRender::QAttribute(); + colorAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + colorAttribute->setBuffer(vertexDataBuffer); + colorAttribute->setDataType(Qt3DRender::QAttribute::Float); + colorAttribute->setDataSize(3); + colorAttribute->setByteOffset(6 * sizeof(float)); + colorAttribute->setByteStride(9 * sizeof(float)); + colorAttribute->setCount(12); + colorAttribute->setName(Qt3DRender::QAttribute::defaultColorAttributeName()); + + customGeometry->addAttribute(positionAttribute); + customGeometry->addAttribute(normalAttribute); + customGeometry->addAttribute(colorAttribute); + + customMeshRenderer->setInstanceCount(1); + customMeshRenderer->setBaseVertex(0); + customMeshRenderer->setBaseInstance(0); + customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); + customMeshRenderer->setGeometry(customGeometry); + // 4 faces of 3 points + customMeshRenderer->setPrimitiveCount(12); + + return customMeshRenderer; +} + +class TestAspect : public Qt3DRender::QRenderAspect +{ +public: + TestAspect(Qt3DCore::QNode *root) + : Qt3DRender::QRenderAspect() + { + Qt3DCore::QNodeVisitor visitor; + visitor.traverse(root, this, &TestAspect::visitNode); + } + + Qt3DRender::Render::NodeManagers *nodeManagers() const + { + return d_func()->m_renderer->nodeManagers(); + } + + void visitNode(Qt3DCore::QNode *node) + { + QAbstractAspect::createBackendNode(node); + } +}; + +class tst_TrianglesExtractor : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void triangles_data() + { + QTest::addColumn<Qt3DRender::QGeometryRenderer *>("geomRenderer"); + QTest::addColumn<QVector<Qt3DRender::Render::TriangleBoundingVolume *> >("expectedVolumes"); + + QVector<Qt3DRender::Render::TriangleBoundingVolume *> v = + QVector<Qt3DRender::Render::TriangleBoundingVolume *>() + << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), QVector3D(0, 1, 0), QVector3D(1, 0, -1), QVector3D(-1, 0, -1)) + << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), QVector3D(-1, 0, -1), QVector3D(1, 0, -1), QVector3D(0, 0, 1)) + << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), QVector3D(0, 0, 1), QVector3D(0, 1, 0), QVector3D(-1, 0, -1)) + << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), QVector3D(0, 1, 0), QVector3D(0, 0, 1), QVector3D(1, 0, -1)); + + QTest::newRow("indexedMesh") << customIndexedGeometryRenderer() << v; + QTest::newRow("nonIndexedMesh") << customNonIndexedGeometryRenderer() << v; + } + + void triangles() + { + // GIVEN + QFETCH(Qt3DRender::QGeometryRenderer *, geomRenderer); + QFETCH(QVector<Qt3DRender::Render::TriangleBoundingVolume *>, expectedVolumes); + TestAspect aspect(geomRenderer); + Qt3DRender::Render::NodeManagers *manager = aspect.nodeManagers(); + + // WHEN + Qt3DRender::Render::GeometryRenderer *bGeomRenderer = + manager->lookupResource + <Qt3DRender::Render::GeometryRenderer, + Qt3DRender::Render::GeometryRendererManager> + (geomRenderer->id()); + // THEN + QVERIFY(bGeomRenderer); + + // WHEN + Qt3DRender::Render::TrianglesExtractor extractor(bGeomRenderer, manager); + QVector<Qt3DCore::QBoundingVolume *> volumes = extractor.extract(Qt3DCore::QNodeId()); + + // THEN + QVERIFY(!volumes.empty()); + QCOMPARE(volumes.size(), expectedVolumes.size()); + for (int i = 0, m = volumes.size(); i < m; ++i) { + const Qt3DRender::Render::TriangleBoundingVolume *expectedVolume = expectedVolumes.at(i); + const Qt3DRender::Render::TriangleBoundingVolume *actualVolume = static_cast<Qt3DRender::Render::TriangleBoundingVolume *>(volumes.at(i)); + + QCOMPARE(expectedVolume->id(), actualVolume->id()); + QCOMPARE(expectedVolume->a(), actualVolume->a()); + QCOMPARE(expectedVolume->b(), actualVolume->b()); + QCOMPARE(expectedVolume->c(), actualVolume->c()); + } + } +}; + + +QTEST_MAIN(tst_TrianglesExtractor) + +#include "tst_trianglesextractor.moc" |