[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-physics3d / utc-Dali-PhysicsAdaptor.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18 #include <iostream>
19 #include <typeinfo>
20
21 // Need to override adaptor classes for toolkit test harness, so include
22 // test harness headers before dali headers.
23 #include <dali-physics/dali-physics.h>
24 #include <dali-toolkit-test-suite-utils.h>
25 #include <toolkit-event-thread-callback.h>
26
27 #include <dali-toolkit/devel-api/controls/alignment/alignment.h>
28 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
29 #include <dali/devel-api/adaptor-framework/window-devel.h>
30 #include <dali/devel-api/events/hit-test-algorithm.h>
31
32 #include <bullet/btBulletDynamicsCommon.h>
33
34 using namespace Dali;
35 using namespace Dali::Toolkit::Physics;
36
37 void utc_dali_physics3d_startup(void)
38 {
39   test_return_value = TET_UNDEF;
40 }
41
42 void utc_dali_physics3d_cleanup(void)
43 {
44   test_return_value = TET_PASS;
45 }
46
47 btRigidBody* CreateBody(btDiscreteDynamicsWorld* bulletWorld)
48 {
49   btSphereShape* ball = new btSphereShape(30);
50   btVector3      localInertia(0.f, 0.f, 0.f);
51   ball->calculateLocalInertia(10, localInertia);
52   btTransform transform;
53   transform.setIdentity();
54   auto* motionState = new btDefaultMotionState(transform);
55
56   btRigidBody::btRigidBodyConstructionInfo ci(10, motionState, ball, localInertia);
57
58   btRigidBody* body = new btRigidBody(ci);
59   body->setFriction(0.5f);
60   body->setRestitution(0.5f);
61   bulletWorld->addRigidBody(body);
62   return body;
63 }
64
65 int UtcDaliPhysics3DCreateAdaptorP1(void)
66 {
67   ToolkitTestApplication application;
68
69   Matrix     transform(true);
70   Uint16Pair size(640, 480);
71
72   PhysicsAdaptor handle = PhysicsAdaptor::New(transform, size);
73   DALI_TEST_CHECK(handle);
74
75   END_TEST;
76 }
77
78 int UtcDaliPhysics3DCreateAdaptorN1(void)
79 {
80   ToolkitTestApplication application;
81
82   PhysicsAdaptor handle;
83   DALI_TEST_CHECK(!handle);
84
85   END_TEST;
86 }
87
88 int UtcDaliPhysics3DDowncastP1(void)
89 {
90   ToolkitTestApplication application;
91
92   Matrix     transform(true);
93   Uint16Pair size(640, 480);
94
95   BaseHandle handle = PhysicsAdaptor::New(transform, size);
96
97   auto adaptor = PhysicsAdaptor::DownCast(handle);
98   DALI_TEST_CHECK(adaptor);
99   //Following only works if type is registered
100   //DALI_TEST_EQUALS("PhysicsAdaptor", adaptor.GetTypeName(), TEST_LOCATION);
101   END_TEST;
102 }
103
104 int UtcDaliPhysics3DDowncastN1(void)
105 {
106   BaseHandle handle;
107   auto       adaptor = PhysicsAdaptor::DownCast(handle);
108   DALI_TEST_CHECK(!adaptor);
109
110   DALI_TEST_CHECK(typeid(PhysicsAdaptor) == typeid(decltype(adaptor)));
111   END_TEST;
112 }
113
114 int UtcDaliPhysics3DAdaptorMoveConstructor(void)
115 {
116   ToolkitTestApplication application;
117   tet_infoline("Testing the move constructor");
118
119   Matrix         transform(true);
120   Uint16Pair     size(640, 480);
121   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
122   DALI_TEST_CHECK(adaptor);
123
124   PhysicsAdaptor moved = std::move(adaptor);
125   DALI_TEST_CHECK(moved);
126   DALI_TEST_CHECK(!adaptor);
127   DALI_TEST_CHECK(moved != adaptor);
128
129   END_TEST;
130 }
131
132 int UtcDaliPhysics3DAdaptorCopyConstructor(void)
133 {
134   ToolkitTestApplication application;
135   tet_infoline("Testing the move constructor");
136
137   Matrix         transform(true);
138   Uint16Pair     size(640, 480);
139   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
140
141   DALI_TEST_CHECK(adaptor);
142
143   PhysicsAdaptor altAdaptor = adaptor;
144   DALI_TEST_CHECK(altAdaptor);
145   DALI_TEST_CHECK(adaptor);
146   DALI_TEST_CHECK(altAdaptor == adaptor); // should point at same object
147
148   END_TEST;
149 }
150
151 int UtcDaliPhysics3DAdaptorCopyAssign(void)
152 {
153   ToolkitTestApplication application;
154   tet_infoline("Testing the copy assign");
155
156   Matrix         transform(true);
157   Uint16Pair     size(640, 480);
158   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
159   DALI_TEST_CHECK(adaptor);
160
161   PhysicsAdaptor altAdaptor = adaptor;
162   DALI_TEST_CHECK(altAdaptor);
163   DALI_TEST_CHECK(adaptor);
164   DALI_TEST_CHECK(altAdaptor == adaptor); // should point at same object
165
166   END_TEST;
167 }
168
169 int UtcDaliPhysics3DAdaptorMoveAssignment(void)
170 {
171   ToolkitTestApplication application;
172   tet_infoline("Testing the move constructor");
173
174   Matrix         transform(true);
175   Uint16Pair     size(640, 480);
176   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
177   DALI_TEST_CHECK(adaptor);
178
179   PhysicsAdaptor moved;
180   moved = std::move(adaptor);
181   DALI_TEST_CHECK(moved);
182   DALI_TEST_CHECK(!adaptor);
183
184   END_TEST;
185 }
186
187 int UtcDaliPhysics3DSetTimestep(void)
188 {
189   ToolkitTestApplication application;
190
191   Matrix     transform(true);
192   Uint16Pair size(640, 480);
193
194   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
195   adaptor.SetTimestep(1.0f / 60.0f);
196
197   DALI_TEST_EQUALS(adaptor.GetTimestep(), 1.0f / 60.0f, 0.0001f, TEST_LOCATION);
198
199   END_TEST;
200 }
201
202 int UtcDaliPhysics3DGetTimestep(void)
203 {
204   ToolkitTestApplication application;
205
206   Matrix     transform(true);
207   Uint16Pair size(640, 480);
208
209   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
210   adaptor.SetTimestep(1.0f / 60.0f);
211   float timestep = adaptor.GetTimestep();
212   float expected = 1.0f / 60.0f;
213   DALI_TEST_EQUALS(timestep, expected, 0.0001f, TEST_LOCATION);
214
215   adaptor.SetTimestep(1.0f / 120.0f);
216   timestep = adaptor.GetTimestep();
217   expected = 1.0f / 120.0f;
218   DALI_TEST_EQUALS(timestep, expected, 0.0001f, TEST_LOCATION);
219
220   END_TEST;
221 }
222
223 int UtcDaliPhysics3DGetPhysicsAccessorP1(void)
224 {
225   ToolkitTestApplication application;
226
227   Matrix     transform(true);
228   Uint16Pair size(640, 480);
229
230   PhysicsAdaptor                           adaptor  = PhysicsAdaptor::New(transform, size);
231   PhysicsAdaptor::ScopedPhysicsAccessorPtr accessor = adaptor.GetPhysicsAccessor();
232   DALI_TEST_CHECK(accessor.get() != nullptr);
233
234   Dali::Any world = accessor->GetNative();
235   DALI_TEST_CHECK(!world.Empty());
236
237   END_TEST;
238 }
239
240 int UtcDaliPhysics3DGetPhysicsAccessorN1(void)
241 {
242   ToolkitTestApplication application;
243
244   PhysicsAdaptor handle;
245   DALI_TEST_CHECK(!handle);
246
247   try
248   {
249     auto ptr = handle.GetPhysicsAccessor();
250     DALI_TEST_CHECK(ptr == nullptr);
251
252     tet_result(TET_FAIL);
253   }
254   catch(DaliException& e)
255   {
256     DALI_TEST_ASSERT(e, "Physics adaptor handle is empty", TEST_LOCATION);
257   }
258
259   END_TEST;
260 }
261
262 int UtcDaliPhysics3DAdaptorGetRootActor(void)
263 {
264   tet_infoline("Test that the root actor can be retrieved");
265
266   ToolkitTestApplication application;
267   Matrix                 transform(false);
268   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
269   Uint16Pair     size(640, 480);
270   auto           scene     = application.GetScene();
271   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
272   Actor          rootActor = adaptor.GetRootActor();
273   scene.Add(rootActor);
274
275   DALI_TEST_CHECK(rootActor);
276   DALI_TEST_EQUALS(rootActor.GetProperty<Vector2>(Actor::Property::SIZE), Vector2(640.0f, 480.0f), 0.001f, TEST_LOCATION);
277
278   END_TEST;
279 }
280
281 int UtcDaliPhysics3DAdaptorCreateDebugLayer(void)
282 {
283   ToolkitTestApplication application;
284   Matrix                 transform(true);
285   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
286   Uint16Pair size(640, 480);
287   auto       scene = application.GetScene();
288
289   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
290   Actor          rootActor = adaptor.GetRootActor();
291   scene.Add(rootActor);
292   Window window = DevelWindow::Get(rootActor);
293
294   Layer layer = adaptor.CreateDebugLayer(window);
295   DALI_TEST_CHECK(layer);
296
297   adaptor.SetDebugState(PhysicsAdaptor::DebugState::ON);
298
299   btRigidBody* body{nullptr};
300   {
301     auto accessor            = adaptor.GetPhysicsAccessor();
302     auto bulletWorld         = accessor->GetNative().Get<btDiscreteDynamicsWorld*>();
303     body                     = CreateBody(bulletWorld);
304     Dali::Actor ballActor    = Toolkit::ImageView::New(TEST_RESOURCE_DIR "/gallery-small-1.jpg");
305     auto        physicsActor = adaptor.AddActorBody(ballActor, body);
306     physicsActor.AsyncSetPhysicsPosition(Vector3(0.f, 0.f, 0.f));
307   }
308   Test::WaitForEventThreadTrigger(1);
309   application.SendNotification();
310   application.Render();
311
312   application.SendNotification();
313   application.Render();
314
315   END_TEST;
316 }
317
318 int UtcDaliPhysics3DAdaptorTranslateToPhysicsSpace1(void)
319 {
320   ToolkitTestApplication application;
321   Matrix                 transform(false);
322   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
323   Uint16Pair     size(640, 480);
324   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
325
326   Vector3 a(30, 20, 10);
327   Vector3 expected = a * 2.0f;
328   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(a), expected, 0.0001f, TEST_LOCATION);
329
330   END_TEST;
331 }
332
333 int UtcDaliPhysics3DAdaptorTranslateToPhysicsSpace2(void)
334 {
335   ToolkitTestApplication application;
336   Matrix                 transform(false);
337   tet_infoline("Test that using an alternative scale doesn't change rotation");
338   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
339   Uint16Pair     size(640, 480);
340   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
341
342   // Rotation shouldn't change under this scale
343   Quaternion q(Degree(30.0f), Vector3::XAXIS);
344   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(q), q, 0.0001f, TEST_LOCATION);
345
346   END_TEST;
347 }
348
349 int UtcDaliPhysics3DAdaptorTranslateToPhysicsSpace3(void)
350 {
351   ToolkitTestApplication application;
352   Matrix                 transform(false);
353   tet_infoline("Test that using an inverted Y scale also inverts quaternions");
354
355   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
356   Uint16Pair     size(640, 480);
357   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
358
359   Quaternion q(Degree(30.0f), Vector3::ZAXIS);
360   Quaternion qp(Degree(-30.0f), Vector3::ZAXIS); // We have mirrored along Y axis, so Z rot is opposite.
361
362   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(q), qp, 0.0001f, TEST_LOCATION);
363
364   END_TEST;
365 }
366
367 int UtcDaliPhysics3DAdaptorTranslateToPhysicsSpace4(void)
368 {
369   ToolkitTestApplication application;
370   Matrix                 transform(false);
371   tet_infoline("Test that using an inverted Y scale also inverts quaternions");
372
373   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
374   Uint16Pair     size(640, 480);
375   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
376
377   Quaternion q(Degree(30.0f), Vector3::XAXIS);
378   Quaternion qp(Degree(-30.0f), Vector3::XAXIS); // We have mirrored along Y axis, so Z rot is opposite.
379
380   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(q), qp, 0.0001f, TEST_LOCATION);
381
382   END_TEST;
383 }
384
385 int UtcDaliPhysics3DAdaptorTranslateToPhysicsSpace5(void)
386 {
387   ToolkitTestApplication application;
388   Matrix                 transform(false);
389   tet_infoline("Test that using an inverted Y scale also inverts quaternions, except along Y axis");
390
391   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
392   Uint16Pair     size(640, 480);
393   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
394
395   Quaternion q(Degree(30.0f), Vector3::YAXIS);
396   Quaternion qp(Degree(30.0f), Vector3::YAXIS);
397
398   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(q), qp, 0.0001f, TEST_LOCATION);
399
400   END_TEST;
401 }
402
403 int UtcDaliPhysics3DAdaptorTranslateFromPhysicsSpace1(void)
404 {
405   ToolkitTestApplication application;
406   Matrix                 transform(false);
407   tet_infoline("Test that using a double scale halves position");
408
409   transform.SetIdentityAndScale(Vector3(2.0f, -2.0f, 2.0f));
410   Uint16Pair     size(640, 480);
411   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
412
413   Vector3 position(20.0f, 20.0f, 0.0f);
414   Vector3 expected(10.0f, -10.0f, 0.0f);
415
416   DALI_TEST_EQUALS(adaptor.TranslateFromPhysicsSpace(position), expected, 0.0001f, TEST_LOCATION);
417
418   END_TEST;
419 }
420
421 int UtcDaliPhysics3DAdaptorConvertVectorToPhysicsSpace01(void)
422 {
423   ToolkitTestApplication application;
424   Matrix                 transform(false);
425   tet_infoline("Test that using a translation does not translate vector");
426
427   transform.SetIdentityAndScale(Vector3(1.0f, 1.0f, 1.0f));
428   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
429   Uint16Pair     size(640, 480);
430   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
431   Vector3        vector(20.0f, 20.0f, 0.0f);
432   DALI_TEST_EQUALS(adaptor.ConvertVectorToPhysicsSpace(vector), vector, 0.0001f, TEST_LOCATION);
433
434   END_TEST;
435 }
436
437 int UtcDaliPhysics3DAdaptorConvertVectorToPhysicsSpace02(void)
438 {
439   ToolkitTestApplication application;
440   Matrix                 transform(false);
441   tet_infoline("Test that using a translation with inverse Y does not translate vector");
442
443   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
444   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
445   Uint16Pair     size(640, 480);
446   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
447   Vector3        vector(20.0f, 20.0f, 0.0f);
448   Vector3        expected(20.0f, -20.0f, 0.0f);
449   DALI_TEST_EQUALS(adaptor.ConvertVectorToPhysicsSpace(vector), expected, 0.0001f, TEST_LOCATION);
450
451   END_TEST;
452 }
453
454 int UtcDaliPhysics3DAdaptorConvertVectorFromPhysicsSpace01(void)
455 {
456   ToolkitTestApplication application;
457   Matrix                 transform(false);
458   tet_infoline("Test that using a translation does not translate vector");
459
460   transform.SetIdentityAndScale(Vector3(1.0f, 1.0f, 1.0f));
461   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
462   Uint16Pair     size(640, 480);
463   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
464   Vector3        vector(20.0f, 20.0f, 0.0f);
465   DALI_TEST_EQUALS(adaptor.ConvertVectorFromPhysicsSpace(vector), vector, 0.0001f, TEST_LOCATION);
466
467   END_TEST;
468 }
469
470 int UtcDaliPhysics3DAdaptorConvertVectorFromPhysicsSpace02(void)
471 {
472   ToolkitTestApplication application;
473   Matrix                 transform(false);
474   tet_infoline("Test that using a translation with inverse Y does not translate vector");
475
476   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
477   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
478   Uint16Pair     size(640, 480);
479   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
480   Vector3        vector(20.0f, 20.0f, 0.0f);
481   Vector3        expected(20.0f, -20.0f, 0.0f);
482   DALI_TEST_EQUALS(adaptor.ConvertVectorFromPhysicsSpace(vector), expected, 0.0001f, TEST_LOCATION);
483
484   END_TEST;
485 }
486
487 int UtcDaliPhysics3DAdaptorSetTransformAndSize(void)
488 {
489   ToolkitTestApplication application;
490   Matrix                 transform(false);
491   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
492   Uint16Pair     size(640, 480);
493   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
494
495   Vector3 a(30, 20, 10);
496   Vector3 expected = a * 2.0f;
497   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(a), expected, 0.0001f, TEST_LOCATION);
498
499   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
500   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
501   adaptor.SetTransformAndSize(transform, size);
502
503   Vector3 expect2(30, 80, 10);
504   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(a), expect2, 0.0001f, TEST_LOCATION);
505
506   END_TEST;
507 }
508
509 int UtcDaliPhysics3DAdaptorSetIntegrationState(void)
510 {
511   tet_infoline("Test that changing the integration state is reflected");
512
513   ToolkitTestApplication application;
514   Matrix                 transform(false);
515   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
516   Uint16Pair     size(640, 480);
517   auto           scene     = application.GetScene();
518   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
519   Actor          rootActor = adaptor.GetRootActor();
520   scene.Add(rootActor);
521
522   DALI_TEST_CHECK(adaptor.GetIntegrationState() == PhysicsAdaptor::IntegrationState::ON);
523
524   adaptor.SetIntegrationState(PhysicsAdaptor::IntegrationState::OFF);
525   DALI_TEST_CHECK(adaptor.GetIntegrationState() == PhysicsAdaptor::IntegrationState::OFF);
526
527   END_TEST;
528 }
529
530 int UtcDaliPhysics3DAdaptorGetIntegrationState(void)
531 {
532   tet_infoline("Test that changing the integration state is reflected");
533
534   ToolkitTestApplication application;
535   Matrix                 transform(false);
536   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
537   Uint16Pair     size(640, 480);
538   auto           scene     = application.GetScene();
539   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
540   Actor          rootActor = adaptor.GetRootActor();
541   scene.Add(rootActor);
542
543   adaptor.SetIntegrationState(PhysicsAdaptor::IntegrationState::OFF);
544   DALI_TEST_CHECK(adaptor.GetIntegrationState() == PhysicsAdaptor::IntegrationState::OFF);
545
546   adaptor.SetIntegrationState(PhysicsAdaptor::IntegrationState::ON);
547   DALI_TEST_CHECK(adaptor.GetIntegrationState() == PhysicsAdaptor::IntegrationState::ON);
548
549   // Can't test actual integration step runs without adding actors - see utc-Dali-PhysicsActor.cpp.
550   END_TEST;
551 }
552
553 int UtcDaliPhysics3DAdaptorSetDebugState(void)
554 {
555   tet_infoline("Test that changing the debug state is reflected");
556
557   ToolkitTestApplication application;
558   Matrix                 transform(false);
559   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
560   Uint16Pair     size(640, 480);
561   auto           scene     = application.GetScene();
562   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
563   Actor          rootActor = adaptor.GetRootActor();
564   scene.Add(rootActor);
565
566   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::OFF);
567
568   adaptor.SetDebugState(PhysicsAdaptor::DebugState::ON);
569   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::ON);
570
571   adaptor.SetDebugState(PhysicsAdaptor::DebugState::OFF);
572   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::OFF);
573
574   END_TEST;
575 }
576
577 int UtcDaliPhysics3DAdaptorGetDebugState(void)
578 {
579   tet_infoline("Test that changing the debug state is reflected");
580
581   ToolkitTestApplication application;
582   Matrix                 transform(false);
583   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
584   Uint16Pair     size(640, 480);
585   auto           scene     = application.GetScene();
586   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
587   Actor          rootActor = adaptor.GetRootActor();
588   scene.Add(rootActor);
589
590   adaptor.SetDebugState(PhysicsAdaptor::DebugState::OFF);
591   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::OFF);
592
593   adaptor.SetDebugState(PhysicsAdaptor::DebugState::ON);
594   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::ON);
595
596   // Can't test actual debug step runs without adding actors - see utc-Dali-PhysicsActor.cpp.
597   END_TEST;
598 }
599
600 int UtcDaliPhysics3DAdaptorAddActorBody(void)
601 {
602   tet_infoline("Test that an actor/body pair can be added");
603
604   ToolkitTestApplication application;
605   Matrix                 transform(false);
606   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
607   Uint16Pair     size(640, 480);
608   auto           scene     = application.GetScene();
609   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
610   Actor          rootActor = adaptor.GetRootActor();
611   scene.Add(rootActor);
612
613   auto accessor    = adaptor.GetPhysicsAccessor();
614   auto bulletWorld = accessor->GetNative().Get<btDiscreteDynamicsWorld*>();
615
616   btRigidBody* body         = CreateBody(bulletWorld);
617   Dali::Actor  ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
618   auto         physicsActor = adaptor.AddActorBody(ballActor, body);
619
620   DALI_TEST_CHECK(physicsActor);
621   int id = ballActor[Actor::Property::ID];
622
623   DALI_TEST_EQUALS(physicsActor.GetId(), id, TEST_LOCATION);
624   DALI_TEST_EQUALS(physicsActor.GetBody().Get<btRigidBody*>(), body, TEST_LOCATION);
625
626   END_TEST;
627 }
628
629 int UtcDaliPhysics3DAdaptorRemoveActorBodyP01(void)
630 {
631   tet_infoline("Test that an actor/body pair can be removed");
632
633   ToolkitTestApplication application;
634   Matrix                 transform(false);
635   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
636   Uint16Pair     size(640, 480);
637   auto           scene     = application.GetScene();
638   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
639   Actor          rootActor = adaptor.GetRootActor();
640   scene.Add(rootActor);
641
642   btRigidBody* body;
643   {
644     auto accessor    = adaptor.GetPhysicsAccessor();
645     auto bulletWorld = accessor->GetNative().Get<btDiscreteDynamicsWorld*>();
646
647     body = CreateBody(bulletWorld);
648   }
649   Dali::Actor ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
650   auto        physicsActor = adaptor.AddActorBody(ballActor, body);
651
652   application.SendNotification();
653   application.Render();
654   application.SendNotification();
655   application.Render();
656
657   adaptor.RemoveActorBody(physicsActor);
658   DALI_TEST_CHECK(!ballActor.GetParent());
659
660   {
661     auto accessor    = adaptor.GetPhysicsAccessor();
662     auto bulletWorld = accessor->GetNative().Get<btDiscreteDynamicsWorld*>();
663
664     bulletWorld->removeRigidBody(body);
665     try
666     {
667       delete body;
668       tet_result(TET_PASS);
669     }
670     catch(std::exception& e)
671     {
672       tet_result(TET_FAIL);
673     }
674   }
675
676   END_TEST;
677 }
678
679 int UtcDaliPhysics3DAdaptorRemoveActorBodyN01(void)
680 {
681   tet_infoline("Test that an empty actor/body pair doesn't break adaptor");
682
683   ToolkitTestApplication application;
684   Matrix                 transform(false);
685   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
686   Uint16Pair     size(640, 480);
687   auto           scene     = application.GetScene();
688   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
689   Actor          rootActor = adaptor.GetRootActor();
690   scene.Add(rootActor);
691
692   tet_infoline("Test that removing a physics actor that hasn't been created with AddActorBody does nothing");
693
694   Dali::Actor  actor = Dali::Actor::New();
695   btRigidBody* body;
696   {
697     auto accessor    = adaptor.GetPhysicsAccessor();
698     auto bulletWorld = accessor->GetNative().Get<btDiscreteDynamicsWorld*>();
699
700     body = CreateBody(bulletWorld);
701   }
702
703   PhysicsActor physicsActor = PhysicsActor::New(actor, body, adaptor);
704   ;
705   try
706   {
707     adaptor.RemoveActorBody(physicsActor);
708     tet_result(TET_PASS);
709   }
710   catch(std::exception& e)
711   {
712     tet_result(TET_FAIL);
713   }
714
715   END_TEST;
716 }
717
718 int UtcDaliPhysics3DAdaptorRemoveActorBodyN02(void)
719 {
720   tet_infoline("Test that an empty actor/body pair doesn't break adaptor");
721
722   ToolkitTestApplication application;
723   Matrix                 transform(false);
724   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
725   Uint16Pair     size(640, 480);
726   auto           scene     = application.GetScene();
727   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
728   Actor          rootActor = adaptor.GetRootActor();
729   scene.Add(rootActor);
730
731   PhysicsActor physicsActor;
732   try
733   {
734     adaptor.RemoveActorBody(physicsActor);
735     tet_result(TET_FAIL);
736   }
737   catch(DaliException& e)
738   {
739     DALI_TEST_ASSERT(e, "Physics actor handle is empty", TEST_LOCATION);
740   }
741
742   END_TEST;
743 }
744
745 int UtcDaliPhysics3DAdaptorGetPhysicsActor(void)
746 {
747   tet_infoline("Test that an actor/body pair can be retrieved");
748
749   ToolkitTestApplication application;
750   Matrix                 transform(false);
751   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
752   Uint16Pair     size(640, 480);
753   auto           scene     = application.GetScene();
754   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
755   Actor          rootActor = adaptor.GetRootActor();
756   scene.Add(rootActor);
757
758   auto accessor    = adaptor.GetPhysicsAccessor();
759   auto bulletWorld = accessor->GetNative().Get<btDiscreteDynamicsWorld*>();
760
761   btRigidBody* body         = CreateBody(bulletWorld);
762   Dali::Actor  ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
763   auto         physicsActor = adaptor.AddActorBody(ballActor, body);
764
765   DALI_TEST_CHECK(physicsActor);
766
767   PhysicsActor testActor = adaptor.GetPhysicsActor(body);
768   DALI_TEST_CHECK(testActor);
769   DALI_TEST_CHECK(physicsActor == testActor);
770
771   END_TEST;
772 }
773
774 int UtcDaliPhysics3DAdaptorBuildPickingRay(void)
775 {
776   tet_infoline("Test that a touch can be converted to a picking ray");
777
778   ToolkitTestApplication application;
779   Matrix                 transform(false);
780   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
781   Uint16Pair     size(640, 480);
782   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
783
784   Vector3 from, to;
785   adaptor.BuildPickingRay(Vector3(), -Vector3::ZAXIS, from, to);
786
787   DALI_TEST_EQUALS(from, Vector3(), 0.001f, TEST_LOCATION);
788   DALI_TEST_EQUALS(to, Vector3(0.0f, 0.0f, -20000.0f), 0.001f, TEST_LOCATION);
789
790   END_TEST;
791 }
792
793 int UtcDaliPhysics3DAdaptorProjectPoint(void)
794 {
795   tet_infoline("Test that a point is projected into physics space");
796
797   ToolkitTestApplication application;
798   Matrix                 transform(false);
799   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
800   Uint16Pair     size(640, 480);
801   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
802
803   // distance is in physics units, not DALi units!
804   Vector3 projectedPoint = adaptor.ProjectPoint(Vector3(), -Vector3::ZAXIS, 200);
805
806   DALI_TEST_EQUALS(projectedPoint, Vector3(0.0f, 0.0f, -200.0f), 0.001f, TEST_LOCATION);
807
808   END_TEST;
809 }
810
811 int UtcDaliPhysics3DAdaptorQueue(void)
812 {
813   tet_infoline("Test that Queue and CreateSyncPoint both work");
814
815   ToolkitTestApplication application;
816   Matrix                 transform(false);
817   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
818   Uint16Pair     size(640, 480);
819   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
820   Actor          rootActor = adaptor.GetRootActor();
821   auto           scene     = application.GetScene();
822   scene.Add(rootActor);
823
824   btRigidBody* body{nullptr};
825   {
826     auto accessor            = adaptor.GetPhysicsAccessor();
827     auto bulletWorld         = accessor->GetNative().Get<btDiscreteDynamicsWorld*>();
828     body                     = CreateBody(bulletWorld);
829     Dali::Actor ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
830     auto        physicsActor = adaptor.AddActorBody(ballActor, body);
831   }
832
833   tet_infoline("Test that Queue works without accessor");
834   adaptor.Queue([body]() {
835     body->getWorldTransform().setOrigin(btVector3(100.0f, 20.0f, 20.0f));
836   });
837   adaptor.CreateSyncPoint();
838
839   application.SendNotification();
840   application.Render();
841   // Should trigger an Update
842
843   {
844     auto accessor = adaptor.GetPhysicsAccessor();
845
846     btVector3 origin = body->getWorldTransform().getOrigin();
847     DALI_TEST_EQUALS(origin.x(), 100.0f, 0.001f, TEST_LOCATION);
848     DALI_TEST_EQUALS(origin.y(), 20.0f, 0.001f, TEST_LOCATION);
849     DALI_TEST_EQUALS(origin.z(), 20.0f, 0.001f, TEST_LOCATION);
850   }
851
852   END_TEST;
853 }
854
855 int UtcDaliPhysics3DAdaptorCreateSyncPoint(void)
856 {
857   tet_infoline("Test that a delayed CreateSyncPoint delays update");
858
859   ToolkitTestApplication application;
860   Matrix                 transform(false);
861   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
862   Uint16Pair     size(640, 480);
863   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
864   Actor          rootActor = adaptor.GetRootActor();
865   auto           scene     = application.GetScene();
866   scene.Add(rootActor);
867
868   btRigidBody* body{nullptr};
869   {
870     auto accessor            = adaptor.GetPhysicsAccessor();
871     auto bulletWorld         = accessor->GetNative().Get<btDiscreteDynamicsWorld*>();
872     body                     = CreateBody(bulletWorld);
873     Dali::Actor ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
874     auto        physicsActor = adaptor.AddActorBody(ballActor, body);
875
876     tet_infoline("Test that Queue works with accessor");
877     adaptor.Queue([body]() {
878       body->getWorldTransform().setOrigin(btVector3(100.0f, 20.0f, 20.0f));
879     });
880   }
881
882   // Should trigger an Update without processing queue
883   application.SendNotification();
884   application.Render();
885
886   {
887     auto accessor = adaptor.GetPhysicsAccessor();
888
889     btVector3 origin = body->getWorldTransform().getOrigin();
890     DALI_TEST_EQUALS(origin.x(), 0.0f, 0.001f, TEST_LOCATION);
891     DALI_TEST_EQUALS(origin.y(), 0.0f, 0.001f, TEST_LOCATION);
892     DALI_TEST_EQUALS(origin.z(), 0.0f, 0.001f, TEST_LOCATION);
893   }
894
895   // Should now execute queue
896   adaptor.CreateSyncPoint();
897   application.SendNotification();
898   application.Render();
899
900   {
901     auto accessor = adaptor.GetPhysicsAccessor();
902
903     btVector3 origin = body->getWorldTransform().getOrigin();
904     DALI_TEST_EQUALS(origin.x(), 100.0f, 0.001f, TEST_LOCATION);
905     DALI_TEST_EQUALS(origin.y(), 20.0f, 0.001f, TEST_LOCATION);
906     DALI_TEST_EQUALS(origin.z(), 20.0f, 0.001f, TEST_LOCATION);
907   }
908
909   END_TEST;
910 }
911
912 int UtcDaliPhysics3DAdaptorHitTestP(void)
913 {
914   tet_infoline("Test that hit testing finds a body");
915
916   ToolkitTestApplication application;
917   Matrix                 transform(false);
918   transform.SetIdentityAndScale(Vector3(1.0f, 1.0f, 1.0f));
919   Uint16Pair     size(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT);
920   const Vector2  center(TestApplication::DEFAULT_SURFACE_WIDTH * 0.5f, TestApplication::DEFAULT_SURFACE_HEIGHT * 0.5f);
921   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
922   Actor          rootActor = adaptor.GetRootActor();
923   auto           scene     = application.GetScene();
924   scene.Add(rootActor);
925
926   {
927     auto         accessor    = adaptor.GetPhysicsAccessor(); // Prevent integration
928     auto         bulletWorld = accessor->GetNative().Get<btDiscreteDynamicsWorld*>();
929     Dali::Actor  ballActor   = Toolkit::ImageView::New(TEST_RESOURCE_DIR "/gallery-small-1.jpg");
930     btRigidBody* body        = CreateBody(bulletWorld);
931     body->getWorldTransform().setOrigin(btVector3(0.f, 0.f, 0.f));
932
933     ballActor[Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
934     ballActor[Actor::Property::ANCHOR_POINT]  = AnchorPoint::CENTER;
935
936     auto physicsActor = adaptor.AddActorBody(ballActor, body);
937   }
938   Test::WaitForEventThreadTrigger(1);
939
940   // Should trigger an Update without processing queue
941   application.SendNotification();
942   application.Render();
943
944   Vector3 origin, direction;
945   Dali::HitTestAlgorithm::BuildPickingRay(scene.GetRenderTaskList().GetTask(0), center, origin, direction);
946   Vector3 from, to;
947   adaptor.BuildPickingRay(origin, direction, from, to); // Hit test centre of screen
948
949   {
950     auto      accessor = adaptor.GetPhysicsAccessor();
951     Vector3   localPivot;
952     float     distanceFromCamera;
953     Dali::Any nullFilter;
954     auto      body = accessor->HitTest(from, to, nullFilter, localPivot, distanceFromCamera);
955
956     DALI_TEST_CHECK(!body.Empty());
957   }
958
959   END_TEST;
960 }
961
962 // todo:
963 // Hit Test
964 // PhysicsDebugRenderer.... Elide?!