// Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include #include #include #include #include #include #include "testarbiter.h" using namespace Qt3DCore; class FakeTransform : public Qt3DCore::QTransform { public: }; class tst_QTransform : public QObject { Q_OBJECT private Q_SLOTS: void defaultConstruction() { // GIVEN Qt3DCore::QTransform transform; // THEN QCOMPARE(transform.isShareable(), false); QCOMPARE(transform.matrix(), QMatrix4x4()); QCOMPARE(transform.worldMatrix(), QMatrix4x4()); QCOMPARE(transform.scale(), 1.0f); QCOMPARE(transform.scale3D(), QVector3D(1.0f, 1.0f, 1.0f)); QCOMPARE(transform.rotation(), QQuaternion()); QCOMPARE(transform.rotationX(), 0.0f); QCOMPARE(transform.rotationY(), 0.0f); QCOMPARE(transform.rotationZ(), 0.0f); QCOMPARE(transform.translation(), QVector3D(0.0f, 0.0f, 0.0f)); } void checkPropertyUpdates() { // GIVEN TestArbiter arbiter; QScopedPointer transform(new Qt3DCore::QTransform()); arbiter.setArbiterOnNode(transform.data()); // WHEN transform->setTranslation(QVector3D(454.0f, 427.0f, 383.0f)); // THEN QCOMPARE(arbiter.dirtyNodes().size(), 1); QCOMPARE(arbiter.dirtyNodes().front(), transform.data()); arbiter.clear(); // WHEN QQuaternion q = Qt3DCore::QTransform::fromAxisAndAngle(QVector3D(0.0f, 1.0f, 0.0f), 90.0f); transform->setRotation(q); // THEN QCOMPARE(arbiter.dirtyNodes().size(), 1); QCOMPARE(arbiter.dirtyNodes().front(), transform.data()); arbiter.clear(); // WHEN transform->setScale3D(QVector3D(883.0f, 1200.0f, 1340.0f)); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.dirtyNodes().size(), 1); QCOMPARE(arbiter.dirtyNodes().front(), transform.data()); arbiter.clear(); // WHEN // Force the transform to update its matrix (void)transform->matrix(); transform->setMatrix(QMatrix4x4()); // THEN QCOMPARE(arbiter.dirtyNodes().size(), 1); QCOMPARE(arbiter.dirtyNodes().front(), transform.data()); arbiter.clear(); // WHEN transform->setRotationX(20.0f); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.dirtyNodes().size(), 1); QCOMPARE(arbiter.dirtyNodes().front(), transform.data()); arbiter.clear(); } void checkSignalEmittion() { // GIVEN QScopedPointer transform(new Qt3DCore::QTransform()); int rotationXChangedCount = 0; int rotationYChangedCount = 0; int rotationZChangedCount = 0; int rotationChangedCount = 0; int matrixChangedCount = 0; int scaleChangedCount = 0; int scale3DChangedCount = 0; int translationChangedCount = 0; QObject::connect(transform.data(), &Qt3DCore::QTransform::rotationChanged, [&] { ++rotationChangedCount; }); QObject::connect(transform.data(), &Qt3DCore::QTransform::rotationXChanged, [&] { ++rotationXChangedCount; }); QObject::connect(transform.data(), &Qt3DCore::QTransform::rotationYChanged, [&] { ++rotationYChangedCount; }); QObject::connect(transform.data(), &Qt3DCore::QTransform::rotationZChanged, [&] { ++rotationZChangedCount; }); QObject::connect(transform.data(), &Qt3DCore::QTransform::matrixChanged, [&] { ++matrixChangedCount; }); QObject::connect(transform.data(), &Qt3DCore::QTransform::scale3DChanged, [&] { ++scale3DChangedCount; }); QObject::connect(transform.data(), &Qt3DCore::QTransform::scaleChanged, [&] { ++scaleChangedCount; }); QObject::connect(transform.data(), &Qt3DCore::QTransform::translationChanged, [&] { ++translationChangedCount; }); // WHEN transform->setRotationX(180.0f); // THEN QCOMPARE(rotationXChangedCount, 1); QCOMPARE(rotationYChangedCount, 0); QCOMPARE(rotationZChangedCount, 0); QCOMPARE(rotationChangedCount, 1); QCOMPARE(matrixChangedCount, 1); QCOMPARE(scaleChangedCount, 0); QCOMPARE(scale3DChangedCount, 0); QCOMPARE(translationChangedCount, 0); // WHEN transform->setRotationY(180.0f); // THEN QCOMPARE(rotationXChangedCount, 1); QCOMPARE(rotationYChangedCount, 1); QCOMPARE(rotationZChangedCount, 0); QCOMPARE(rotationChangedCount, 2); QCOMPARE(matrixChangedCount, 2); QCOMPARE(scaleChangedCount, 0); QCOMPARE(scale3DChangedCount, 0); QCOMPARE(translationChangedCount, 0); // WHEN transform->setRotationZ(180.0f); // THEN QCOMPARE(rotationXChangedCount, 1); QCOMPARE(rotationYChangedCount, 1); QCOMPARE(rotationZChangedCount, 1); QCOMPARE(rotationChangedCount, 3); QCOMPARE(matrixChangedCount, 3); QCOMPARE(scaleChangedCount, 0); QCOMPARE(scale3DChangedCount, 0); QCOMPARE(translationChangedCount, 0); // WHEN transform->setRotation(Qt3DCore::QTransform::fromEulerAngles(15.0f, 25.0f, 84.0f)); // THEN QCOMPARE(rotationXChangedCount, 2); QCOMPARE(rotationYChangedCount, 2); QCOMPARE(rotationZChangedCount, 2); QCOMPARE(rotationChangedCount, 4); QCOMPARE(matrixChangedCount, 4); QCOMPARE(scaleChangedCount, 0); QCOMPARE(scale3DChangedCount, 0); QCOMPARE(translationChangedCount, 0); // WHEN transform->setMatrix(QMatrix4x4()); // THEN QCOMPARE(rotationXChangedCount, 3); QCOMPARE(rotationYChangedCount, 3); QCOMPARE(rotationZChangedCount, 3); QCOMPARE(rotationChangedCount, 5); QCOMPARE(matrixChangedCount, 5); QCOMPARE(scaleChangedCount, 1); QCOMPARE(scale3DChangedCount, 1); QCOMPARE(translationChangedCount, 1); // WHEN transform->setScale(18.0f); // THEN QCOMPARE(rotationXChangedCount, 3); QCOMPARE(rotationYChangedCount, 3); QCOMPARE(rotationZChangedCount, 3); QCOMPARE(rotationChangedCount, 5); QCOMPARE(matrixChangedCount, 6); QCOMPARE(scaleChangedCount, 2); QCOMPARE(scale3DChangedCount, 2); QCOMPARE(translationChangedCount, 1); // WHEN transform->setScale3D(QVector3D(15.0f, 18.0f, 15.0f)); // THEN QCOMPARE(rotationXChangedCount, 3); QCOMPARE(rotationYChangedCount, 3); QCOMPARE(rotationZChangedCount, 3); QCOMPARE(rotationChangedCount, 5); QCOMPARE(matrixChangedCount, 7); QCOMPARE(scaleChangedCount, 2); QCOMPARE(scale3DChangedCount, 3); QCOMPARE(translationChangedCount, 1); // WHEN transform->setTranslation(QVector3D(350.0f, 383.0f, 454.0f)); // THEN QCOMPARE(rotationXChangedCount, 3); QCOMPARE(rotationYChangedCount, 3); QCOMPARE(rotationZChangedCount, 3); QCOMPARE(rotationChangedCount, 5); QCOMPARE(matrixChangedCount, 8); QCOMPARE(scaleChangedCount, 2); QCOMPARE(scale3DChangedCount, 3); QCOMPARE(translationChangedCount, 2); } void checkCompositionDecomposition() { // GIVEN Qt3DCore::QTransform t; Qt3DCore::QTransform t2; QMatrix4x4 m = Qt3DCore::QTransform::rotateAround(QVector3D(0.1877f, 0.6868f, 0.3884f), 45.0f, QVector3D(0.0f, 0.0f, 1.0f)); // WHEN t.setMatrix(m); t2.setScale3D(t.scale3D()); t2.setRotation(t.rotation()); t2.setTranslation(t.translation()); // THEN QCOMPARE(t.scale3D(), t2.scale3D()); QCOMPARE(t.rotation(), t2.rotation()); QCOMPARE(t.translation(), t2.translation()); // Note: t.matrix() != t2.matrix() since different matrices // can result in the same scale, rotation, translation } void checkUpdateWorldTransform() { // GIVEN TestArbiter arbiter; FakeTransform t; arbiter.setArbiterOnNode(&t); // WHEN QSignalSpy spy(&t, SIGNAL(worldMatrixChanged(QMatrix4x4))); // THEN QVERIFY(spy.isValid()); // WHEN QTransformPrivate *dT = static_cast(QNodePrivate::get(&t)); const QMatrix4x4 newValue(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f); dT->setWorldMatrix(newValue); // THEN QCOMPARE(spy.count(), 1); QCOMPARE(arbiter.dirtyNodes().size(), 0); QCOMPARE(t.worldMatrix(), newValue); // WHEN spy.clear(); dT->setWorldMatrix(newValue); // THEN QCOMPARE(spy.count(), 0); QCOMPARE(arbiter.dirtyNodes().size(), 0); QCOMPARE(t.worldMatrix(), newValue); } }; QTEST_MAIN(tst_QTransform) #include "tst_qtransform.moc"