summaryrefslogtreecommitdiffstats
path: root/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp')
-rw-r--r--tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp197
1 files changed, 190 insertions, 7 deletions
diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
index cdbc242640..444ccdeb88 100644
--- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
+++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
+** 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
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -54,6 +54,9 @@ private slots:
void normalize_data();
void normalize();
+ void inverted_data();
+ void inverted();
+
void compare();
void add_data();
@@ -80,6 +83,12 @@ private slots:
void fromAxisAndAngle_data();
void fromAxisAndAngle();
+ void fromRotationMatrix_data();
+ void fromRotationMatrix();
+
+ void fromEulerAngles_data();
+ void fromEulerAngles();
+
void slerp_data();
void slerp();
@@ -291,6 +300,32 @@ void tst_QQuaternion::normalize()
QCOMPARE(v.length(), 1.0f);
}
+void tst_QQuaternion::inverted_data()
+{
+ // Use the same test data as the length test.
+ length_data();
+}
+void tst_QQuaternion::inverted()
+{
+ QFETCH(float, x);
+ QFETCH(float, y);
+ QFETCH(float, z);
+ QFETCH(float, w);
+ QFETCH(float, len);
+
+ QQuaternion v(w, x, y, z);
+ QQuaternion u = v.inverted();
+ if (v.isNull()) {
+ QVERIFY(u.isNull());
+ } else {
+ len *= len;
+ QCOMPARE(-u.x() * len, v.x());
+ QCOMPARE(-u.y() * len, v.y());
+ QCOMPARE(-u.z() * len, v.z());
+ QCOMPARE(u.scalar() * len, v.scalar());
+ }
+}
+
// Test the comparison operators for quaternions.
void tst_QQuaternion::compare()
{
@@ -689,11 +724,159 @@ void tst_QQuaternion::fromAxisAndAngle()
QVERIFY(qFuzzyCompare(answer.z(), result.z()));
QVERIFY(qFuzzyCompare(answer.scalar(), result.scalar()));
+ {
+ QVector3D answerAxis;
+ float answerAngle;
+ answer.toAxisAndAngle(&answerAxis, &answerAngle);
+ QVERIFY(qFuzzyCompare(answerAxis.x(), vector.x()));
+ QVERIFY(qFuzzyCompare(answerAxis.y(), vector.y()));
+ QVERIFY(qFuzzyCompare(answerAxis.z(), vector.z()));
+ QVERIFY(qFuzzyCompare(answerAngle, angle));
+ }
+
answer = QQuaternion::fromAxisAndAngle(x1, y1, z1, angle);
QVERIFY(qFuzzyCompare(answer.x(), result.x()));
QVERIFY(qFuzzyCompare(answer.y(), result.y()));
QVERIFY(qFuzzyCompare(answer.z(), result.z()));
QVERIFY(qFuzzyCompare(answer.scalar(), result.scalar()));
+
+ {
+ float answerAxisX, answerAxisY, answerAxisZ;
+ float answerAngle;
+ answer.toAxisAndAngle(&answerAxisX, &answerAxisY, &answerAxisZ, &answerAngle);
+ QVERIFY(qFuzzyCompare(answerAxisX, vector.x()));
+ QVERIFY(qFuzzyCompare(answerAxisY, vector.y()));
+ QVERIFY(qFuzzyCompare(answerAxisZ, vector.z()));
+ QVERIFY(qFuzzyCompare(answerAngle, angle));
+ }
+}
+
+// Test quaternion convertion to and from rotation matrix.
+void tst_QQuaternion::fromRotationMatrix_data()
+{
+ fromAxisAndAngle_data();
+}
+void tst_QQuaternion::fromRotationMatrix()
+{
+ QFETCH(float, x1);
+ QFETCH(float, y1);
+ QFETCH(float, z1);
+ QFETCH(float, angle);
+
+ QQuaternion result = QQuaternion::fromAxisAndAngle(QVector3D(x1, y1, z1), angle);
+ QMatrix3x3 rot3x3 = result.toRotationMatrix();
+ QQuaternion answer = QQuaternion::fromRotationMatrix(rot3x3);
+
+ QVERIFY(qFuzzyCompare(answer, result) || qFuzzyCompare(-answer, result));
+}
+
+// This is a more tolerant version of qFuzzyCompare that also handles the case
+// where one or more of the values being compare are close to zero
+static inline bool myFuzzyCompare(float p1, float p2)
+{
+ if (qFuzzyIsNull(p1))
+ return qFuzzyIsNull(p2);
+ if (qFuzzyIsNull(p2))
+ return false;
+ // a very slightly looser version of qFuzzyCompare
+ // for use with values that are not very close to zero
+ return qAbs(p1 - p2) <= 0.00003f * qMin(qAbs(p1), qAbs(p2));
+}
+
+static inline bool myFuzzyCompareRadians(float p1, float p2)
+{
+ static const float fPI = float(M_PI);
+ if (p1 < -fPI)
+ p1 += 2.0f * fPI;
+ else if (p1 > fPI)
+ p1 -= 2.0f * fPI;
+
+ if (p2 < -fPI)
+ p2 += 2.0f * fPI;
+ else if (p2 > fPI)
+ p2 -= 2.0f * fPI;
+
+ return qAbs(qAbs(p1) - qAbs(p2)) <= qDegreesToRadians(0.05f);
+}
+
+static inline bool myFuzzyCompareDegrees(float p1, float p2)
+{
+ p1 = qDegreesToRadians(p1);
+ p2 = qDegreesToRadians(p2);
+ return myFuzzyCompareRadians(p1, p2);
+}
+
+// Test quaternion creation from an axis and an angle.
+void tst_QQuaternion::fromEulerAngles_data()
+{
+ QTest::addColumn<float>("pitch");
+ QTest::addColumn<float>("yaw");
+ QTest::addColumn<float>("roll");
+
+ QTest::newRow("null")
+ << 0.0f << 0.0f << 0.0f;
+
+ QTest::newRow("xonly")
+ << 90.0f << 0.0f << 0.0f;
+
+ QTest::newRow("yonly")
+ << 0.0f << 180.0f << 0.0f;
+
+ QTest::newRow("zonly")
+ << 0.0f << 0.0f << 270.0f;
+
+ QTest::newRow("x+z")
+ << 30.0f << 0.0f << 45.0f;
+
+ QTest::newRow("x+y")
+ << 30.0f << 90.0f << 0.0f;
+
+ QTest::newRow("y+z")
+ << 0.0f << 45.0f << 30.0f;
+
+ QTest::newRow("complex")
+ << 30.0f << 240.0f << -45.0f;
+}
+void tst_QQuaternion::fromEulerAngles()
+{
+ QFETCH(float, pitch);
+ QFETCH(float, yaw);
+ QFETCH(float, roll);
+
+ // Use a straight-forward implementation of the algorithm at:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60
+ // to calculate the answer we expect to get.
+ QQuaternion qx = QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), pitch);
+ QQuaternion qy = QQuaternion::fromAxisAndAngle(QVector3D(0, 1, 0), yaw);
+ QQuaternion qz = QQuaternion::fromAxisAndAngle(QVector3D(0, 0, 1), roll);
+ QQuaternion result = qy * (qx * qz);
+ QQuaternion answer = QQuaternion::fromEulerAngles(QVector3D(pitch, yaw, roll));
+
+ QVERIFY(myFuzzyCompare(answer.x(), result.x()));
+ QVERIFY(myFuzzyCompare(answer.y(), result.y()));
+ QVERIFY(myFuzzyCompare(answer.z(), result.z()));
+ QVERIFY(myFuzzyCompare(answer.scalar(), result.scalar()));
+
+ {
+ QVector3D answerEulerAngles = answer.toEulerAngles();
+ QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.x(), pitch));
+ QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.y(), yaw));
+ QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.z(), roll));
+ }
+
+ answer = QQuaternion::fromEulerAngles(pitch, yaw, roll);
+ QVERIFY(myFuzzyCompare(answer.x(), result.x()));
+ QVERIFY(myFuzzyCompare(answer.y(), result.y()));
+ QVERIFY(myFuzzyCompare(answer.z(), result.z()));
+ QVERIFY(myFuzzyCompare(answer.scalar(), result.scalar()));
+
+ {
+ float answerPitch, answerYaw, answerRoll;
+ answer.toEulerAngles(&answerPitch, &answerYaw, &answerRoll);
+ QVERIFY(myFuzzyCompareDegrees(answerPitch, pitch));
+ QVERIFY(myFuzzyCompareDegrees(answerYaw, yaw));
+ QVERIFY(myFuzzyCompareDegrees(answerRoll, roll));
+ }
}
// Test spherical interpolation of quaternions.