Adding chipmunk implementation for physics adaptor
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-scene3d-internal / utc-Dali-Gltf2LoaderImpl.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
18 // Enable debug log for test coverage
19 #define DEBUG_ENABLED 1
20
21 #include <dali-scene3d/internal/loader/gltf2-loader-impl.h>
22 #include <dali-scene3d/public-api/loader/load-result.h>
23 #include <dali-scene3d/public-api/loader/resource-bundle.h>
24 #include <dali-scene3d/public-api/loader/scene-definition.h>
25 #include <dali-scene3d/public-api/loader/shader-manager.h>
26 #include <dali-test-suite-utils.h>
27 #include <string_view>
28
29 using namespace Dali;
30 using namespace Dali::Scene3D::Loader;
31
32 #define DALI_TEST_THROW(expression, exception, predicate) \
33   {                                                       \
34     bool daliTestThrowSuccess__ = false;                  \
35     try                                                   \
36     {                                                     \
37       do                                                  \
38       {                                                   \
39         expression;                                       \
40       } while(0);                                         \
41       printf("No exception was thrown.\n");               \
42     }                                                     \
43     catch(std::decay<exception>::type & ex)               \
44     {                                                     \
45       daliTestThrowSuccess__ = predicate(ex);             \
46     }                                                     \
47     catch(...)                                            \
48     {                                                     \
49       printf("Wrong type of exception thrown.\n");        \
50     }                                                     \
51     DALI_TEST_CHECK(daliTestThrowSuccess__);              \
52   }
53
54 namespace
55 {
56 struct Context
57 {
58   ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type)
59   {
60     return TEST_RESOURCE_DIR "/";
61   };
62
63   ResourceBundle  resources;
64   SceneDefinition scene;
65   SceneMetadata   metaData;
66
67   std::vector<AnimationDefinition>      animations;
68   std::vector<AnimationGroupDefinition> animationGroups;
69   std::vector<CameraParameters>         cameras;
70   std::vector<LightParameters>          lights;
71
72   LoadResult loadResult{
73     resources,
74     scene,
75     metaData,
76     animations,
77     animationGroups,
78     cameras,
79     lights};
80
81   Dali::Scene3D::Loader::Internal::Gltf2LoaderImpl loader;
82 };
83
84 struct ExceptionMessageStartsWith
85 {
86   const std::string_view expected;
87
88   bool operator()(const std::runtime_error& e)
89   {
90     const bool success = (0 == strncmp(e.what(), expected.data(), expected.size()));
91     if(!success)
92     {
93       printf("Expected: %s, got: %s.\n", expected.data(), e.what());
94     }
95     return success;
96   }
97 };
98
99 } // namespace
100
101 int UtcDaliGltfLoaderFailedToLoad(void)
102 {
103   Context ctx;
104
105   DALI_TEST_EQUAL(ctx.loader.LoadModel("non-existent.gltf", ctx.loadResult), false);
106
107   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
108   DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
109
110   DALI_TEST_EQUAL(0, ctx.resources.mEnvironmentMaps.size());
111   DALI_TEST_EQUAL(0, ctx.resources.mMaterials.size());
112   DALI_TEST_EQUAL(0, ctx.resources.mMeshes.size());
113   DALI_TEST_EQUAL(0, ctx.resources.mShaders.size());
114   DALI_TEST_EQUAL(0, ctx.resources.mSkeletons.size());
115
116   DALI_TEST_EQUAL(0, ctx.cameras.size());
117   DALI_TEST_EQUAL(0, ctx.lights.size());
118   DALI_TEST_EQUAL(0, ctx.animations.size());
119   DALI_TEST_EQUAL(0, ctx.animationGroups.size());
120
121   END_TEST;
122 }
123
124 int UtcDaliGltfLoaderFailedToParse(void)
125 {
126   Context ctx;
127
128   DALI_TEST_EQUAL(ctx.loader.LoadModel(TEST_RESOURCE_DIR "/invalid.gltf", ctx.loadResult), false);
129
130   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
131   DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
132
133   DALI_TEST_EQUAL(0, ctx.resources.mEnvironmentMaps.size());
134   DALI_TEST_EQUAL(0, ctx.resources.mMaterials.size());
135   DALI_TEST_EQUAL(0, ctx.resources.mMeshes.size());
136   DALI_TEST_EQUAL(0, ctx.resources.mSkeletons.size());
137
138   DALI_TEST_EQUAL(0, ctx.cameras.size());
139   DALI_TEST_EQUAL(0, ctx.lights.size());
140   DALI_TEST_EQUAL(0, ctx.animations.size());
141   DALI_TEST_EQUAL(0, ctx.animationGroups.size());
142
143   END_TEST;
144 }
145
146 int UtcDaliGltfLoaderSuccess1(void)
147 {
148   Context ctx;
149
150   LoadSceneMetadata(TEST_RESOURCE_DIR "/AnimatedCube.metadata", ctx.metaData);
151
152   std::unordered_map<std::string, ImageMetadata> imageMetadataGroundTruth;
153   imageMetadataGroundTruth["AnimatedCube_BaseColor.png"]         = ImageMetadata{ImageDimensions(256, 256), Dali::SamplingMode::BOX_THEN_NEAREST};
154   imageMetadataGroundTruth["AnimatedCube_MetallicRoughness.png"] = ImageMetadata{ImageDimensions(256, 256), Dali::SamplingMode::NEAREST};
155
156   auto metaData = ctx.metaData.mImageMetadata.begin();
157   for(auto& groundTruth : imageMetadataGroundTruth)
158   {
159     DALI_TEST_EQUAL(groundTruth.first, metaData->first);
160     DALI_TEST_EQUAL(groundTruth.second.mMinSize, metaData->second.mMinSize);
161     DALI_TEST_EQUAL(groundTruth.second.mSamplingMode, metaData->second.mSamplingMode);
162     ++metaData;
163   }
164
165   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AnimatedCube.gltf", ctx.loadResult);
166
167   DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
168   DALI_TEST_EQUAL(9u, ctx.scene.GetNodeCount());
169
170   // Default envmap is used
171   DALI_TEST_EQUAL(1u, ctx.resources.mEnvironmentMaps.size());
172
173   TestApplication app;
174
175   Customization::Choices choices;
176   for(auto iRoot : ctx.scene.GetRoots())
177   {
178     auto resourceRefs = ctx.resources.CreateRefCounter();
179     ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs);
180     ctx.resources.mReferenceCounts = std::move(resourceRefs);
181     ctx.resources.CountEnvironmentReferences();
182     ctx.resources.LoadResources(ctx.pathProvider);
183   }
184
185   auto& materials = ctx.resources.mMaterials;
186   DALI_TEST_EQUAL(2u, materials.size());
187   const MaterialDefinition materialGroundTruth[]{
188     {
189       nullptr,
190       MaterialDefinition::ALBEDO | MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
191         MaterialDefinition::NORMAL | MaterialDefinition::SPECULAR | MaterialDefinition::SPECULAR_COLOR |
192         MaterialDefinition::GLTF_CHANNELS | (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
193       0,
194       Color::WHITE,
195       1.f,
196       0.f,
197       Vector4(1.000, 0.766, 0.336, 1.0),
198       1.f,
199       1.f,
200       Vector3(0.2, 0.1, 0.0),
201       1.0f,
202       0.0f,
203       0.5f,
204       Vector3(0, 0, 1),
205       true,
206       false,
207       true,
208       false,
209       Scene3D::Material::AlphaModeType::MASK,
210       true,
211       true,
212       {
213         {
214           MaterialDefinition::ALBEDO,
215           {
216             "AnimatedCube_BaseColor.png",
217             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
218             ImageDimensions(256, 256),
219             SamplingMode::BOX_THEN_NEAREST,
220           },
221         },
222         {
223           MaterialDefinition::NORMAL,
224           {
225             "AnimatedCube_BaseColor.png",
226             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
227             ImageDimensions(256, 256),
228             SamplingMode::BOX_THEN_NEAREST,
229           },
230         },
231         {
232           MaterialDefinition::OCCLUSION,
233           {
234             "AnimatedCube_BaseColor.png",
235             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
236             ImageDimensions(256, 256),
237             SamplingMode::BOX_THEN_NEAREST,
238           },
239         },
240         {
241           MaterialDefinition::EMISSIVE,
242           {
243             "AnimatedCube_BaseColor.png",
244             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
245             ImageDimensions(256, 256),
246             SamplingMode::BOX_THEN_NEAREST,
247           },
248         },
249         {
250           MaterialDefinition::SPECULAR,
251           {
252             "AnimatedCube_BaseColor.png",
253             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
254             ImageDimensions(256, 256),
255             SamplingMode::BOX_THEN_NEAREST,
256           },
257         },
258         {
259           MaterialDefinition::SPECULAR_COLOR,
260           {
261             "AnimatedCube_BaseColor.png",
262             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
263             ImageDimensions(256, 256),
264             SamplingMode::BOX_THEN_NEAREST,
265           },
266         },
267       },
268       nullptr
269     },
270     {
271       nullptr,
272       MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
273         MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION | MaterialDefinition::NORMAL |
274         MaterialDefinition::GLTF_CHANNELS,
275       0,
276       Color::WHITE,
277       1.f,
278       0.f,
279       Vector4(1.000, 0.766, 0.336, 1.0),
280       1.f,
281       1.f,
282       Vector3(0.2, 0.1, 0.0),
283       -1.0f,
284       0.04f,
285       1.0f,
286       Vector3::ONE,
287       true,
288       true,
289       true,
290       false,
291       Scene3D::Material::AlphaModeType::OPAQUE,
292       true,
293       false,
294       {
295         {
296           MaterialDefinition::ALBEDO,
297           {
298             "AnimatedCube_BaseColor.png",
299             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
300             ImageDimensions(256, 256),
301             SamplingMode::BOX_THEN_NEAREST,
302           },
303         },
304         {
305           MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS,
306           {
307             "AnimatedCube_MetallicRoughness.png",
308             SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT),
309             ImageDimensions(256, 256),
310             SamplingMode::NEAREST,
311           },
312         },
313         {
314           MaterialDefinition::NORMAL,
315           {
316             "AnimatedCube_BaseColor.png",
317             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
318             ImageDimensions(256, 256),
319             SamplingMode::BOX_THEN_NEAREST,
320           },
321         },
322         {
323           MaterialDefinition::OCCLUSION,
324           {
325             "AnimatedCube_BaseColor.png",
326             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
327             ImageDimensions(256, 256),
328             SamplingMode::BOX_THEN_NEAREST,
329           },
330         },
331         {
332           MaterialDefinition::EMISSIVE,
333           {
334             "AnimatedCube_BaseColor.png",
335             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
336             ImageDimensions(256, 256),
337             SamplingMode::BOX_THEN_NEAREST,
338           },
339         },
340       },
341       nullptr,
342     },
343   };
344
345   auto iMaterial = materials.begin();
346   auto iMetadata = ctx.metaData.mImageMetadata.begin();
347   for(auto& m : materialGroundTruth)
348   {
349     printf("material %ld\n", iMaterial - materials.begin());
350     auto& md = iMaterial->first;
351     DALI_TEST_EQUAL(md.mFlags, m.mFlags);
352     DALI_TEST_EQUAL(md.mEnvironmentIdx, m.mEnvironmentIdx);
353     DALI_TEST_EQUAL(md.mColor, m.mColor);
354     DALI_TEST_EQUAL(md.mMetallic, m.mMetallic);
355     DALI_TEST_EQUAL(md.mRoughness, m.mRoughness);
356     DALI_TEST_EQUAL(md.mBaseColorFactor, m.mBaseColorFactor);
357     DALI_TEST_EQUAL(md.mNormalScale, m.mNormalScale);
358     DALI_TEST_EQUAL(md.mOcclusionStrength, m.mOcclusionStrength);
359     DALI_TEST_EQUAL(md.mEmissiveFactor, m.mEmissiveFactor);
360     DALI_TEST_EQUAL(md.mIor, m.mIor);
361     DALI_TEST_EQUAL(md.mDielectricSpecular, m.mDielectricSpecular);
362     DALI_TEST_EQUAL(md.mSpecularFactor, m.mSpecularFactor);
363     DALI_TEST_EQUAL(md.mSpecularColorFactor, m.mSpecularColorFactor);
364     DALI_TEST_EQUAL(md.mNeedAlbedoTexture, m.mNeedAlbedoTexture);
365     DALI_TEST_EQUAL(md.mNeedMetallicRoughnessTexture, m.mNeedMetallicRoughnessTexture);
366     DALI_TEST_EQUAL(md.mNeedNormalTexture, m.mNeedNormalTexture);
367     DALI_TEST_EQUAL(md.mAlphaModeType, m.mAlphaModeType);
368     DALI_TEST_EQUAL(md.mIsOpaque, m.mIsOpaque);
369     DALI_TEST_EQUAL(md.mIsMask, m.mIsMask);
370
371     DALI_TEST_EQUAL(md.mTextureStages.size(), m.mTextureStages.size());
372     auto iTexture = md.mTextureStages.begin();
373     for(auto& ts : m.mTextureStages)
374     {
375       printf("texture %ld\n", iTexture - md.mTextureStages.begin());
376       DALI_TEST_EQUAL(iTexture->mSemantic, ts.mSemantic);
377       DALI_TEST_EQUAL(iTexture->mTexture.mImageUri, ts.mTexture.mImageUri);
378       DALI_TEST_EQUAL(uint32_t(iTexture->mTexture.mSamplerFlags), uint32_t(ts.mTexture.mSamplerFlags)); // don't interpret it as a character
379       DALI_TEST_EQUAL(iTexture->mTexture.mMinImageDimensions, ts.mTexture.mMinImageDimensions);
380       DALI_TEST_EQUAL(iTexture->mTexture.mSamplingMode, ts.mTexture.mSamplingMode);
381
382       ++iTexture;
383     }
384     ++iMaterial;
385     ++iMetadata;
386   }
387
388   auto& meshes = ctx.resources.mMeshes;
389   DALI_TEST_EQUAL(2u, meshes.size());
390
391   using Blob     = MeshDefinition::Blob;
392   using Accessor = MeshDefinition::Accessor;
393   const MeshDefinition meshGroundTruth[]{
394     {
395       nullptr,
396       0,
397       Geometry::TRIANGLES,
398       "AnimatedCube.bin",
399       Accessor{Blob{0, 0}, {}},
400       Accessor{Blob{0, 0}, {}},
401       Accessor{Blob{0, 0}, {}},
402       Accessor{Blob{0, 0}, {}},
403       Accessor{Blob{0, 0}, {}},
404       Accessor{Blob{0, 0}, {}},
405     },
406     {
407       nullptr,
408       0,
409       Geometry::TRIANGLES,
410       "AnimatedCube.bin",
411       Accessor{Blob{0, 0}, {}},
412       Accessor{Blob{0, 0}, {}},
413       Accessor{Blob{0, 0}, {}},
414       Accessor{Blob{0, 0}, {}},
415       Accessor{Blob{0, 0}, {}},
416       Accessor{Blob{0, 0}, {}},
417     },
418   };
419
420   auto iMesh = meshes.begin();
421   for(auto& m : meshGroundTruth)
422   {
423     printf("mesh %ld\n", iMesh - meshes.begin());
424
425     auto& md = iMesh->first;
426     DALI_TEST_EQUAL(md.mFlags, m.mFlags);
427     DALI_TEST_EQUAL(md.mPrimitiveType, m.mPrimitiveType);
428     for(auto mp : {
429           &MeshDefinition::mIndices,
430           &MeshDefinition::mPositions,
431           &MeshDefinition::mNormals,
432           &MeshDefinition::mTexCoords,
433           &MeshDefinition::mColors,
434           &MeshDefinition::mTangents,
435           &MeshDefinition::mJoints0,
436           &MeshDefinition::mWeights0})
437     {
438       DALI_TEST_EQUAL((md.*mp).IsDefined(), (m.*mp).IsDefined());
439       DALI_TEST_EQUAL((md.*mp).mBlob.IsDefined(), (m.*mp).mBlob.IsDefined());
440     }
441
442     DALI_TEST_EQUAL(md.mBlendShapeHeader.IsDefined(), m.mBlendShapeHeader.IsDefined());
443
444     ++iMesh;
445   }
446
447   DALI_TEST_EQUAL(0u, ctx.resources.mSkeletons.size());
448
449   DALI_TEST_EQUAL(6u, ctx.cameras.size());
450   DALI_TEST_EQUAL(0u, ctx.lights.size());
451   DALI_TEST_EQUAL(1u, ctx.animations.size());
452   DALI_TEST_EQUAL(0u, ctx.animationGroups.size());
453
454   END_TEST;
455 }
456
457 int UtcDaliGltfLoaderSuccess2(void)
458 {
459   Context                 ctx;
460
461   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AnimatedCubeStride.gltf", ctx.loadResult);
462
463   DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
464   DALI_TEST_EQUAL(1u, ctx.scene.GetNodeCount());
465
466   TestApplication app;
467
468   Customization::Choices choices;
469   for(auto iRoot : ctx.scene.GetRoots())
470   {
471     auto resourceRefs = ctx.resources.CreateRefCounter();
472     ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs);
473     ctx.resources.mReferenceCounts = std::move(resourceRefs);
474     ctx.resources.LoadResources(ctx.pathProvider);
475   }
476
477   DALI_TEST_EQUAL(true, ctx.resources.mMeshes[0u].first.mPositions.IsDefined());
478   DALI_TEST_EQUAL(432, ctx.resources.mMeshes[0u].first.mPositions.mBlob.mLength);
479
480   END_TEST;
481 }
482
483 int UtcDaliGltfLoaderSuccessShort(void)
484 {
485   TestApplication app;
486
487   const std::string resourcePath = TEST_RESOURCE_DIR "/";
488   auto              pathProvider = [resourcePath](ResourceType::Value)
489   {
490     return resourcePath;
491   };
492
493   Customization::Choices choices;
494   for(auto modelName : {
495         "2CylinderEngine",
496         "AnimatedMorphCube",
497         "AnimatedMorphCubeAnimateNonZeroFrame",
498         "AnimatedMorphSphere",
499         "AnimatedTriangle",
500         "BoxAnimated",
501         "CesiumMan",
502         "CesiumMilkTruck",
503         "EnvironmentTest",
504         "MetalRoughSpheres",
505         "MorphPrimitivesTest",
506         "MRendererTest",
507         "SimpleSparseAccessor",
508         "AnimatedCube",
509       })
510   {
511     Context ctx;
512
513     auto& resources = ctx.resources;
514     resources.mEnvironmentMaps.push_back({});
515
516     printf("%s\n", modelName);
517     ctx.loader.LoadModel(resourcePath + modelName + ".gltf", ctx.loadResult);
518     DALI_TEST_CHECK(ctx.scene.GetNodeCount() > 0);
519
520     auto& scene = ctx.scene;
521     for(auto iRoot : scene.GetRoots())
522     {
523       struct Visitor : NodeDefinition::IVisitor
524       {
525         struct ResourceReceiver : IResourceReceiver
526         {
527           std::vector<bool> mCounts;
528
529           void Register(ResourceType::Value type, Index id) override
530           {
531             if(type == ResourceType::Mesh)
532             {
533               mCounts[id] = true;
534             }
535           }
536         } receiver;
537
538         void Start(NodeDefinition& n) override
539         {
540           for(auto& renderable : n.mRenderables)
541           {
542             renderable->RegisterResources(receiver);
543           }
544         }
545
546         void Finish(NodeDefinition& n) override
547         {
548         }
549       } visitor;
550       visitor.receiver.mCounts.resize(resources.mMeshes.size(), false);
551
552       scene.Visit(iRoot, choices, visitor);
553       for(uint32_t i0 = 0, i1 = resources.mMeshes.size(); i0 < i1; ++i0)
554       {
555         if(visitor.receiver.mCounts[i0])
556         {
557           auto raw = resources.mMeshes[i0].first.LoadRaw(resourcePath, resources.mBuffers);
558           DALI_TEST_CHECK(!raw.mAttribs.empty());
559
560           resources.mMeshes[i0].second = resources.mMeshes[i0].first.Load(std::move(raw));
561           DALI_TEST_CHECK(resources.mMeshes[i0].second.geometry);
562         }
563       }
564     }
565   }
566
567   END_TEST;
568 }
569
570 int UtcDaliGltfLoaderMRendererTest(void)
571 {
572   Context ctx;
573   auto& resources = ctx.resources;
574
575   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/MRendererTest.gltf", ctx.loadResult);
576
577   auto& scene = ctx.scene;
578   auto& roots = scene.GetRoots();
579   DALI_TEST_EQUAL(roots.size(), 1u);
580   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "RootNode");
581   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mScale, Vector3(1.0f, 1.0f, 1.0f));
582
583   DALI_TEST_EQUAL(scene.GetNodeCount(), 1u);
584
585   Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
586   ViewProjection viewProjection;
587   Transforms     xforms{
588     MatrixStack{},
589     viewProjection};
590   NodeDefinition::CreateParams nodeParams{
591     resources,
592     xforms,
593     shaderManager,
594   };
595
596   Customization::Choices choices;
597
598   TestApplication app;
599
600   Actor root = Actor::New();
601   SetActorCentered(root);
602   for(auto iRoot : roots)
603   {
604     auto resourceRefs = resources.CreateRefCounter();
605     scene.CountResourceRefs(iRoot, choices, resourceRefs);
606     ctx.resources.mReferenceCounts = std::move(resourceRefs);
607     ctx.resources.CountEnvironmentReferences();
608     ctx.resources.LoadResources(ctx.pathProvider);
609     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
610     {
611       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
612       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
613       root.Add(actor);
614     }
615   }
616
617   DALI_TEST_EQUAL(root.GetChildCount(), 1u);
618   Actor child = root.GetChildAt(0);
619
620   DALI_TEST_EQUAL(child.GetProperty(Actor::Property::NAME).Get<std::string>(), "RootNode");
621   DALI_TEST_EQUAL(child.GetProperty(Actor::Property::SCALE).Get<Vector3>(), Vector3(1.0f, 1.0f, 1.0f));
622   DALI_TEST_EQUAL(child.GetRendererCount(), 1u);
623   DALI_TEST_EQUAL(child.GetRendererAt(0).GetTextures().GetTextureCount(), 4u);
624
625   DALI_TEST_EQUAL(child.GetRendererCount(), 1u);
626   DALI_TEST_EQUAL(child.GetRendererAt(0u).GetProperty<decltype(BlendMode::ON)>(Renderer::Property::BLEND_MODE), BlendMode::ON);
627
628   END_TEST;
629 }
630
631 int UtcDaliGltfLoaderAnimationLoadingTest(void)
632 {
633   TestApplication app;
634   Context ctx;
635
636   auto& resources = ctx.resources;
637
638   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/CesiumMan_e.gltf", ctx.loadResult);
639
640   auto& scene = ctx.scene;
641   auto& roots = scene.GetRoots();
642   DALI_TEST_EQUAL(roots.size(), 1u);
643
644   Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
645   ViewProjection viewProjection;
646   Transforms     xforms{
647     MatrixStack{},
648     viewProjection};
649   NodeDefinition::CreateParams nodeParams{
650     resources,
651     xforms,
652     shaderManager,
653   };
654
655   Customization::Choices choices;
656
657   Actor root = Actor::New();
658   SetActorCentered(root);
659   for(auto iRoot : roots)
660   {
661     auto resourceRefs = resources.CreateRefCounter();
662     scene.CountResourceRefs(iRoot, choices, resourceRefs);
663     resources.mReferenceCounts = std::move(resourceRefs);
664     resources.CountEnvironmentReferences();
665     resources.LoadResources(ctx.pathProvider);
666     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
667     {
668       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
669       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
670       root.Add(actor);
671     }
672   }
673
674   DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions.size(), 1u);
675   DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions[0].GetPropertyCount(), 57u);
676
677   uint32_t id = ctx.loadResult.mScene.GetNode(ctx.loadResult.mAnimationDefinitions[0].GetPropertyAt(0).mNodeIndex)->mNodeId;
678   DALI_TEST_EQUAL(id, root.FindChildByName("Skeleton_torso_joint_1").GetProperty<int32_t>(Dali::Actor::Property::ID));
679
680   END_TEST;
681 }
682
683 int UtcDaliGltfLoaderImageFromBufferView(void)
684 {
685   Context ctx;
686
687   auto& resources = ctx.resources;
688
689   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/EnvironmentTest_b.gltf", ctx.loadResult);
690
691   auto& scene = ctx.scene;
692   auto& roots = scene.GetRoots();
693   DALI_TEST_EQUAL(roots.size(), 1u);
694
695   Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
696   ViewProjection viewProjection;
697   Transforms     xforms{
698     MatrixStack{},
699     viewProjection};
700   NodeDefinition::CreateParams nodeParams{
701     resources,
702     xforms,
703     shaderManager,
704   };
705
706   Customization::Choices choices;
707
708   TestApplication app;
709
710   Actor root = Actor::New();
711   SetActorCentered(root);
712   for(auto iRoot : roots)
713   {
714     auto resourceRefs = resources.CreateRefCounter();
715     scene.CountResourceRefs(iRoot, choices, resourceRefs);
716     resources.mReferenceCounts = std::move(resourceRefs);
717     resources.CountEnvironmentReferences();
718     resources.LoadResources(ctx.pathProvider);
719     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
720     {
721       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
722       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
723       root.Add(actor);
724     }
725   }
726
727   DALI_TEST_CHECK(resources.mMaterials[0].second.GetTextureCount() > 1);
728   DALI_TEST_EQUAL(resources.mMaterials[0].second.GetTexture(0).GetWidth(), 256);
729   DALI_TEST_EQUAL(resources.mMaterials[0].second.GetTexture(0).GetHeight(), 256);
730
731   END_TEST;
732 }
733
734 int UtcDaliGltfLoaderUint8Indices(void)
735 {
736   Context ctx;
737
738   auto& resources = ctx.resources;
739
740   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AlphaBlendModeTest.gltf", ctx.loadResult);
741
742   auto& scene = ctx.scene;
743   auto& roots = scene.GetRoots();
744   DALI_TEST_EQUAL(roots.size(), 1u);
745
746   Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
747   ViewProjection viewProjection;
748   Transforms     xforms{
749     MatrixStack{},
750     viewProjection};
751   NodeDefinition::CreateParams nodeParams{
752     resources,
753     xforms,
754     shaderManager,
755   };
756
757   Customization::Choices choices;
758
759   TestApplication app;
760
761   Actor root = Actor::New();
762   SetActorCentered(root);
763   for(auto iRoot : roots)
764   {
765     auto resourceRefs = resources.CreateRefCounter();
766     scene.CountResourceRefs(iRoot, choices, resourceRefs);
767     resources.mReferenceCounts = std::move(resourceRefs);
768     resources.CountEnvironmentReferences();
769     resources.LoadResources(ctx.pathProvider);
770     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
771     {
772       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
773       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
774       root.Add(actor);
775     }
776   }
777
778   DALI_TEST_CHECK(root.FindChildByName("Bed"));
779   DALI_TEST_CHECK(root.FindChildByName("DecalBlend"));
780   DALI_TEST_CHECK(root.FindChildByName("DecalOpaque"));
781
782   END_TEST;
783 }