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/joint_p.h> |
31 | #include <Qt3DRender/private/nodemanagers_p.h> |
32 | #include <Qt3DCore/qjoint.h> |
33 | #include <Qt3DCore/private/qnode_p.h> |
34 | #include <Qt3DCore/private/qscene_p.h> |
35 | #include <QtGui/qmatrix4x4.h> |
36 | #include <QtGui/qvector3d.h> |
37 | #include <qbackendnodetester.h> |
38 | #include <testpostmanarbiter.h> |
39 | #include <testrenderer.h> |
40 | |
41 | using namespace Qt3DCore; |
42 | using namespace Qt3DRender; |
43 | using namespace Qt3DRender::Render; |
44 | |
45 | class tst_Joint : public Qt3DCore::QBackendNodeTester |
46 | { |
47 | Q_OBJECT |
48 | |
49 | private Q_SLOTS: |
50 | void checkPeerPropertyMirroring() |
51 | { |
52 | // GIVEN |
53 | TestRenderer renderer; |
54 | NodeManagers nodeManagers; |
55 | renderer.setNodeManagers(&nodeManagers); |
56 | Joint backendJoint; |
57 | backendJoint.setRenderer(&renderer); |
58 | backendJoint.setJointManager(nodeManagers.jointManager()); |
59 | backendJoint.setSkeletonManager(nodeManagers.skeletonManager()); |
60 | QJoint joint; |
61 | |
62 | joint.setTranslation(QVector3D(1.0f, 2.0f, 3.0f)); |
63 | joint.setScale(QVector3D(1.5f, 2.5f, 3.5)); |
64 | joint.setRotation(QQuaternion::fromAxisAndAngle(x: 1.0f, y: 0.0f, z: 0.0f, angle: 45.0f)); |
65 | QMatrix4x4 inverseBind; |
66 | inverseBind.rotate(angle: -45.0f, x: 1.0f, y: 0.0, z: 0.0f); |
67 | joint.setInverseBindMatrix(inverseBind); |
68 | |
69 | QVector<QJoint *> childJoints; |
70 | for (int i = 0; i < 10; ++i) { |
71 | const auto childJoint = new QJoint(); |
72 | joint.addChildJoint(joint: childJoint); |
73 | childJoints.push_back(t: childJoint); |
74 | } |
75 | |
76 | // WHEN |
77 | simulateInitializationSync(frontend: &joint, backend: &backendJoint); |
78 | |
79 | // THEN |
80 | QCOMPARE(backendJoint.peerId(), joint.id()); |
81 | QCOMPARE(backendJoint.isEnabled(), joint.isEnabled()); |
82 | QCOMPARE(backendJoint.translation(), joint.translation()); |
83 | QCOMPARE(backendJoint.rotation(), joint.rotation()); |
84 | QCOMPARE(backendJoint.scale(), joint.scale()); |
85 | QCOMPARE(backendJoint.inverseBindMatrix(), joint.inverseBindMatrix()); |
86 | for (int i = 0; i < childJoints.size(); ++i) { |
87 | QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); |
88 | } |
89 | } |
90 | |
91 | void checkInitialAndCleanedUpState() |
92 | { |
93 | // GIVEN |
94 | TestRenderer renderer; |
95 | NodeManagers nodeManagers; |
96 | renderer.setNodeManagers(&nodeManagers); |
97 | Joint backendJoint; |
98 | backendJoint.setRenderer(&renderer); |
99 | backendJoint.setJointManager(nodeManagers.jointManager()); |
100 | backendJoint.setSkeletonManager(nodeManagers.skeletonManager()); |
101 | |
102 | // THEN |
103 | QVERIFY(backendJoint.peerId().isNull()); |
104 | QCOMPARE(backendJoint.isEnabled(), false); |
105 | QCOMPARE(backendJoint.translation(), QVector3D()); |
106 | QCOMPARE(backendJoint.rotation(), QQuaternion()); |
107 | QCOMPARE(backendJoint.scale(), QVector3D(1.0f, 1.0f, 1.0f)); |
108 | QCOMPARE(backendJoint.inverseBindMatrix(), QMatrix4x4()); |
109 | QCOMPARE(backendJoint.childJointIds(), QNodeIdVector()); |
110 | QCOMPARE(backendJoint.owningSkeleton(), HSkeleton()); |
111 | |
112 | // GIVEN |
113 | QJoint joint; |
114 | joint.setTranslation(QVector3D(1.0f, 2.0f, 3.0f)); |
115 | joint.setScale(QVector3D(1.5f, 2.5f, 3.5)); |
116 | joint.setRotation(QQuaternion::fromAxisAndAngle(x: 1.0f, y: 0.0f, z: 0.0f, angle: 45.0f)); |
117 | QMatrix4x4 inverseBind; |
118 | inverseBind.rotate(angle: -45.0f, x: 1.0f, y: 0.0, z: 0.0f); |
119 | joint.setInverseBindMatrix(inverseBind); |
120 | |
121 | QVector<QJoint *> childJoints; |
122 | for (int i = 0; i < 10; ++i) { |
123 | const auto childJoint = new QJoint(); |
124 | joint.addChildJoint(joint: childJoint); |
125 | childJoints.push_back(t: childJoint); |
126 | } |
127 | |
128 | // WHEN |
129 | simulateInitializationSync(frontend: &joint, backend: &backendJoint); |
130 | backendJoint.cleanup(); |
131 | |
132 | // THEN |
133 | QCOMPARE(backendJoint.isEnabled(), false); |
134 | QCOMPARE(backendJoint.translation(), QVector3D()); |
135 | QCOMPARE(backendJoint.rotation(), QQuaternion()); |
136 | QCOMPARE(backendJoint.scale(), QVector3D(1.0f, 1.0f, 1.0f)); |
137 | QCOMPARE(backendJoint.inverseBindMatrix(), QMatrix4x4()); |
138 | QCOMPARE(backendJoint.childJointIds(), QNodeIdVector()); |
139 | QCOMPARE(backendJoint.owningSkeleton(), HSkeleton()); |
140 | } |
141 | |
142 | void checkPropertyChanges() |
143 | { |
144 | // GIVEN |
145 | TestRenderer renderer; |
146 | NodeManagers nodeManagers; |
147 | renderer.setNodeManagers(&nodeManagers); |
148 | Joint backendJoint; |
149 | backendJoint.setRenderer(&renderer); |
150 | backendJoint.setJointManager(nodeManagers.jointManager()); |
151 | backendJoint.setSkeletonManager(nodeManagers.skeletonManager()); |
152 | QJoint joint; |
153 | simulateInitializationSync(frontend: &joint, backend: &backendJoint); |
154 | |
155 | // WHEN |
156 | joint.setEnabled(false); |
157 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
158 | |
159 | // THEN |
160 | QCOMPARE(backendJoint.isEnabled(), false); |
161 | |
162 | // WHEN |
163 | const QVector3D newTranslation = QVector3D(1.0f, 2.0f, 3.0f); |
164 | joint.setTranslation(newTranslation); |
165 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
166 | |
167 | // THEN |
168 | QCOMPARE(backendJoint.translation(), newTranslation); |
169 | |
170 | // WHEN |
171 | const QQuaternion newRotation = QQuaternion::fromAxisAndAngle(x: 1.0f, y: 0.0f, z: 0.0f, angle: 45.0f); |
172 | joint.setRotation(newRotation); |
173 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
174 | |
175 | // THEN |
176 | QCOMPARE(backendJoint.rotation(), newRotation); |
177 | |
178 | // WHEN |
179 | const QVector3D newScale = QVector3D(1.5f, 2.5f, 3.5f); |
180 | joint.setScale(newScale); |
181 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
182 | |
183 | // THEN |
184 | QCOMPARE(backendJoint.scale(), newScale); |
185 | |
186 | // WHEN |
187 | QMatrix4x4 newInverseBind; |
188 | newInverseBind.scale(factor: 5.4f); |
189 | joint.setInverseBindMatrix(newInverseBind); |
190 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
191 | |
192 | // THEN |
193 | QCOMPARE(backendJoint.inverseBindMatrix(), newInverseBind); |
194 | |
195 | // WHEN |
196 | QVector<QJoint *> childJoints; |
197 | for (int i = 0; i < 10; ++i) { |
198 | const auto childJoint = new QJoint(); |
199 | childJoints.push_back(t: childJoint); |
200 | joint.addChildJoint(joint: childJoint); |
201 | } |
202 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
203 | |
204 | // THEN |
205 | for (int i = 0; i < childJoints.size(); ++i) |
206 | QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); |
207 | |
208 | for (int i = 0; i < 10; ++i) { |
209 | // WHEN |
210 | const auto childJoint = childJoints.takeLast(); |
211 | joint.removeChildJoint(joint: childJoint); |
212 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
213 | |
214 | // THEN |
215 | for (int i = 0; i < childJoints.size(); ++i) |
216 | QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); |
217 | } |
218 | } |
219 | |
220 | void checkDirectPropertyChanges() |
221 | { |
222 | // GIVEN |
223 | TestRenderer renderer; |
224 | NodeManagers nodeManagers; |
225 | renderer.setNodeManagers(&nodeManagers); |
226 | Joint backendJoint; |
227 | backendJoint.setRenderer(&renderer); |
228 | backendJoint.setJointManager(nodeManagers.jointManager()); |
229 | backendJoint.setSkeletonManager(nodeManagers.skeletonManager()); |
230 | |
231 | QJoint joint; |
232 | simulateInitializationSync(frontend: &joint, backend: &backendJoint); |
233 | |
234 | // WHEN |
235 | joint.setEnabled(false); |
236 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
237 | |
238 | // THEN |
239 | QCOMPARE(backendJoint.isEnabled(), false); |
240 | |
241 | // WHEN |
242 | const QVector3D newTranslation = QVector3D(1.0f, 2.0f, 3.0f); |
243 | joint.setTranslation(newTranslation); |
244 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
245 | |
246 | // THEN |
247 | QCOMPARE(backendJoint.translation(), newTranslation); |
248 | |
249 | // WHEN |
250 | const QQuaternion newRotation = QQuaternion::fromAxisAndAngle(x: 1.0f, y: 0.0f, z: 0.0f, angle: 45.0f); |
251 | joint.setRotation(newRotation); |
252 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
253 | |
254 | // THEN |
255 | QCOMPARE(backendJoint.rotation(), newRotation); |
256 | |
257 | // WHEN |
258 | const QVector3D newScale = QVector3D(1.5f, 2.5f, 3.5f); |
259 | joint.setScale(newScale); |
260 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
261 | |
262 | // THEN |
263 | QCOMPARE(backendJoint.scale(), newScale); |
264 | |
265 | // WHEN |
266 | QMatrix4x4 newInverseBind; |
267 | newInverseBind.scale(factor: 5.4f); |
268 | joint.setInverseBindMatrix(newInverseBind); |
269 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
270 | |
271 | // THEN |
272 | QCOMPARE(backendJoint.inverseBindMatrix(), newInverseBind); |
273 | |
274 | // WHEN |
275 | QVector<QJoint *> childJoints; |
276 | for (int i = 0; i < 10; ++i) { |
277 | const auto childJoint = new QJoint(); |
278 | joint.addChildJoint(joint: childJoint); |
279 | childJoints.push_back(t: childJoint); |
280 | } |
281 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
282 | |
283 | // THEN |
284 | for (int i = 0; i < childJoints.size(); ++i) { |
285 | QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); |
286 | } |
287 | |
288 | for (int i = 0; i < 10; ++i) { |
289 | // WHEN |
290 | const auto childJoint = childJoints.takeLast(); |
291 | |
292 | joint.removeChildJoint(joint: childJoint); |
293 | backendJoint.syncFromFrontEnd(frontEnd: &joint, firstTime: false); |
294 | |
295 | // THEN |
296 | for (int j = 0; j < childJoints.size(); ++j) |
297 | QCOMPARE(backendJoint.childJointIds()[j], childJoints[j]->id()); |
298 | } |
299 | } |
300 | }; |
301 | |
302 | QTEST_APPLESS_MAIN(tst_Joint) |
303 | |
304 | #include "tst_joint.moc" |
305 | |