summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp141
-rw-r--r--tests/benchmarks/qmatrix4x4/tst_qmatrix4x4.cpp411
2 files changed, 520 insertions, 32 deletions
diff --git a/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp b/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp
index bfd346b..d3d511a 100644
--- a/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp
+++ b/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp
@@ -84,60 +84,131 @@ void tst_QGraphicsTransform::cleanup()
{
}
+static QTransform transform2D(const QGraphicsTransform& t)
+{
+ QMatrix4x4 m;
+ t.applyTo(&m);
+ return m.toTransform();
+}
void tst_QGraphicsTransform::scale()
{
QGraphicsScale scale;
- scale.setOrigin(QPointF(10, 10));
- QTransform t;
+ // check initial conditions
+ QCOMPARE(scale.xScale(), qreal(1));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(0, 0, 0));
+
+ scale.setOrigin(QVector3D(10, 10, 0));
+
+ QCOMPARE(scale.xScale(), qreal(1));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(10, 10, 0));
+
+ QMatrix4x4 t;
scale.applyTo(&t);
- QCOMPARE(t, QTransform());
- QCOMPARE(scale.transform(), QTransform());
+ QCOMPARE(t, QMatrix4x4());
+ QCOMPARE(transform2D(scale), QTransform());
scale.setXScale(10);
- scale.setOrigin(QPointF(0, 0));
+ scale.setOrigin(QVector3D(0, 0, 0));
+
+ QCOMPARE(scale.xScale(), qreal(10));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(0, 0, 0));
QTransform res;
res.scale(10, 1);
- QCOMPARE(scale.transform(), res);
- QCOMPARE(scale.transform().map(QPointF(10, 10)), QPointF(100, 10));
+ QCOMPARE(transform2D(scale), res);
+ QCOMPARE(transform2D(scale).map(QPointF(10, 10)), QPointF(100, 10));
+
+ scale.setOrigin(QVector3D(10, 10, 0));
+ QCOMPARE(transform2D(scale).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(transform2D(scale).map(QPointF(11, 10)), QPointF(20, 10));
+
+ scale.setYScale(2);
+ scale.setZScale(4.5);
+ scale.setOrigin(QVector3D(1, 2, 3));
+
+ QCOMPARE(scale.xScale(), qreal(10));
+ QCOMPARE(scale.yScale(), qreal(2));
+ QCOMPARE(scale.zScale(), qreal(4.5));
+ QCOMPARE(scale.origin(), QVector3D(1, 2, 3));
+
+ QMatrix4x4 t2;
+ scale.applyTo(&t2);
- scale.setOrigin(QPointF(10, 10));
- QCOMPARE(scale.transform().map(QPointF(10, 10)), QPointF(10, 10));
- QCOMPARE(scale.transform().map(QPointF(11, 10)), QPointF(20, 10));
+ QCOMPARE(t2.map(QVector3D(4, 5, 6)), QVector3D(31, 8, 16.5));
+
+ // Because the origin has a non-zero z, mapping (4, 5) in 2D
+ // will introduce a projective component into the result.
+ QTransform t3 = t2.toTransform();
+ 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)
+{
+ return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
+}
+static bool fuzzyCompare(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());
}
void tst_QGraphicsTransform::rotation()
{
QGraphicsRotation rotation;
- QCOMPARE(rotation.axis().x(), (qreal)0);
- QCOMPARE(rotation.axis().y(), (qreal)0);
- QCOMPARE(rotation.axis().z(), (qreal)1);
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(0, 0, 0));
QCOMPARE(rotation.angle(), (qreal)0);
- rotation.setOrigin(QPointF(10, 10));
+ rotation.setOrigin(QVector3D(10, 10, 0));
+
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(10, 10, 0));
+ QCOMPARE(rotation.angle(), (qreal)0);
- QTransform t;
+ QMatrix4x4 t;
rotation.applyTo(&t);
- QCOMPARE(t, QTransform());
- QCOMPARE(rotation.transform(), QTransform());
+ QCOMPARE(t, QMatrix4x4());
+ QCOMPARE(transform2D(rotation), QTransform());
rotation.setAngle(40);
- rotation.setOrigin(QPointF(0, 0));
+ rotation.setOrigin(QVector3D(0, 0, 0));
+
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(0, 0, 0));
+ QCOMPARE(rotation.angle(), (qreal)40);
QTransform res;
res.rotate(40);
- QCOMPARE(rotation.transform(), res);
+ QVERIFY(fuzzyCompare(transform2D(rotation), res));
- rotation.setOrigin(QPointF(10, 10));
+ rotation.setOrigin(QVector3D(10, 10, 0));
rotation.setAngle(90);
- QCOMPARE(rotation.transform().map(QPointF(10, 10)), QPointF(10, 10));
- QCOMPARE(rotation.transform().map(QPointF(20, 10)), QPointF(10, 20));
+ QCOMPARE(transform2D(rotation).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(transform2D(rotation).map(QPointF(20, 10)), QPointF(10, 20));
}
Q_DECLARE_METATYPE(Qt::Axis);
@@ -161,38 +232,44 @@ void tst_QGraphicsTransform::rotation3d()
QGraphicsRotation rotation;
rotation.setAxis(axis);
- QTransform t;
+ QMatrix4x4 t;
rotation.applyTo(&t);
QVERIFY(t.isIdentity());
- QVERIFY(rotation.transform().isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
rotation.setAngle(angle);
+ // QGraphicsRotation uses a correct mathematical rotation in 3D.
+ // QTransform's Qt::YAxis rotation is inverted from the mathematical
+ // version of rotation. We correct for that here.
QTransform expected;
- expected.rotate(angle, axis);
+ if (axis == Qt::YAxis && angle != 180.)
+ expected.rotate(-angle, axis);
+ else
+ expected.rotate(angle, axis);
- QVERIFY(qFuzzyCompare(rotation.transform(), expected));
+ QVERIFY(fuzzyCompare(transform2D(rotation), expected));
//now let's check that a null vector will not change the transform
rotation.setAxis(QVector3D(0, 0, 0));
- rotation.setOrigin(QPointF(10, 10));
+ rotation.setOrigin(QVector3D(10, 10, 0));
- t.reset();
+ t.setIdentity();
rotation.applyTo(&t);
QVERIFY(t.isIdentity());
- QVERIFY(rotation.transform().isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
rotation.setAngle(angle);
QVERIFY(t.isIdentity());
- QVERIFY(rotation.transform().isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
- rotation.setOrigin(QPointF(0, 0));
+ rotation.setOrigin(QVector3D(0, 0, 0));
QVERIFY(t.isIdentity());
- QVERIFY(rotation.transform().isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
}
diff --git a/tests/benchmarks/qmatrix4x4/tst_qmatrix4x4.cpp b/tests/benchmarks/qmatrix4x4/tst_qmatrix4x4.cpp
index aeefd20..f80a142 100644
--- a/tests/benchmarks/qmatrix4x4/tst_qmatrix4x4.cpp
+++ b/tests/benchmarks/qmatrix4x4/tst_qmatrix4x4.cpp
@@ -67,6 +67,33 @@ private slots:
void mapVectorDirect_data();
void mapVectorDirect();
+
+ void compareTranslate_data();
+ void compareTranslate();
+
+ void compareTranslateAfterScale_data();
+ void compareTranslateAfterScale();
+
+ void compareTranslateAfterRotate_data();
+ void compareTranslateAfterRotate();
+
+ void compareScale_data();
+ void compareScale();
+
+ void compareScaleAfterTranslate_data();
+ void compareScaleAfterTranslate();
+
+ void compareScaleAfterRotate_data();
+ void compareScaleAfterRotate();
+
+ void compareRotate_data();
+ void compareRotate();
+
+ void compareRotateAfterTranslate_data();
+ void compareRotateAfterTranslate();
+
+ void compareRotateAfterScale_data();
+ void compareRotateAfterScale();
};
static qreal const generalValues[16] =
@@ -256,6 +283,390 @@ void tst_QMatrix4x4::mapVectorDirect()
}
}
+// Compare the performance of QTransform::translate() to
+// QMatrix4x4::translate().
+void tst_QMatrix4x4::compareTranslate_data()
+{
+ QTest::addColumn<bool>("useQTransform");
+ QTest::addColumn<QVector3D>("translation");
+
+ QTest::newRow("QTransform::translate(0, 0, 0)")
+ << true << QVector3D(0, 0, 0);
+ QTest::newRow("QMatrix4x4::translate(0, 0, 0)")
+ << false << QVector3D(0, 0, 0);
+
+ QTest::newRow("QTransform::translate(1, 2, 0)")
+ << true << QVector3D(1, 2, 0);
+ QTest::newRow("QMatrix4x4::translate(1, 2, 0)")
+ << false << QVector3D(1, 2, 0);
+
+ QTest::newRow("QTransform::translate(1, 2, 4)")
+ << true << QVector3D(1, 2, 4);
+ QTest::newRow("QMatrix4x4::translate(1, 2, 4)")
+ << false << QVector3D(1, 2, 4);
+}
+void tst_QMatrix4x4::compareTranslate()
+{
+ QFETCH(bool, useQTransform);
+ QFETCH(QVector3D, translation);
+
+ qreal x = translation.x();
+ qreal y = translation.y();
+ qreal z = translation.z();
+
+ if (useQTransform) {
+ QTransform t;
+ QBENCHMARK {
+ t.translate(x, y);
+ }
+ } else if (z == 0.0f) {
+ QMatrix4x4 m;
+ QBENCHMARK {
+ m.translate(x, y);
+ }
+ } else {
+ QMatrix4x4 m;
+ QBENCHMARK {
+ m.translate(x, y, z);
+ }
+ }
+}
+
+// Compare the performance of QTransform::translate() to
+// QMatrix4x4::translate() after priming the matrix with a scale().
+void tst_QMatrix4x4::compareTranslateAfterScale_data()
+{
+ compareTranslate_data();
+}
+void tst_QMatrix4x4::compareTranslateAfterScale()
+{
+ QFETCH(bool, useQTransform);
+ QFETCH(QVector3D, translation);
+
+ qreal x = translation.x();
+ qreal y = translation.y();
+ qreal z = translation.z();
+
+ if (useQTransform) {
+ QTransform t;
+ t.scale(3, 4);
+ QBENCHMARK {
+ t.translate(x, y);
+ }
+ } else if (z == 0.0f) {
+ QMatrix4x4 m;
+ m.scale(3, 4);
+ QBENCHMARK {
+ m.translate(x, y);
+ }
+ } else {
+ QMatrix4x4 m;
+ m.scale(3, 4, 5);
+ QBENCHMARK {
+ m.translate(x, y, z);
+ }
+ }
+}
+
+// Compare the performance of QTransform::translate() to
+// QMatrix4x4::translate() after priming the matrix with a rotate().
+void tst_QMatrix4x4::compareTranslateAfterRotate_data()
+{
+ compareTranslate_data();
+}
+void tst_QMatrix4x4::compareTranslateAfterRotate()
+{
+ QFETCH(bool, useQTransform);
+ QFETCH(QVector3D, translation);
+
+ qreal x = translation.x();
+ qreal y = translation.y();
+ qreal z = translation.z();
+
+ if (useQTransform) {
+ QTransform t;
+ t.rotate(45.0f);
+ QBENCHMARK {
+ t.translate(x, y);
+ }
+ } else if (z == 0.0f) {
+ QMatrix4x4 m;
+ m.rotate(45.0f, 0, 0, 1);
+ QBENCHMARK {
+ m.translate(x, y);
+ }
+ } else {
+ QMatrix4x4 m;
+ m.rotate(45.0f, 0, 0, 1);
+ QBENCHMARK {
+ m.translate(x, y, z);
+ }
+ }
+}
+
+// Compare the performance of QTransform::scale() to
+// QMatrix4x4::scale().
+void tst_QMatrix4x4::compareScale_data()
+{
+ QTest::addColumn<bool>("useQTransform");
+ QTest::addColumn<QVector3D>("scale");
+
+ QTest::newRow("QTransform::scale(1, 1, 1)")
+ << true << QVector3D(1, 1, 1);
+ QTest::newRow("QMatrix4x4::scale(1, 1, 1)")
+ << false << QVector3D(1, 1, 1);
+
+ QTest::newRow("QTransform::scale(3, 6, 1)")
+ << true << QVector3D(3, 6, 1);
+ QTest::newRow("QMatrix4x4::scale(3, 6, 1)")
+ << false << QVector3D(3, 6, 1);
+
+ QTest::newRow("QTransform::scale(3, 6, 4)")
+ << true << QVector3D(3, 6, 4);
+ QTest::newRow("QMatrix4x4::scale(3, 6, 4)")
+ << false << QVector3D(3, 6, 4);
+}
+void tst_QMatrix4x4::compareScale()
+{
+ QFETCH(bool, useQTransform);
+ QFETCH(QVector3D, scale);
+
+ qreal x = scale.x();
+ qreal y = scale.y();
+ qreal z = scale.z();
+
+ if (useQTransform) {
+ QTransform t;
+ QBENCHMARK {
+ t.scale(x, y);
+ }
+ } else if (z == 1.0f) {
+ QMatrix4x4 m;
+ QBENCHMARK {
+ m.scale(x, y);
+ }
+ } else {
+ QMatrix4x4 m;
+ QBENCHMARK {
+ m.scale(x, y, z);
+ }
+ }
+}
+
+// Compare the performance of QTransform::scale() to
+// QMatrix4x4::scale() after priming the matrix with a translate().
+void tst_QMatrix4x4::compareScaleAfterTranslate_data()
+{
+ compareScale_data();
+}
+void tst_QMatrix4x4::compareScaleAfterTranslate()
+{
+ QFETCH(bool, useQTransform);
+ QFETCH(QVector3D, scale);
+
+ qreal x = scale.x();
+ qreal y = scale.y();
+ qreal z = scale.z();
+
+ if (useQTransform) {
+ QTransform t;
+ t.translate(20, 34);
+ QBENCHMARK {
+ t.scale(x, y);
+ }
+ } else if (z == 1.0f) {
+ QMatrix4x4 m;
+ m.translate(20, 34);
+ QBENCHMARK {
+ m.scale(x, y);
+ }
+ } else {
+ QMatrix4x4 m;
+ m.translate(20, 34, 42);
+ QBENCHMARK {
+ m.scale(x, y, z);
+ }
+ }
+}
+
+// Compare the performance of QTransform::scale() to
+// QMatrix4x4::scale() after priming the matrix with a rotate().
+void tst_QMatrix4x4::compareScaleAfterRotate_data()
+{
+ compareScale_data();
+}
+void tst_QMatrix4x4::compareScaleAfterRotate()
+{
+ QFETCH(bool, useQTransform);
+ QFETCH(QVector3D, scale);
+
+ qreal x = scale.x();
+ qreal y = scale.y();
+ qreal z = scale.z();
+
+ if (useQTransform) {
+ QTransform t;
+ t.rotate(45.0f);
+ QBENCHMARK {
+ t.scale(x, y);
+ }
+ } else if (z == 1.0f) {
+ QMatrix4x4 m;
+ m.rotate(45.0f, 0, 0, 1);
+ QBENCHMARK {
+ m.scale(x, y);
+ }
+ } else {
+ QMatrix4x4 m;
+ m.rotate(45.0f, 0, 0, 1);
+ QBENCHMARK {
+ m.scale(x, y, z);
+ }
+ }
+}
+
+// Compare the performance of QTransform::rotate() to
+// QMatrix4x4::rotate().
+void tst_QMatrix4x4::compareRotate_data()
+{
+ QTest::addColumn<bool>("useQTransform");
+ QTest::addColumn<qreal>("angle");
+ QTest::addColumn<QVector3D>("rotation");
+ QTest::addColumn<int>("axis");
+
+ QTest::newRow("QTransform::rotate(0, ZAxis)")
+ << true << qreal(0.0f) << QVector3D(0, 0, 1) << int(Qt::ZAxis);
+ QTest::newRow("QMatrix4x4::rotate(0, ZAxis)")
+ << false << qreal(0.0f) << QVector3D(0, 0, 1) << int(Qt::ZAxis);
+
+ QTest::newRow("QTransform::rotate(45, ZAxis)")
+ << true << qreal(45.0f) << QVector3D(0, 0, 1) << int(Qt::ZAxis);
+ QTest::newRow("QMatrix4x4::rotate(45, ZAxis)")
+ << false << qreal(45.0f) << QVector3D(0, 0, 1) << int(Qt::ZAxis);
+
+ QTest::newRow("QTransform::rotate(90, ZAxis)")
+ << true << qreal(90.0f) << QVector3D(0, 0, 1) << int(Qt::ZAxis);
+ QTest::newRow("QMatrix4x4::rotate(90, ZAxis)")
+ << false << qreal(90.0f) << QVector3D(0, 0, 1) << int(Qt::ZAxis);
+
+ QTest::newRow("QTransform::rotate(0, YAxis)")
+ << true << qreal(0.0f) << QVector3D(0, 1, 0) << int(Qt::YAxis);
+ QTest::newRow("QMatrix4x4::rotate(0, YAxis)")
+ << false << qreal(0.0f) << QVector3D(0, 1, 0) << int(Qt::YAxis);
+
+ QTest::newRow("QTransform::rotate(45, YAxis)")
+ << true << qreal(45.0f) << QVector3D(0, 1, 0) << int(Qt::YAxis);
+ QTest::newRow("QMatrix4x4::rotate(45, YAxis)")
+ << false << qreal(45.0f) << QVector3D(0, 1, 0) << int(Qt::YAxis);
+
+ QTest::newRow("QTransform::rotate(90, YAxis)")
+ << true << qreal(90.0f) << QVector3D(0, 1, 0) << int(Qt::YAxis);
+ QTest::newRow("QMatrix4x4::rotate(90, YAxis)")
+ << false << qreal(90.0f) << QVector3D(0, 1, 0) << int(Qt::YAxis);
+
+ QTest::newRow("QTransform::rotate(0, XAxis)")
+ << true << qreal(0.0f) << QVector3D(0, 1, 0) << int(Qt::XAxis);
+ QTest::newRow("QMatrix4x4::rotate(0, XAxis)")
+ << false << qreal(0.0f) << QVector3D(0, 1, 0) << int(Qt::XAxis);
+
+ QTest::newRow("QTransform::rotate(45, XAxis)")
+ << true << qreal(45.0f) << QVector3D(1, 0, 0) << int(Qt::XAxis);
+ QTest::newRow("QMatrix4x4::rotate(45, XAxis)")
+ << false << qreal(45.0f) << QVector3D(1, 0, 0) << int(Qt::XAxis);
+
+ QTest::newRow("QTransform::rotate(90, XAxis)")
+ << true << qreal(90.0f) << QVector3D(1, 0, 0) << int(Qt::XAxis);
+ QTest::newRow("QMatrix4x4::rotate(90, XAxis)")
+ << false << qreal(90.0f) << QVector3D(1, 0, 0) << int(Qt::XAxis);
+}
+void tst_QMatrix4x4::compareRotate()
+{
+ QFETCH(bool, useQTransform);
+ QFETCH(qreal, angle);
+ QFETCH(QVector3D, rotation);
+ QFETCH(int, axis);
+
+ qreal x = rotation.x();
+ qreal y = rotation.y();
+ qreal z = rotation.z();
+
+ if (useQTransform) {
+ QTransform t;
+ QBENCHMARK {
+ t.rotate(angle, Qt::Axis(axis));
+ }
+ } else {
+ QMatrix4x4 m;
+ QBENCHMARK {
+ m.rotate(angle, x, y, z);
+ }
+ }
+}
+
+// Compare the performance of QTransform::rotate() to
+// QMatrix4x4::rotate() after priming the matrix with a translate().
+void tst_QMatrix4x4::compareRotateAfterTranslate_data()
+{
+ compareRotate_data();
+}
+void tst_QMatrix4x4::compareRotateAfterTranslate()
+{
+ QFETCH(bool, useQTransform);
+ QFETCH(qreal, angle);
+ QFETCH(QVector3D, rotation);
+ QFETCH(int, axis);
+
+ qreal x = rotation.x();
+ qreal y = rotation.y();
+ qreal z = rotation.z();
+
+ if (useQTransform) {
+ QTransform t;
+ t.translate(3, 4);
+ QBENCHMARK {
+ t.rotate(angle, Qt::Axis(axis));
+ }
+ } else {
+ QMatrix4x4 m;
+ m.translate(3, 4, 5);
+ QBENCHMARK {
+ m.rotate(angle, x, y, z);
+ }
+ }
+}
+
+// Compare the performance of QTransform::rotate() to
+// QMatrix4x4::rotate() after priming the matrix with a scale().
+void tst_QMatrix4x4::compareRotateAfterScale_data()
+{
+ compareRotate_data();
+}
+void tst_QMatrix4x4::compareRotateAfterScale()
+{
+ QFETCH(bool, useQTransform);
+ QFETCH(qreal, angle);
+ QFETCH(QVector3D, rotation);
+ QFETCH(int, axis);
+
+ qreal x = rotation.x();
+ qreal y = rotation.y();
+ qreal z = rotation.z();
+
+ if (useQTransform) {
+ QTransform t;
+ t.scale(3, 4);
+ QBENCHMARK {
+ t.rotate(angle, Qt::Axis(axis));
+ }
+ } else {
+ QMatrix4x4 m;
+ m.scale(3, 4, 5);
+ QBENCHMARK {
+ m.rotate(angle, x, y, z);
+ }
+ }
+}
+
QTEST_MAIN(tst_QMatrix4x4)
#include "tst_qmatrix4x4.moc"