diff options
Diffstat (limited to 'tests/auto/gui/math3d')
-rw-r--r-- | tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp | 20 | ||||
-rw-r--r-- | tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp | 386 | ||||
-rw-r--r-- | tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp | 339 |
3 files changed, 707 insertions, 38 deletions
diff --git a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp index 5ce833eb3a..e7659a25bd 100644 --- a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp +++ b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.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$ @@ -2279,9 +2279,9 @@ void tst_QMatrixNxN::rotate4x4_data() float y = 2.0f; float z = -6.0f; float angle = -45.0f; - float c = qCos(angle * M_PI / 180.0f); - float s = qSin(angle * M_PI / 180.0f); - float len = sqrtf(x * x + y * y + z * z); + float c = std::cos(angle * M_PI / 180.0f); + float s = std::sin(angle * M_PI / 180.0f); + float len = std::sqrt(x * x + y * y + z * z); float xu = x / len; float yu = y / len; float zu = z / len; diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp index cdbc242640..2c38e4c111 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$ @@ -35,6 +35,52 @@ #include <QtCore/qmath.h> #include <QtGui/qquaternion.h> +// 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) && qFuzzyIsNull(p2)) + return true; + return qAbs(qAbs(p1) - qAbs(p2)) <= 0.00003f; +} + +static inline bool myFuzzyCompare(const QVector3D &v1, const QVector3D &v2) +{ + return myFuzzyCompare(v1.x(), v2.x()) + && myFuzzyCompare(v1.y(), v2.y()) + && myFuzzyCompare(v1.z(), v2.z()); +} + +static inline bool myFuzzyCompare(const QQuaternion &q1, const QQuaternion &q2) +{ + const float d = QQuaternion::dotProduct(q1, q2); + return myFuzzyCompare(d * d, 1.0f); +} + +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); +} + + class tst_QQuaternion : public QObject { Q_OBJECT @@ -45,6 +91,9 @@ public: private slots: void create(); + void dotProduct_data(); + void dotProduct(); + void length_data(); void length(); @@ -54,6 +103,9 @@ private slots: void normalize_data(); void normalize(); + void inverted_data(); + void inverted(); + void compare(); void add_data(); @@ -80,6 +132,18 @@ private slots: void fromAxisAndAngle_data(); void fromAxisAndAngle(); + void fromRotationMatrix_data(); + void fromRotationMatrix(); + + void fromAxes_data(); + void fromAxes(); + + void rotationTo_data(); + void rotationTo(); + + void fromEulerAngles_data(); + void fromEulerAngles(); + void slerp_data(); void slerp(); @@ -210,6 +274,58 @@ void tst_QQuaternion::create() QCOMPARE(v10.w(), 34.0f); } +// Test the computation of dot product. +void tst_QQuaternion::dotProduct_data() +{ + QTest::addColumn<float>("x1"); + QTest::addColumn<float>("y1"); + QTest::addColumn<float>("z1"); + QTest::addColumn<float>("scalar1"); + QTest::addColumn<float>("x2"); + QTest::addColumn<float>("y2"); + QTest::addColumn<float>("z2"); + QTest::addColumn<float>("scalar2"); + QTest::addColumn<float>("dot"); + + QTest::newRow("null") + << 0.0f << 0.0f << 0.0f << 0.0f + << 0.0f << 0.0f << 0.0f << 0.0f + << 0.0f; + + QTest::newRow("identity") + << 0.0f << 0.0f << 0.0f << 1.0f + << 0.0f << 0.0f << 0.0f << 1.0f + << 1.0f; + + QTest::newRow("unitvec") + << 1.0f << 0.0f << 0.0f << 0.0f + << 0.0f << 1.0f << 0.0f << 0.0f + << 0.0f; + + QTest::newRow("complex") + << 1.0f << 2.0f << 3.0f << 4.0f + << 4.0f << 5.0f << 6.0f << 7.0f + << 60.0f; +} +void tst_QQuaternion::dotProduct() +{ + QFETCH(float, x1); + QFETCH(float, y1); + QFETCH(float, z1); + QFETCH(float, scalar1); + QFETCH(float, x2); + QFETCH(float, y2); + QFETCH(float, z2); + QFETCH(float, scalar2); + QFETCH(float, dot); + + QQuaternion q1(scalar1, x1, y1, z1); + QQuaternion q2(scalar2, x2, y2, z2); + + QCOMPARE(QQuaternion::dotProduct(q1, q2), dot); + QCOMPARE(QQuaternion::dotProduct(q2, q1), dot); +} + // Test length computation for quaternions. void tst_QQuaternion::length_data() { @@ -228,7 +344,7 @@ void tst_QQuaternion::length_data() QTest::newRow("-1y") << 0.0f << -1.0f << 0.0f << 0.0f << 1.0f; QTest::newRow("-1z") << 0.0f << 0.0f << -1.0f << 0.0f << 1.0f; QTest::newRow("-1w") << 0.0f << 0.0f << 0.0f << -1.0f << 1.0f; - QTest::newRow("two") << 2.0f << -2.0f << 2.0f << 2.0f << sqrtf(16.0f); + QTest::newRow("two") << 2.0f << -2.0f << 2.0f << 2.0f << std::sqrt(16.0f); } void tst_QQuaternion::length() { @@ -291,6 +407,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() { @@ -675,8 +817,9 @@ void tst_QQuaternion::fromAxisAndAngle() // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56 // to calculate the answer we expect to get. QVector3D vector = QVector3D(x1, y1, z1).normalized(); - float sin_a = sinf((angle * M_PI / 180.0) / 2.0); - float cos_a = cosf((angle * M_PI / 180.0) / 2.0); + const float a = (angle * M_PI / 180.0) / 2.0; + const float sin_a = std::sin(a); + const float cos_a = std::cos(a); QQuaternion result(cos_a, (vector.x() * sin_a), (vector.y() * sin_a), @@ -689,11 +832,234 @@ void tst_QQuaternion::fromAxisAndAngle() QVERIFY(qFuzzyCompare(answer.z(), result.z())); QVERIFY(qFuzzyCompare(answer.scalar(), result.scalar())); + { + QVector3D answerAxis; + float answerAngle; + answer.getAxisAndAngle(&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.getAxisAndAngle(&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)); +} + +// Test quaternion convertion to and from orthonormal axes. +void tst_QQuaternion::fromAxes_data() +{ + QTest::addColumn<float>("x1"); + QTest::addColumn<float>("y1"); + QTest::addColumn<float>("z1"); + QTest::addColumn<float>("angle"); + QTest::addColumn<QVector3D>("xAxis"); + QTest::addColumn<QVector3D>("yAxis"); + QTest::addColumn<QVector3D>("zAxis"); + + QTest::newRow("null") + << 0.0f << 0.0f << 0.0f << 0.0f + << QVector3D(1, 0, 0) << QVector3D(0, 1, 0) << QVector3D(0, 0, 1); + + QTest::newRow("xonly") + << 1.0f << 0.0f << 0.0f << 90.0f + << QVector3D(1, 0, 0) << QVector3D(0, 0, 1) << QVector3D(0, -1, 0); + + QTest::newRow("yonly") + << 0.0f << 1.0f << 0.0f << 180.0f + << QVector3D(-1, 0, 0) << QVector3D(0, 1, 0) << QVector3D(0, 0, -1); + + QTest::newRow("zonly") + << 0.0f << 0.0f << 1.0f << 270.0f + << QVector3D(0, -1, 0) << QVector3D(1, 0, 0) << QVector3D(0, 0, 1); + + 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); +} +void tst_QQuaternion::fromAxes() +{ + QFETCH(float, x1); + QFETCH(float, y1); + QFETCH(float, z1); + QFETCH(float, angle); + QFETCH(QVector3D, xAxis); + QFETCH(QVector3D, yAxis); + QFETCH(QVector3D, zAxis); + + QQuaternion result = QQuaternion::fromAxisAndAngle(QVector3D(x1, y1, z1), angle); + + QVector3D axes[3]; + result.getAxes(&axes[0], &axes[1], &axes[2]); + QVERIFY(myFuzzyCompare(axes[0], xAxis)); + QVERIFY(myFuzzyCompare(axes[1], yAxis)); + QVERIFY(myFuzzyCompare(axes[2], zAxis)); + + QQuaternion answer = QQuaternion::fromAxes(axes[0], axes[1], axes[2]); + + QVERIFY(qFuzzyCompare(answer, result) || qFuzzyCompare(-answer, result)); +} + +// Test shortest arc quaternion. +void tst_QQuaternion::rotationTo_data() +{ + QTest::addColumn<QVector3D>("from"); + QTest::addColumn<QVector3D>("to"); + + // same + QTest::newRow("+X -> +X") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(10.0f, 0.0f, 0.0f); + QTest::newRow("-X -> -X") << QVector3D(-10.0f, 0.0f, 0.0f) << QVector3D(-10.0f, 0.0f, 0.0f); + QTest::newRow("+Y -> +Y") << QVector3D(0.0f, 10.0f, 0.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("-Y -> -Y") << QVector3D(0.0f, -10.0f, 0.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("+Z -> +Z") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, 0.0f, 10.0f); + QTest::newRow("-Z -> -Z") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(0.0f, 0.0f, -10.0f); + QTest::newRow("+X+Y+Z -> +X+Y+Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(10.0f, 10.0f, 10.0f); + QTest::newRow("-X-Y-Z -> -X-Y-Z") << QVector3D(-10.0f, -10.0f, -10.0f) << QVector3D(-10.0f, -10.0f, -10.0f); + + // arbitrary + QTest::newRow("+Z -> +X") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(10.0f, 0.0f, 0.0f); + QTest::newRow("+Z -> -X") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(-10.0f, 0.0f, 0.0f); + QTest::newRow("+Z -> +Y") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("+Z -> -Y") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("-Z -> +X") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(10.0f, 0.0f, 0.0f); + QTest::newRow("-Z -> -X") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(-10.0f, 0.0f, 0.0f); + QTest::newRow("-Z -> +Y") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("-Z -> -Y") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("+X -> +Y") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("+X -> -Y") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("-X -> +Y") << QVector3D(-10.0f, 0.0f, 0.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("-X -> -Y") << QVector3D(-10.0f, 0.0f, 0.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("+X+Y+Z -> +X-Y-Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(10.0f, -10.0f, -10.0f); + QTest::newRow("-X-Y+Z -> -X+Y-Z") << QVector3D(-10.0f, -10.0f, 10.0f) << QVector3D(-10.0f, 10.0f, -10.0f); + QTest::newRow("+X+Y+Z -> +Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(0.0f, 0.0f, 10.0f); + + // collinear + QTest::newRow("+X -> -X") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(-10.0f, 0.0f, 0.0f); + QTest::newRow("+Y -> -Y") << QVector3D(0.0f, 10.0f, 0.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("+Z -> -Z") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, 0.0f, -10.0f); + QTest::newRow("+X+Y+Z -> -X-Y-Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(-10.0f, -10.0f, -10.0f); +} +void tst_QQuaternion::rotationTo() +{ + QFETCH(QVector3D, from); + QFETCH(QVector3D, to); + + QQuaternion q1 = QQuaternion::rotationTo(from, to); + QVERIFY(myFuzzyCompare(q1, q1.normalized())); + QVector3D vec1(q1 * from); + vec1 *= (to.length() / from.length()); // discard rotated length + QVERIFY(myFuzzyCompare(vec1, to)); + + QQuaternion q2 = QQuaternion::rotationTo(to, from); + QVERIFY(myFuzzyCompare(q2, q2.normalized())); + QVector3D vec2(q2 * to); + vec2 *= (from.length() / to.length()); // discard rotated length + QVERIFY(myFuzzyCompare(vec2, from)); +} + +// 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.getEulerAngles(&answerPitch, &answerYaw, &answerRoll); + QVERIFY(myFuzzyCompareDegrees(answerPitch, pitch)); + QVERIFY(myFuzzyCompareDegrees(answerYaw, yaw)); + QVERIFY(myFuzzyCompareDegrees(answerRoll, roll)); + } } // Test spherical interpolation of quaternions. diff --git a/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp b/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp index 2d4b6d16b0..d2e0bbe375 100644 --- a/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp +++ b/tests/auto/gui/math3d/qvectornd/tst_qvectornd.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$ @@ -36,6 +36,7 @@ #include <QtGui/qvector2d.h> #include <QtGui/qvector3d.h> #include <QtGui/qvector4d.h> +#include <QtGui/qmatrix4x4.h> class tst_QVectorND : public QObject { @@ -113,6 +114,13 @@ private slots: void divide4_data(); void divide4(); + void divideFactor2_data(); + void divideFactor2(); + void divideFactor3_data(); + void divideFactor3(); + void divideFactor4_data(); + void divideFactor4(); + void negate2_data(); void negate2(); void negate3_data(); @@ -142,6 +150,11 @@ private slots: void dotProduct4_data(); void dotProduct4(); + void project_data(); + void project(); + void unproject_data(); + void unproject(); + void properties(); void metaTypes(); }; @@ -654,7 +667,7 @@ void tst_QVectorND::length2_data() QTest::newRow("1y") << 0.0f << 1.0f << 1.0f; QTest::newRow("-1x") << -1.0f << 0.0f << 1.0f; QTest::newRow("-1y") << 0.0f << -1.0f << 1.0f; - QTest::newRow("two") << 2.0f << -2.0f << sqrtf(8.0f); + QTest::newRow("two") << 2.0f << -2.0f << std::sqrt(8.0f); } void tst_QVectorND::length2() { @@ -682,7 +695,7 @@ void tst_QVectorND::length3_data() QTest::newRow("-1x") << -1.0f << 0.0f << 0.0f << 1.0f; QTest::newRow("-1y") << 0.0f << -1.0f << 0.0f << 1.0f; QTest::newRow("-1z") << 0.0f << 0.0f << -1.0f << 1.0f; - QTest::newRow("two") << 2.0f << -2.0f << 2.0f << sqrtf(12.0f); + QTest::newRow("two") << 2.0f << -2.0f << 2.0f << std::sqrt(12.0f); } void tst_QVectorND::length3() { @@ -714,7 +727,7 @@ void tst_QVectorND::length4_data() QTest::newRow("-1y") << 0.0f << -1.0f << 0.0f << 0.0f << 1.0f; QTest::newRow("-1z") << 0.0f << 0.0f << -1.0f << 0.0f << 1.0f; QTest::newRow("-1w") << 0.0f << 0.0f << 0.0f << -1.0f << 1.0f; - QTest::newRow("two") << 2.0f << -2.0f << 2.0f << 2.0f << sqrtf(16.0f); + QTest::newRow("two") << 2.0f << -2.0f << 2.0f << 2.0f << std::sqrt(16.0f); } void tst_QVectorND::length4() { @@ -1623,16 +1636,154 @@ void tst_QVectorND::multiplyFactor4() QCOMPARE(v3.w(), v1.w() * factor); } -// Test vector division by a factor for 2D vectors. +// Test component-wise vector division for 2D vectors. void tst_QVectorND::divide2_data() { // Use the same test data as the multiply test. - multiplyFactor2_data(); + multiply2_data(); } void tst_QVectorND::divide2() { QFETCH(float, x1); QFETCH(float, y1); + QFETCH(float, x2); + QFETCH(float, y2); + QFETCH(float, x3); + QFETCH(float, y3); + + QVector2D v1(x1, y1); + QVector2D v2(x2, y2); + QVector2D v3(x3, y3); + + if (v2.x() != 0.0f && v2.y() != 0.0f) { + QVERIFY((v3 / v2) == v1); + + QVector2D v4(v3); + v4 /= v2; + QVERIFY(v4 == v1); + + QCOMPARE(v4.x(), v3.x() / v2.x()); + QCOMPARE(v4.y(), v3.y() / v2.y()); + } + if (v1.x() != 0.0f && v1.y() != 0.0f) { + QVERIFY((v3 / v1) == v2); + + QVector2D v4(v3); + v4 /= v1; + QVERIFY(v4 == v2); + + QCOMPARE(v4.x(), v3.x() / v1.x()); + QCOMPARE(v4.y(), v3.y() / v1.y()); + } +} + +// Test component-wise vector division for 3D vectors. +void tst_QVectorND::divide3_data() +{ + // Use the same test data as the multiply test. + multiply3_data(); +} +void tst_QVectorND::divide3() +{ + QFETCH(float, x1); + QFETCH(float, y1); + QFETCH(float, z1); + QFETCH(float, x2); + QFETCH(float, y2); + QFETCH(float, z2); + QFETCH(float, x3); + QFETCH(float, y3); + QFETCH(float, z3); + + QVector3D v1(x1, y1, z1); + QVector3D v2(x2, y2, z2); + QVector3D v3(x3, y3, z3); + + if (v2.x() != 0.0f && v2.y() != 0.0f && v2.z() != 0.0f) { + QVERIFY((v3 / v2) == v1); + + QVector3D v4(v3); + v4 /= v2; + QVERIFY(v4 == v1); + + QCOMPARE(v4.x(), v3.x() / v2.x()); + QCOMPARE(v4.y(), v3.y() / v2.y()); + QCOMPARE(v4.z(), v3.z() / v2.z()); + } + if (v1.x() != 0.0f && v1.y() != 0.0f && v1.z() != 0.0f) { + QVERIFY((v3 / v1) == v2); + + QVector3D v4(v3); + v4 /= v1; + QVERIFY(v4 == v2); + + QCOMPARE(v4.x(), v3.x() / v1.x()); + QCOMPARE(v4.y(), v3.y() / v1.y()); + QCOMPARE(v4.z(), v3.z() / v1.z()); + } +} + +// Test component-wise vector division for 4D vectors. +void tst_QVectorND::divide4_data() +{ + // Use the same test data as the multiply test. + multiply4_data(); +} +void tst_QVectorND::divide4() +{ + QFETCH(float, x1); + QFETCH(float, y1); + QFETCH(float, z1); + QFETCH(float, w1); + QFETCH(float, x2); + QFETCH(float, y2); + QFETCH(float, z2); + QFETCH(float, w2); + QFETCH(float, x3); + QFETCH(float, y3); + QFETCH(float, z3); + QFETCH(float, w3); + + QVector4D v1(x1, y1, z1, w1); + QVector4D v2(x2, y2, z2, w2); + QVector4D v3(x3, y3, z3, w3); + + if (v2.x() != 0.0f && v2.y() != 0.0f && v2.z() != 0.0f && v2.w() != 0.0f) { + QVERIFY((v3 / v2) == v1); + + QVector4D v4(v3); + v4 /= v2; + QVERIFY(v4 == v1); + + QCOMPARE(v4.x(), v3.x() / v2.x()); + QCOMPARE(v4.y(), v3.y() / v2.y()); + QCOMPARE(v4.z(), v3.z() / v2.z()); + QCOMPARE(v4.w(), v3.w() / v2.w()); + } + if (v1.x() != 0.0f && v1.y() != 0.0f && v1.z() != 0.0f && v1.w() != 0.0f) { + QVERIFY((v3 / v1) == v2); + + QVector4D v4(v3); + v4 /= v1; + QVERIFY(v4 == v2); + + QCOMPARE(v4.x(), v3.x() / v1.x()); + QCOMPARE(v4.y(), v3.y() / v1.y()); + QCOMPARE(v4.z(), v3.z() / v1.z()); + QCOMPARE(v4.w(), v3.w() / v1.w()); + } +} + +// Test vector division by a factor for 2D vectors. +void tst_QVectorND::divideFactor2_data() +{ + // Use the same test data as the multiplyFactor test. + multiplyFactor2_data(); +} +void tst_QVectorND::divideFactor2() +{ + QFETCH(float, x1); + QFETCH(float, y1); QFETCH(float, factor); QFETCH(float, x2); QFETCH(float, y2); @@ -1654,12 +1805,12 @@ void tst_QVectorND::divide2() } // Test vector division by a factor for 3D vectors. -void tst_QVectorND::divide3_data() +void tst_QVectorND::divideFactor3_data() { - // Use the same test data as the multiply test. + // Use the same test data as the multiplyFactor test. multiplyFactor3_data(); } -void tst_QVectorND::divide3() +void tst_QVectorND::divideFactor3() { QFETCH(float, x1); QFETCH(float, y1); @@ -1687,12 +1838,12 @@ void tst_QVectorND::divide3() } // Test vector division by a factor for 4D vectors. -void tst_QVectorND::divide4_data() +void tst_QVectorND::divideFactor4_data() { - // Use the same test data as the multiply test. + // Use the same test data as the multiplyFactor test. multiplyFactor4_data(); } -void tst_QVectorND::divide4() +void tst_QVectorND::divideFactor4() { QFETCH(float, x1); QFETCH(float, y1); @@ -2291,6 +2442,158 @@ void tst_QVectorND::dotProduct4() QCOMPARE(QVector4D::dotProduct(v1, v2), d); } +void tst_QVectorND::project_data() +{ + QTest::addColumn<QVector3D>("point"); + QTest::addColumn<QRect>("viewport"); + QTest::addColumn<QMatrix4x4>("projection"); + QTest::addColumn<QMatrix4x4>("view"); + QTest::addColumn<QVector2D>("result"); + + QMatrix4x4 projection; + projection.ortho(-1.0f, 1.0f, -1.0f, 1.0f, 0.1f, 1000.0f); + + QMatrix4x4 view; + // Located at (0, 0, 10), looking at origin, y is up + view.lookAt(QVector3D(0.0f, 0.0f, 10.0f), QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f)); + + QMatrix4x4 nullMatrix(0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f); + + QTest::newRow("center") + << QVector3D(0.0f, 0.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector2D(400.0f, 300.0f); + + QTest::newRow("topLeft") + << QVector3D(-1.0f, 1.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector2D(0.0f, 600.0f); + + QTest::newRow("topRight") + << QVector3D(1.0f, 1.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector2D(800.0f, 600.0f); + + QTest::newRow("bottomLeft") + << QVector3D(-1.0f, -1.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector2D(0.0f, 0.0f); + + QTest::newRow("bottomRight") + << QVector3D(1.0f, -1.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector2D(800.0f, 0.0f); + + QTest::newRow("nullMatrix") + << QVector3D(0.0f, 0.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << nullMatrix + << nullMatrix + << QVector2D(400.0f, 300.0f); +} + +void tst_QVectorND::project() +{ + QFETCH(QVector3D, point); + QFETCH(QRect, viewport); + QFETCH(QMatrix4x4, projection); + QFETCH(QMatrix4x4, view); + QFETCH(QVector2D, result); + + QVector3D project = point.project(view, projection, viewport); + + QCOMPARE(project.toVector2D(), result); +} + +void tst_QVectorND::unproject_data() +{ + QTest::addColumn<QVector3D>("point"); + QTest::addColumn<QRect>("viewport"); + QTest::addColumn<QMatrix4x4>("projection"); + QTest::addColumn<QMatrix4x4>("view"); + QTest::addColumn<QVector3D>("result"); + + QMatrix4x4 projection; + projection.ortho(-1.0f, 1.0f, -1.0f, 1.0f, 0.1f, 1000.0f); + + QMatrix4x4 view; + // Located at (0, 0, 10), looking at origin, y is up + view.lookAt(QVector3D(0.0f, 0.0f, 10.0f), QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f)); + + QMatrix4x4 nullMatrix(0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f); + + QTest::newRow("center") + << QVector3D(400.0f, 300.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector3D(0.0f, 0.0f, 9.9f); + + QTest::newRow("topLeft") + << QVector3D(0.0f, 600.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector3D(-1.0f, 1.0f, 9.9f); + + QTest::newRow("topRight") + << QVector3D(800.0f, 600.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector3D(1.0f, 1.0f, 9.9f); + + QTest::newRow("bottomLeft") + << QVector3D(0.0f, 0.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector3D(-1.0, -1.0f, 9.9f); + + QTest::newRow("bottomRight") + << QVector3D(800.0f, 0.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << projection + << view + << QVector3D(1.0f, -1.0f, 9.9f); + + QTest::newRow("nullMatrix") + << QVector3D(400.0f, 300.0f, 0.0f) + << QRect(0.0f, 0.0f, 800.0f, 600.0f) + << nullMatrix + << nullMatrix + << QVector3D(0.0f, 0.0f, -1.0f); + +} + +void tst_QVectorND::unproject() +{ + QFETCH(QVector3D, point); + QFETCH(QRect, viewport); + QFETCH(QMatrix4x4, projection); + QFETCH(QMatrix4x4, view); + QFETCH(QVector3D, result); + + QVector3D unproject = point.unproject(view, projection, viewport); + QVERIFY(qFuzzyCompare(unproject, result)); +} + class tst_QVectorNDProperties : public QObject { Q_OBJECT |