1/****************************************************************************
2**
3** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QTest>
30#include <Qt3DRender/private/skeleton_p.h>
31#include <Qt3DRender/private/nodemanagers_p.h>
32#include <Qt3DCore/qjoint.h>
33#include <Qt3DCore/qskeleton.h>
34#include <Qt3DCore/qskeletonloader.h>
35#include <Qt3DCore/private/qnode_p.h>
36#include <Qt3DCore/private/qscene_p.h>
37#include <Qt3DCore/private/qbackendnode_p.h>
38#include <qbackendnodetester.h>
39#include <testpostmanarbiter.h>
40#include <testrenderer.h>
41
42using namespace Qt3DCore;
43using namespace Qt3DRender;
44using namespace Qt3DRender::Render;
45
46Q_DECLARE_METATYPE(Qt3DRender::Render::JointInfo)
47Q_DECLARE_METATYPE(Qt3DRender::Render::SkeletonData)
48Q_DECLARE_METATYPE(Qt3DCore::Sqt)
49
50class tst_Skeleton : public Qt3DCore::QBackendNodeTester
51{
52 Q_OBJECT
53
54private Q_SLOTS:
55 void checkPeerPropertyMirroring()
56 {
57 // GIVEN
58 TestRenderer renderer;
59 NodeManagers nodeManagers;
60 renderer.setNodeManagers(&nodeManagers);
61 Skeleton backendSkeleton;
62 backendSkeleton.setRenderer(&renderer);
63 backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager());
64 QSkeletonLoader skeleton;
65
66 skeleton.setSource(QUrl::fromLocalFile(localfile: "funnybones.json"));
67
68 // WHEN
69 simulateInitializationSync(frontend: &skeleton, backend: &backendSkeleton);
70
71 // THEN
72 QCOMPARE(backendSkeleton.peerId(), skeleton.id());
73 QCOMPARE(backendSkeleton.isEnabled(), skeleton.isEnabled());
74 QCOMPARE(backendSkeleton.source(), skeleton.source());
75 QCOMPARE(backendSkeleton.rootJointId(), QNodeId());
76
77 // GIVEN
78 Skeleton backendSkeleton2;
79 backendSkeleton2.setRenderer(&renderer);
80 backendSkeleton2.setSkeletonManager(nodeManagers.skeletonManager());
81 QSkeleton skeleton2;
82
83 QJoint *joint = new QJoint();
84 skeleton2.setRootJoint(joint);
85
86 // WHEN
87 simulateInitializationSync(frontend: &skeleton2, backend: &backendSkeleton2);
88
89 // THEN
90 QCOMPARE(backendSkeleton2.peerId(), skeleton2.id());
91 QCOMPARE(backendSkeleton2.isEnabled(), skeleton2.isEnabled());
92 QCOMPARE(backendSkeleton2.source(), QUrl());
93 QCOMPARE(backendSkeleton2.rootJointId(), joint->id());
94 }
95
96 void checkInitialAndCleanedUpState()
97 {
98 // GIVEN
99 TestRenderer renderer;
100 NodeManagers nodeManagers;
101 renderer.setNodeManagers(&nodeManagers);
102 Skeleton backendSkeleton;
103 backendSkeleton.setRenderer(&renderer);
104 backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager());
105
106 // THEN
107 QVERIFY(backendSkeleton.peerId().isNull());
108 QCOMPARE(backendSkeleton.isEnabled(), false);
109 QCOMPARE(backendSkeleton.source(), QUrl());
110 QCOMPARE(backendSkeleton.status(), QSkeletonLoader::NotReady);
111 QCOMPARE(backendSkeleton.rootJointId(), QNodeId());
112
113 // GIVEN
114 QSkeletonLoader skeleton;
115 skeleton.setSource(QUrl::fromLocalFile(localfile: "skeleton1.json"));
116
117 // WHEN
118 simulateInitializationSync(frontend: &skeleton, backend: &backendSkeleton);
119 backendSkeleton.cleanup();
120
121 // THEN
122 QCOMPARE(backendSkeleton.source(), QUrl());
123 QCOMPARE(backendSkeleton.isEnabled(), false);
124 QCOMPARE(backendSkeleton.status(), QSkeletonLoader::NotReady);
125 QCOMPARE(backendSkeleton.rootJointId(), QNodeId());
126 }
127
128 void checkDirectPropertyChanges()
129 {
130 // GIVEN
131 TestRenderer renderer;
132 NodeManagers nodeManagers;
133 renderer.setNodeManagers(&nodeManagers);
134 Skeleton backendSkeleton;
135 backendSkeleton.setRenderer(&renderer);
136 backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager());
137 backendSkeleton.setDataType(Skeleton::File);
138
139 // Initialize to ensure skeleton manager is set
140 QSkeletonLoader skeleton;
141 skeleton.setSource(QUrl::fromLocalFile(localfile: "skeleton1.json"));
142 simulateInitializationSync(frontend: &skeleton, backend: &backendSkeleton);
143
144 // WHEN
145 skeleton.setEnabled(false);
146 backendSkeleton.syncFromFrontEnd(frontEnd: &skeleton, firstTime: false);
147
148 // THEN
149 QCOMPARE(backendSkeleton.isEnabled(), false);
150
151 // WHEN
152 const QUrl newSource = QUrl::fromLocalFile(localfile: "terminator.json");
153 skeleton.setSource(newSource);
154 backendSkeleton.syncFromFrontEnd(frontEnd: &skeleton, firstTime: false);
155
156 // THEN
157 QCOMPARE(backendSkeleton.source(), newSource);
158 }
159
160 void checkCreateFrontendJoint_data()
161 {
162 QTest::addColumn<QMatrix4x4>(name: "inverseBindMatrix");
163 QTest::addColumn<Qt3DCore::Sqt>(name: "localPose");
164 QTest::addColumn<QString>(name: "jointName");
165 QTest::addColumn<QJoint *>(name: "expectedJoint");
166
167 QMatrix4x4 m;
168 Qt3DCore::Sqt localPose;
169 QTest::newRow(dataTag: "default") << m << localPose << QString() << new QJoint();
170
171 const QVector3D t(1.0f, 2.0f, 3.0f);
172 const QQuaternion r = QQuaternion::fromAxisAndAngle(x: 1.0f, y: 0.0f, z: 0.0f, angle: 45.0f);
173 const QVector3D s(1.5f, 2.5f, 3.5f);
174 localPose.scale = s;
175 localPose.rotation = r;
176 localPose.translation = t;
177
178
179 QString name = QLatin1String("Foo");
180 QJoint *joint = new QJoint();
181 joint->setTranslation(t);
182 joint->setRotation(r);
183 joint->setScale(s);
184 joint->setName(name);
185 joint->setInverseBindMatrix(m);
186 QTest::newRow(dataTag: "localPose") << m << localPose << name << joint;
187
188 m.rotate(quaternion: r);
189 m.scale(vector: QVector3D(1.0f, 1.0f, 1.0f) / s);
190 m.translate(vector: -t);
191 name = QLatin1String("Bar");
192
193 joint = new QJoint();
194 joint->setTranslation(t);
195 joint->setRotation(r);
196 joint->setScale(s);
197 joint->setInverseBindMatrix(m);
198 joint->setName(name);
199 QTest::newRow(dataTag: "inverseBind") << m << localPose << name << joint;
200 }
201};
202
203QTEST_APPLESS_MAIN(tst_Skeleton)
204
205#include "tst_skeleton.moc"
206

source code of qt3d/tests/auto/render/skeleton/tst_skeleton.cpp