diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/extras/extras.pro | 3 | ||||
-rw-r--r-- | tests/auto/extras/qtorusgeometry/qtorusgeometry.pro | 12 | ||||
-rw-r--r-- | tests/auto/extras/qtorusgeometry/tst_qtorusgeometry.cpp | 366 |
3 files changed, 380 insertions, 1 deletions
diff --git a/tests/auto/extras/extras.pro b/tests/auto/extras/extras.pro index 3bba4d37b..381924d7b 100644 --- a/tests/auto/extras/extras.pro +++ b/tests/auto/extras/extras.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs SUBDIRS = \ - qcuboidgeometry + qcuboidgeometry \ + qtorusgeometry diff --git a/tests/auto/extras/qtorusgeometry/qtorusgeometry.pro b/tests/auto/extras/qtorusgeometry/qtorusgeometry.pro new file mode 100644 index 000000000..e20e447dc --- /dev/null +++ b/tests/auto/extras/qtorusgeometry/qtorusgeometry.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qtorusgeometry + +QT += 3dextras testlib + +CONFIG += testcase + +SOURCES += \ + tst_qtorusgeometry.cpp + +include(../common/common.pri) diff --git a/tests/auto/extras/qtorusgeometry/tst_qtorusgeometry.cpp b/tests/auto/extras/qtorusgeometry/tst_qtorusgeometry.cpp new file mode 100644 index 000000000..28fe76ae9 --- /dev/null +++ b/tests/auto/extras/qtorusgeometry/tst_qtorusgeometry.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 <QObject> +#include <Qt3DExtras/qtorusgeometry.h> +#include <Qt3DRender/qattribute.h> +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <QtGui/qopenglcontext.h> +#include <QtGui/qvector2d.h> +#include <QtGui/qvector3d.h> +#include <QtGui/qvector4d.h> +#include <QtCore/qdebug.h> +#include <QtCore/qsharedpointer.h> +#include <QSignalSpy> +#include <qmath.h> + +#include "geometrytesthelper.h" + +class tst_QTorusGeometry : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void defaultConstruction() + { + // WHEN + Qt3DExtras::QTorusGeometry geometry; + + // THEN + QCOMPARE(geometry.rings(), 16); + QCOMPARE(geometry.slices(), 16); + QCOMPARE(geometry.radius(), 1.0f); + QCOMPARE(geometry.minorRadius(), 1.0f); + QVERIFY(geometry.positionAttribute() != nullptr); + QCOMPARE(geometry.positionAttribute()->name(), Qt3DRender::QAttribute::defaultPositionAttributeName()); + QVERIFY(geometry.normalAttribute() != nullptr); + QCOMPARE(geometry.normalAttribute()->name(), Qt3DRender::QAttribute::defaultNormalAttributeName()); + QVERIFY(geometry.texCoordAttribute() != nullptr); + QCOMPARE(geometry.texCoordAttribute()->name(), Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); + // TODO: Expose tangent attribute in Qt 5.8 and see below +// QVERIFY(geometry.tangentAttribute() != nullptr); +// QCOMPARE(geometry.tangentAttribute()->name(), Qt3DRender::QAttribute::defaultTangentAttributeName()); + QVERIFY(geometry.indexAttribute() != nullptr); + } + + void properties() + { + // GIVEN + Qt3DExtras::QTorusGeometry geometry; + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(ringsChanged(int))); + const int newValue = 20; + geometry.setRings(newValue); + + // THEN + QCOMPARE(geometry.rings(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setRings(newValue); + + // THEN + QCOMPARE(geometry.rings(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(slicesChanged(int))); + const int newValue = 2.0f; + geometry.setSlices(newValue); + + // THEN + QCOMPARE(geometry.slices(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setSlices(newValue); + + // THEN + QCOMPARE(geometry.slices(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(radiusChanged(float))); + const float newValue = 2.0f; + geometry.setRadius(newValue); + + // THEN + QCOMPARE(geometry.radius(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setRadius(newValue); + + // THEN + QCOMPARE(geometry.radius(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&geometry, SIGNAL(minorRadiusChanged(float))); + const float newValue = 0.25f; + geometry.setMinorRadius(newValue); + + // THEN + QCOMPARE(geometry.minorRadius(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + geometry.setMinorRadius(newValue); + + // THEN + QCOMPARE(geometry.minorRadius(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void generatedGeometryShouldBeConsistent_data() + { + QTest::addColumn<int>("rings"); + QTest::addColumn<int>("slices"); + QTest::addColumn<float>("radius"); + QTest::addColumn<float>("minorRadius"); + QTest::addColumn<int>("triangleIndex"); + QTest::addColumn<QVector<quint16>>("indices"); + QTest::addColumn<QVector<QVector3D>>("positions"); + QTest::addColumn<QVector<QVector3D>>("normals"); + QTest::addColumn<QVector<QVector2D>>("texCoords"); + QTest::addColumn<QVector<QVector4D>>("tangents"); + + { + // Torus properties + const int rings = 8; + const int slices = 8; + const float radius = 2.0f; + const float minorRadius = 0.5f; + + // Angular factors for the vertices: + // u iterates around the major radius + // v iterates around the minor radius (around each ring) + const float du = float(2.0 * M_PI / rings); + const float dv = float(2.0 * M_PI / slices); + const float u0 = 0.0f; + const float u1 = du; + const float v0 = 0.0f; + const float v1 = dv; + + const float cosu0 = float(qCos(u0)); + const float sinu0 = float(qSin(u0)); + const float cosu1 = float(qCos(u1)); + const float sinu1 = float(qSin(u1)); + + const float cosv0 = float(qCos(v0 + M_PI)); // Seam is on inner edge + const float sinv0 = float(qSin(v0)); + const float cosv1 = float(qCos(v1 + M_PI)); + const float sinv1 = float(qSin(v1)); + + // The triangle and indices + const int triangleIndex = 0; + const auto indices = (QVector<quint16>() << 0 << 1 << 9); + + // Calculate attributes for vertices A, B, and C of the triangle + const float rA = radius + minorRadius * cosv0; + const float rB = radius + minorRadius * cosv1; + const float rC = radius + minorRadius * cosv0; + + const auto posA = QVector3D(rA * cosu0, rA * sinu0, minorRadius * sinv0); + const auto posB = QVector3D(rB * cosu0, rB * sinu0, minorRadius * sinv1); + const auto posC = QVector3D(rC * cosu1, rC * sinu1, minorRadius * sinv0); + const auto positions = (QVector<QVector3D>() << posA << posB << posC); + + const auto nA = QVector3D(cosv0 * cosu0, cosv0 * sinu0, sinv0).normalized(); + const auto nB = QVector3D(cosv1 * cosu0, cosv1 * sinu0, sinv1).normalized(); + const auto nC = QVector3D(cosv0 * cosu1, cosv0 * sinu1, sinv0).normalized(); + const auto normals = (QVector<QVector3D>() << nA << nB << nC); + + const auto tcA = QVector2D(u0, v0) / float(2.0 * M_PI); + const auto tcB = QVector2D(u0, v1) / float(2.0 * M_PI); + const auto tcC = QVector2D(u1, v0) / float(2.0 * M_PI); + const auto texCoords = (QVector<QVector2D>() << tcA << tcB << tcC); + + const auto tA = QVector4D(-sinu0, cosu0, 0.0f, 1.0f); + const auto tB = QVector4D(-sinu0, cosu0, 0.0f, 1.0f); + const auto tC = QVector4D(-sinu1, cosu1, 0.0f, 1.0f); + const auto tangents = (QVector<QVector4D>() << tA << tB << tC); + + // Add the row + QTest::newRow("8rings_8slices_firstTriangle") + << rings << slices << radius << minorRadius + << triangleIndex + << indices << positions << normals << texCoords << tangents; + } + + { + // Note: The vertices used in this test case are different than the + // ones above. So, we cannot abstract this into a function easily. + // Here we use the 2nd triangle in a rectangular face, the test above + // uses the first triangle in the rectangular face. + + // Torus properties + const int rings = 8; + const int slices = 8; + const float radius = 2.0f; + const float minorRadius = 0.5f; + + // Angular factors for the vertices: + // u iterates around the major radius + // v iterates around the minor radius (around each ring) + const float du = float(2.0 * M_PI / rings); + const float dv = float(2.0 * M_PI / slices); + const float u0 = 7.0f * du; + const float u1 = float(2.0 * M_PI); + const float v0 = 7.0f * dv; + const float v1 = float(2.0 * M_PI); + + const float cosu0 = float(qCos(u0)); + const float sinu0 = float(qSin(u0)); + const float cosu1 = float(qCos(u1)); + const float sinu1 = float(qSin(u1)); + + const float cosv0 = float(qCos(v0 + M_PI)); // Seam is on inner edge + const float sinv0 = float(qSin(v0)); + const float cosv1 = float(qCos(v1 + M_PI)); + const float sinv1 = float(qSin(v1)); + + // The triangle and indices + const int triangleIndex = 127; + const auto indices = (QVector<quint16>() << 71 << 80 << 79); + + // Calculate attributes for vertices A, B, and C of the triangle + const float rA = radius + minorRadius * cosv1; + const float rB = radius + minorRadius * cosv1; + const float rC = radius + minorRadius * cosv0; + + const auto posA = QVector3D(rA * cosu0, rA * sinu0, minorRadius * sinv1); + const auto posB = QVector3D(rB * cosu1, rB * sinu1, minorRadius * sinv1); + const auto posC = QVector3D(rC * cosu1, rC * sinu1, minorRadius * sinv0); + const auto positions = (QVector<QVector3D>() << posA << posB << posC); + + const auto nA = QVector3D(cosv1 * cosu0, cosv1 * sinu0, sinv1).normalized(); + const auto nB = QVector3D(cosv1 * cosu1, cosv1 * sinu1, sinv1).normalized(); + const auto nC = QVector3D(cosv0 * cosu1, cosv0 * sinu1, sinv0).normalized(); + const auto normals = (QVector<QVector3D>() << nA << nB << nC); + + const auto tcA = QVector2D(u0, v1) / float(2.0 * M_PI); + const auto tcB = QVector2D(u1, v1) / float(2.0 * M_PI); + const auto tcC = QVector2D(u1, v0) / float(2.0 * M_PI); + const auto texCoords = (QVector<QVector2D>() << tcA << tcB << tcC); + + const auto tA = QVector4D(-sinu0, cosu1, 0.0f, 1.0f); + const auto tB = QVector4D(-sinu1, cosu1, 0.0f, 1.0f); + const auto tC = QVector4D(-sinu1, cosu1, 0.0f, 1.0f); + const auto tangents = (QVector<QVector4D>() << tA << tB << tC); + + // Add the row + QTest::newRow("8rings_8slices_lastTriangle") + << rings << slices << radius << minorRadius + << triangleIndex + << indices << positions << normals << texCoords << tangents; + } + } + + void generatedGeometryShouldBeConsistent() + { + // GIVEN + Qt3DExtras::QTorusGeometry geometry; + const QVector<Qt3DRender::QAttribute *> attributes = geometry.attributes(); + Qt3DRender::QAttribute *positionAttribute = geometry.positionAttribute(); + Qt3DRender::QAttribute *normalAttribute = geometry.normalAttribute(); + Qt3DRender::QAttribute *texCoordAttribute = geometry.texCoordAttribute(); +// Qt3DRender::QAttribute *tangentAttribute = geometry.tangentAttribute(); + Qt3DRender::QAttribute *indexAttribute = geometry.indexAttribute(); + + // WHEN + QFETCH(int, rings); + QFETCH(int, slices); + QFETCH(float, radius); + QFETCH(float, minorRadius); + geometry.setRings(rings); + geometry.setSlices(slices); + geometry.setRadius(radius); + geometry.setMinorRadius(minorRadius); + + generateGeometry(geometry); + + // THEN + + // Check buffer of each attribute is valid and actually has some data + for (const auto &attribute : attributes) { + Qt3DRender::QBuffer *buffer = attribute->buffer(); + QVERIFY(buffer != nullptr); + QVERIFY(buffer->data().size() != 0); + } + + // Check some data in the buffers + + // Check specific indices and vertex attributes of triangle under test + QFETCH(int, triangleIndex); + QFETCH(QVector<quint16>, indices); + QFETCH(QVector<QVector3D>, positions); + QFETCH(QVector<QVector3D>, normals); + QFETCH(QVector<QVector2D>, texCoords); +// QFETCH(QVector<QVector4D>, tangents); + + int i = 0; + for (auto index : indices) { + const auto testIndex = extractIndexData<quint16>(indexAttribute, 3 * triangleIndex + i); + QCOMPARE(testIndex, indices.at(i)); + + const auto position = extractVertexData<QVector3D, quint32>(positionAttribute, index); + QVERIFY(qFuzzyCompare(position, positions.at(i))); + + const auto normal = extractVertexData<QVector3D, quint32>(normalAttribute, index); + QVERIFY(qFuzzyCompare(normal, normals.at(i))); + + const auto texCoord = extractVertexData<QVector2D, quint32>(texCoordAttribute, index); + QVERIFY(qFuzzyCompare(texCoord, texCoords.at(i))); + +// const auto tangent = extractVertexData<QVector4D, quint32>(tangentAttribute, index); +// QVERIFY(qFuzzyCompare(tangent, tangents.at(i))); + + ++i; + } + } +}; + + +QTEST_APPLESS_MAIN(tst_QTorusGeometry) + +#include "tst_qtorusgeometry.moc" |