diff options
Diffstat (limited to 'tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp')
-rw-r--r-- | tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp | 132 |
1 files changed, 71 insertions, 61 deletions
diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp index b9ba7278da..8cdc06354e 100644 --- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp +++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp @@ -1,30 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses #include <QTest> #include <QtCore/qmath.h> @@ -600,7 +577,7 @@ void tst_QQuaternion::multiply_data() for (float x = -1.0f; x <= 1.0f; x += 0.5f) for (float y = -1.0f; y <= 1.0f; y += 0.5f) for (float z = -1.0f; z <= 1.0f; z += 0.5f) { - QTest::newRow("exhaustive") + QTest::addRow("exhaustive: (%.1f, %.1f, %.1f), %.1f", x, y, z, w) << x << y << z << w << z << w << y << x; } @@ -905,7 +882,7 @@ void tst_QQuaternion::fromAxes_data() QTest::newRow("complex") << 1.0f << 2.0f << -3.0f << 45.0f - << QVector3D(0.728028, -0.525105, -0.440727) << QVector3D(0.608789, 0.790791, 0.0634566) << QVector3D(0.315202, -0.314508, 0.895395); + << QVector3D(0.728028f, -0.525105f, -0.440727f) << QVector3D(0.608789f, 0.790791f, 0.0634566f) << QVector3D(0.315202f, -0.314508f, 0.895395f); } void tst_QQuaternion::fromAxes() { @@ -987,28 +964,6 @@ void tst_QQuaternion::rotationTo() QVERIFY(myFuzzyCompare(vec2, from)); } -static QByteArray testnameForAxis(const QVector3D &axis) -{ - QByteArray testname; - if (axis == QVector3D()) { - testname = "null"; - } else { - if (axis.x()) { - testname += axis.x() < 0 ? '-' : '+'; - testname += 'X'; - } - if (axis.y()) { - testname += axis.y() < 0 ? '-' : '+'; - testname += 'Y'; - } - if (axis.z()) { - testname += axis.z() < 0 ? '-' : '+'; - testname += 'Z'; - } - } - return testname; -} - // Test quaternion convertion to and from orthonormal axes. void tst_QQuaternion::fromDirection_data() { @@ -1031,7 +986,10 @@ void tst_QQuaternion::fromDirection_data() QVector3D xAxis, yAxis, zAxis; q.getAxes(&xAxis, &yAxis, &zAxis); - QTest::newRow("dir: " + testnameForAxis(zAxis) + ", up: " + testnameForAxis(yAxis)) + QTest::addRow("ortho dirs: (%.1f,%.1f,%.1f), (%.1f,%.1f,%.1f), (%.1f,%.1f,%.1f)", + xAxis.x(), xAxis.y(), xAxis.z(), + yAxis.x(), yAxis.y(), yAxis.z(), + zAxis.x(), zAxis.y(), zAxis.z()) << zAxis * 10.0f << yAxis * 10.0f; } @@ -1050,7 +1008,10 @@ void tst_QQuaternion::fromDirection_data() QVector3D xAxis, yAxis, zAxis; q.getAxes(&xAxis, &yAxis, &zAxis); - QTest::newRow("dir: " + testnameForAxis(zAxis) + ", up: null") + QTest::addRow("bad dirs: (%.1f,%.1f,%.1f), (%.1f,%.1f,%.1f), (%.1f,%.1f,%.1f)", + xAxis.x(), xAxis.y(), xAxis.z(), + yAxis.x(), yAxis.y(), yAxis.z(), + zAxis.x(), zAxis.y(), zAxis.z()) << zAxis * 10.0f << QVector3D(); } } @@ -1085,35 +1046,67 @@ void tst_QQuaternion::fromEulerAngles_data() QTest::addColumn<float>("yaw"); QTest::addColumn<float>("roll"); + QTest::addColumn<QQuaternion>("quaternion"); + QTest::newRow("null") - << 0.0f << 0.0f << 0.0f; + << 0.0f << 0.0f << 0.0f << QQuaternion(1.0f, 0.0f, 0.0f, 0.0f); QTest::newRow("xonly") - << 90.0f << 0.0f << 0.0f; + << 90.0f << 0.0f << 0.0f << QQuaternion(0.707107f, 0.707107f, 0.0f, 0.0f); QTest::newRow("yonly") - << 0.0f << 180.0f << 0.0f; + << 0.0f << 180.0f << 0.0f << QQuaternion(0.0f, 0.0f, 1.0f, 0.0f); QTest::newRow("zonly") - << 0.0f << 0.0f << 270.0f; + << 0.0f << 0.0f << 270.0f << QQuaternion(-0.707107f, 0.0f, 0.0f, 0.707107f); QTest::newRow("x+z") - << 30.0f << 0.0f << 45.0f; + << 30.0f << 0.0f << 45.0f << QQuaternion(0.892399f, 0.239118f, -0.099046f, 0.369644f); QTest::newRow("x+y") - << 30.0f << 90.0f << 0.0f; + << 30.0f << 90.0f << 0.0f << QQuaternion(0.683013f, 0.183013f, 0.683013f, -0.183013f); QTest::newRow("y+z") - << 0.0f << 45.0f << 30.0f; + << 0.0f << 45.0f << 30.0f << QQuaternion(0.892399f, 0.099046f, 0.369644f, 0.239118f); QTest::newRow("complex") - << 30.0f << 240.0f << -45.0f; + << 30.0f << 240.0f << -45.0f << QQuaternion(-0.531976f, -0.43968f, 0.723317f, -0.02226f); + + // Three gimbal_lock cases are not unique for the conversions from quaternion + // to euler, Qt will use only XY rotations for these cases. + // For example, QQuaternion(0.5f, 0.5f, -0.5f, 0.5f) can be EulerXYZ(90.0f, 0.0f, 90.0f), too. + // But Qt will always convert it to EulerXYZ(90.0f, -90.0f, 0.0f) without Z-rotation. + QTest::newRow("gimbal_lock_1") + << 90.0f << -90.0f << 0.0f << QQuaternion(0.5f, 0.5f, -0.5f, 0.5f); + + QTest::newRow("gimbal_lock_2") + << 90.0f << 40.0f << 0.0f << QQuaternion(0.664463f, 0.664463f, 0.241845f, -0.241845f); + + QTest::newRow("gimbal_lock_3") << 90.0f << 170.0f << 0.0f + << QQuaternion(0.0616285f, 0.0616285f, 0.704416f, -0.704416f); + + // These four examples have a fraction of errors that would bypass normalize() threshold + // and could make Gimbal lock detection fail. + QTest::newRow("gimbal_lock_fraction_1") + << -90.0f << 90.001152f << 0.0f << QQuaternion(0.499989986f, -0.5f, 0.5f, 0.5f); + + QTest::newRow("gimbal_lock_fraction_2") + << -90.0f << -179.999985f << 0.0f + << QQuaternion(1.00000001e-07f, 1.00000001e-10f, -0.707106769f, -0.707105756f); + + QTest::newRow("gimbal_lock_fraction_3") + << -90.0f << 90.0011597f << 0.0f << QQuaternion(0.499989986f, -0.49999994f, 0.5f, 0.5f); + + QTest::newRow("gimbal_lock_fraction_4") + << -90.0f << -180.0f << 0.0f + << QQuaternion(9.99999996e-12f, 9.99999996e-12f, -0.707106769f, -0.707096756f); } void tst_QQuaternion::fromEulerAngles() { QFETCH(float, pitch); QFETCH(float, yaw); QFETCH(float, roll); + QFETCH(QQuaternion, quaternion); // Use a straight-forward implementation of the algorithm at: // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60 @@ -1129,11 +1122,22 @@ void tst_QQuaternion::fromEulerAngles() QVERIFY(myFuzzyCompare(answer.z(), result.z())); QVERIFY(myFuzzyCompare(answer.scalar(), result.scalar())); + // quaternion should be the same as the result + QVERIFY(myFuzzyCompare(answer.x(), quaternion.x())); + QVERIFY(myFuzzyCompare(answer.y(), quaternion.y())); + QVERIFY(myFuzzyCompare(answer.z(), quaternion.z())); + QVERIFY(myFuzzyCompare(answer.scalar(), quaternion.scalar())); + { QVector3D answerEulerAngles = answer.toEulerAngles(); QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.x(), pitch)); QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.y(), yaw)); QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.z(), roll)); + + QVector3D quaternionEulerAngles = quaternion.toEulerAngles(); + QVERIFY(myFuzzyCompareDegrees(quaternionEulerAngles.x(), pitch)); + QVERIFY(myFuzzyCompareDegrees(quaternionEulerAngles.y(), yaw)); + QVERIFY(myFuzzyCompareDegrees(quaternionEulerAngles.z(), roll)); } answer = QQuaternion::fromEulerAngles(pitch, yaw, roll); @@ -1148,6 +1152,12 @@ void tst_QQuaternion::fromEulerAngles() QVERIFY(myFuzzyCompareDegrees(answerPitch, pitch)); QVERIFY(myFuzzyCompareDegrees(answerYaw, yaw)); QVERIFY(myFuzzyCompareDegrees(answerRoll, roll)); + + float quaternionPitch, quaternionYaw, quaternionRoll; + quaternion.getEulerAngles(&quaternionPitch, &quaternionYaw, &quaternionRoll); + QVERIFY(myFuzzyCompareDegrees(quaternionPitch, pitch)); + QVERIFY(myFuzzyCompareDegrees(quaternionYaw, yaw)); + QVERIFY(myFuzzyCompareDegrees(quaternionRoll, roll)); } } |