summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2012-08-20 20:55:40 +0100
committerQt by Nokia <qt-info@nokia.com>2012-09-07 13:27:38 +0200
commit51d40d7e9bdfc63c5109aef5b732aa2ba10f985a (patch)
treeffa750956ab2e96e0cd8f02bafa820042aa9f78a /tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp
parent56414e2498ae19d305b391678afe3a67a9069832 (diff)
Make gui/math3d classes use float rather than qreal
This corrects the mismatch between using floats for internal storage and qreal in the API of QVector*D which leads to lots of implicit casts between double and float. This change also stops users from being surprised by the loss of precision when using these classes on desktop platforms and removes the need for the private constructors taking a dummy int as the final argument. The QMatrix4x4 and QQuaternion classes have been changed to use float for their internal storage since these are meant to be used in conjunction with the QVector*D classes. This is to prevent unexpected loss of precision and to improve performance. The on-disk format has also been changed from double to float thereby reducing the storage required when streaming vectors and matrices. This is potentially a large saving when working with complex 3D meshes etc. This also has a significant performance improvement when passing matrices to QOpenGLShaderProgram (and QGLShaderProgram) as we no longer have to iterate and convert the data to floats. This is an operation that could easily be needed many times per frame. This change also opens the door for further optimisations of these classes to be implemented by using SIMD intrinsics. This needs to be applied in conjunction with https://codereview.qt-project.org/#change,33548 Task-number: QTBUG-21035 Task-number: QTBUG-20661 Change-Id: I9321b06040ffb93ae1cbd72fd2013267ac901b2e Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp')
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp83
1 files changed, 39 insertions, 44 deletions
diff --git a/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp b/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp
index 5820598034..b0e3d6fd40 100644
--- a/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp
@@ -156,31 +156,39 @@ void tst_QGraphicsTransform::scale()
QCOMPARE(t3.map(QPointF(4, 5)), QPointF(31 / t3.m33(), 8 / t3.m33()));
}
-// QMatrix4x4 uses float internally, whereas QTransform uses qreal.
-// This can lead to issues with qFuzzyCompare() where it uses double
-// precision to compare values that have no more than float precision
-// after conversion from QMatrix4x4 to QTransform. The following
-// definitions correct for the difference.
-static inline bool fuzzyCompare(qreal p1, qreal p2)
+// fuzzyCompareNonZero is a very slightly looser version of qFuzzyCompare
+// for use with values that are not very close to zero
+Q_DECL_CONSTEXPR static inline bool fuzzyCompareNonZero(float p1, float p2)
{
- // increase delta on small machines using float instead of double
- if (sizeof(qreal) == sizeof(float))
- return (qAbs(p1 - p2) <= 0.00003f * qMin(qAbs(p1), qAbs(p2)));
+ return (qAbs(p1 - p2) <= 0.00003f * qMin(qAbs(p1), qAbs(p2)));
+}
+
+// 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 fuzzyCompare(float p1, float p2)
+{
+ if (qFuzzyIsNull(p1))
+ return qFuzzyIsNull(p2);
+ else if (qFuzzyIsNull(p2))
+ return false;
else
- return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
+ return fuzzyCompareNonZero(p1, p2);
}
-static bool fuzzyCompare(const QTransform& t1, const QTransform& t2)
+// This compares two QTransforms by casting the elements to float. This is
+// necessary here because in this test one of the transforms is created from
+// a QMatrix4x4 which uses float storage.
+static bool fuzzyCompareAsFloat(const QTransform& t1, const QTransform& t2)
{
- return fuzzyCompare(t1.m11(), t2.m11()) &&
- fuzzyCompare(t1.m12(), t2.m12()) &&
- fuzzyCompare(t1.m13(), t2.m13()) &&
- fuzzyCompare(t1.m21(), t2.m21()) &&
- fuzzyCompare(t1.m22(), t2.m22()) &&
- fuzzyCompare(t1.m23(), t2.m23()) &&
- fuzzyCompare(t1.m31(), t2.m31()) &&
- fuzzyCompare(t1.m32(), t2.m32()) &&
- fuzzyCompare(t1.m33(), t2.m33());
+ return fuzzyCompare(float(t1.m11()), float(t2.m11())) &&
+ fuzzyCompare(float(t1.m12()), float(t2.m12())) &&
+ fuzzyCompare(float(t1.m13()), float(t2.m13())) &&
+ fuzzyCompare(float(t1.m21()), float(t2.m21())) &&
+ fuzzyCompare(float(t1.m22()), float(t2.m22())) &&
+ fuzzyCompare(float(t1.m23()), float(t2.m23())) &&
+ fuzzyCompare(float(t1.m31()), float(t2.m31())) &&
+ fuzzyCompare(float(t1.m32()), float(t2.m32())) &&
+ fuzzyCompare(float(t1.m33()), float(t2.m33()));
}
static inline bool fuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
@@ -221,7 +229,7 @@ void tst_QGraphicsTransform::rotation()
QTransform res;
res.rotate(40);
- QVERIFY(fuzzyCompare(transform2D(rotation), res));
+ QVERIFY(fuzzyCompareAsFloat(transform2D(rotation), res));
rotation.setOrigin(QVector3D(10, 10, 0));
rotation.setAngle(90);
@@ -271,20 +279,14 @@ void tst_QGraphicsTransform::rotation3d()
else
expected.rotate(angle, axis);
- QVERIFY(fuzzyCompare(transform2D(rotation), expected));
+ QVERIFY(fuzzyCompareAsFloat(transform2D(rotation), expected));
// Check that "rotation" produces the 4x4 form of the 3x3 matrix.
// i.e. third row and column are 0 0 1 0.
t.setToIdentity();
rotation.applyTo(&t);
QMatrix4x4 r(expected);
- if (sizeof(qreal) == sizeof(float) && angle == 268) {
- // This test fails, on only this angle, when qreal == float
- // because the deg2rad value in QTransform is not accurate
- // enough to match what QMatrix4x4 is doing.
- } else {
- QVERIFY(fuzzyCompare(t, r));
- }
+ QVERIFY(fuzzyCompare(t, r));
//now let's check that a null vector will not change the transform
rotation.setAxis(QVector3D(0, 0, 0));
@@ -358,21 +360,8 @@ void tst_QGraphicsTransform::rotation3dArbitraryAxis()
exp.rotate(angle, axis);
QTransform expected = exp.toTransform(1024.0f);
-#if defined(MAY_HIT_QTBUG_20661)
- // These failures possibly relate to the float vs qreal issue mentioned
- // in the comment above fuzzyCompare().
- if (sizeof(qreal) == sizeof(double)) {
- QEXPECT_FAIL("rotation of 120 on (1, 1, 1)", "QTBUG-20661", Abort);
- QEXPECT_FAIL("rotation of 240 on (1, 1, 1)", "QTBUG-20661", Abort);
- QEXPECT_FAIL("rotation of 120 on (0.01, 0.01, 0.01)", "QTBUG-20661", Abort);
- QEXPECT_FAIL("rotation of 240 on (0.01, 0.01, 0.01)", "QTBUG-20661", Abort);
- QEXPECT_FAIL("rotation of 120 on (0.0001, 0.0001, 0.0001)", "QTBUG-20661", Abort);
- QEXPECT_FAIL("rotation of 240 on (0.0001, 0.0001, 0.0001)", "QTBUG-20661", Abort);
- }
-#endif
-
QTransform actual = transform2D(rotation);
- QVERIFY2(fuzzyCompare(actual, expected), qPrintable(
+ QVERIFY2(fuzzyCompareAsFloat(actual, expected), qPrintable(
QString("\nactual: %1\n"
"expected: %2")
.arg(toString(actual))
@@ -384,7 +373,13 @@ void tst_QGraphicsTransform::rotation3dArbitraryAxis()
t.setToIdentity();
rotation.applyTo(&t);
QMatrix4x4 r(expected);
- QVERIFY(qFuzzyCompare(t, r));
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ float a = t(row, col);
+ float b = r(row, col);
+ QVERIFY2(fuzzyCompare(a, b), QString("%1 is not equal to %2").arg(a).arg(b).toLatin1());
+ }
+ }
}
QString tst_QGraphicsTransform::toString(QTransform const& t)