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