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