Use c-style string when webview loads contents.
[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-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   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   ShaderDefinitionFactory sdf;
129   sdf.SetResources(ctx.resources);
130
131   DALI_TEST_EQUAL(ctx.loader.LoadModel(TEST_RESOURCE_DIR "/invalid.gltf", ctx.loadResult), false);
132
133   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
134   DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
135
136   DALI_TEST_EQUAL(0, ctx.resources.mEnvironmentMaps.size());
137   DALI_TEST_EQUAL(0, ctx.resources.mMaterials.size());
138   DALI_TEST_EQUAL(0, ctx.resources.mMeshes.size());
139   DALI_TEST_EQUAL(0, ctx.resources.mShaders.size());
140   DALI_TEST_EQUAL(0, ctx.resources.mSkeletons.size());
141
142   DALI_TEST_EQUAL(0, ctx.cameras.size());
143   DALI_TEST_EQUAL(0, ctx.lights.size());
144   DALI_TEST_EQUAL(0, ctx.animations.size());
145   DALI_TEST_EQUAL(0, ctx.animationGroups.size());
146
147   END_TEST;
148 }
149
150 int UtcDaliGltfLoaderSuccess1(void)
151 {
152   Context ctx;
153
154   LoadSceneMetadata(TEST_RESOURCE_DIR "/AnimatedCube.metadata", ctx.metaData);
155
156   std::unordered_map<std::string, ImageMetadata> imageMetadataGroundTruth;
157   imageMetadataGroundTruth["AnimatedCube_BaseColor.png"]         = ImageMetadata{ImageDimensions(256, 256), Dali::SamplingMode::BOX_THEN_NEAREST};
158   imageMetadataGroundTruth["AnimatedCube_MetallicRoughness.png"] = ImageMetadata{ImageDimensions(256, 256), Dali::SamplingMode::NEAREST};
159
160   auto metaData = ctx.metaData.mImageMetadata.begin();
161   for(auto& groundTruth : imageMetadataGroundTruth)
162   {
163     DALI_TEST_EQUAL(groundTruth.first, metaData->first);
164     DALI_TEST_EQUAL(groundTruth.second.mMinSize, metaData->second.mMinSize);
165     DALI_TEST_EQUAL(groundTruth.second.mSamplingMode, metaData->second.mSamplingMode);
166     ++metaData;
167   }
168
169   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AnimatedCube.gltf", ctx.loadResult);
170
171   DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
172   DALI_TEST_EQUAL(9u, ctx.scene.GetNodeCount());
173
174   // Default envmap is used
175   DALI_TEST_EQUAL(1u, ctx.resources.mEnvironmentMaps.size());
176
177   TestApplication app;
178
179   Customization::Choices choices;
180   for(auto iRoot : ctx.scene.GetRoots())
181   {
182     auto resourceRefs = ctx.resources.CreateRefCounter();
183     ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs);
184     ctx.resources.mReferenceCounts = std::move(resourceRefs);
185     ctx.resources.CountEnvironmentReferences();
186     ctx.resources.LoadResources(ctx.pathProvider);
187   }
188
189   auto& materials = ctx.resources.mMaterials;
190   DALI_TEST_EQUAL(2u, materials.size());
191   const MaterialDefinition materialGroundTruth[]{
192     {
193       nullptr,
194       MaterialDefinition::ALBEDO | MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
195         MaterialDefinition::NORMAL | MaterialDefinition::SPECULAR | MaterialDefinition::SPECULAR_COLOR |
196         (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
197       0,
198       Color::WHITE,
199       1.f,
200       0.f,
201       Vector4(1.000, 0.766, 0.336, 1.0),
202       1.f,
203       1.f,
204       Vector3(0.2, 0.1, 0.0),
205       0.0f,
206       0.5f,
207       Vector3(0, 0, 1),
208       true,
209       false,
210       true,
211       false,
212       true,
213       true,
214       {
215         {
216           MaterialDefinition::ALBEDO,
217           {
218             "AnimatedCube_BaseColor.png",
219             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
220             ImageDimensions(256, 256),
221             SamplingMode::BOX_THEN_NEAREST,
222           },
223         },
224         {
225           MaterialDefinition::NORMAL,
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::OCCLUSION,
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::EMISSIVE,
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::SPECULAR,
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_COLOR,
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     },
271     {
272       nullptr,
273       MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
274         MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION | MaterialDefinition::NORMAL |
275         MaterialDefinition::GLTF_CHANNELS,
276       0,
277       Color::WHITE,
278       1.f,
279       0.f,
280       Vector4(1.000, 0.766, 0.336, 1.0),
281       1.f,
282       1.f,
283       Vector3(0.2, 0.1, 0.0),
284       0.04f,
285       1.0f,
286       Vector3::ONE,
287       true,
288       true,
289       true,
290       false,
291       true,
292       false,
293       {
294         {
295           MaterialDefinition::ALBEDO,
296           {
297             "AnimatedCube_BaseColor.png",
298             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
299             ImageDimensions(256, 256),
300             SamplingMode::BOX_THEN_NEAREST,
301           },
302         },
303         {
304           MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
305           {
306             "AnimatedCube_MetallicRoughness.png",
307             SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT),
308             ImageDimensions(256, 256),
309             SamplingMode::NEAREST,
310           },
311         },
312         {
313           MaterialDefinition::NORMAL,
314           {
315             "AnimatedCube_BaseColor.png",
316             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
317             ImageDimensions(256, 256),
318             SamplingMode::BOX_THEN_NEAREST,
319           },
320         },
321         {
322           MaterialDefinition::OCCLUSION,
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::EMISSIVE,
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     },
341   };
342
343   auto iMaterial = materials.begin();
344   auto iMetadata = ctx.metaData.mImageMetadata.begin();
345   for(auto& m : materialGroundTruth)
346   {
347     printf("material %ld\n", iMaterial - materials.begin());
348     auto& md = iMaterial->first;
349     DALI_TEST_EQUAL(md.mFlags, m.mFlags);
350     DALI_TEST_EQUAL(md.mEnvironmentIdx, m.mEnvironmentIdx);
351     DALI_TEST_EQUAL(md.mColor, m.mColor);
352     DALI_TEST_EQUAL(md.mMetallic, m.mMetallic);
353     DALI_TEST_EQUAL(md.mRoughness, m.mRoughness);
354     DALI_TEST_EQUAL(md.mBaseColorFactor, m.mBaseColorFactor);
355     DALI_TEST_EQUAL(md.mNormalScale, m.mNormalScale);
356     DALI_TEST_EQUAL(md.mOcclusionStrength, m.mOcclusionStrength);
357     DALI_TEST_EQUAL(md.mEmissiveFactor, m.mEmissiveFactor);
358     DALI_TEST_EQUAL(md.mDielectricSpecular, m.mDielectricSpecular);
359     DALI_TEST_EQUAL(md.mSpecularFactor, m.mSpecularFactor);
360     DALI_TEST_EQUAL(md.mSpecularColorFactor, m.mSpecularColorFactor);
361     DALI_TEST_EQUAL(md.mNeedAlbedoTexture, m.mNeedAlbedoTexture);
362     DALI_TEST_EQUAL(md.mNeedMetallicRoughnessTexture, m.mNeedMetallicRoughnessTexture);
363     DALI_TEST_EQUAL(md.mNeedNormalTexture, m.mNeedNormalTexture);
364     DALI_TEST_EQUAL(md.mIsOpaque, m.mIsOpaque);
365     DALI_TEST_EQUAL(md.mIsMask, m.mIsMask);
366
367     DALI_TEST_EQUAL(md.mTextureStages.size(), m.mTextureStages.size());
368     auto iTexture = md.mTextureStages.begin();
369     for(auto& ts : m.mTextureStages)
370     {
371       printf("texture %ld\n", iTexture - md.mTextureStages.begin());
372       DALI_TEST_EQUAL(iTexture->mSemantic, ts.mSemantic);
373       DALI_TEST_EQUAL(iTexture->mTexture.mImageUri, ts.mTexture.mImageUri);
374       DALI_TEST_EQUAL(uint32_t(iTexture->mTexture.mSamplerFlags), uint32_t(ts.mTexture.mSamplerFlags)); // don't interpret it as a character
375       DALI_TEST_EQUAL(iTexture->mTexture.mMinImageDimensions, ts.mTexture.mMinImageDimensions);
376       DALI_TEST_EQUAL(iTexture->mTexture.mSamplingMode, ts.mTexture.mSamplingMode);
377
378       ++iTexture;
379     }
380     ++iMaterial;
381     ++iMetadata;
382   }
383
384   auto& meshes = ctx.resources.mMeshes;
385   DALI_TEST_EQUAL(2u, meshes.size());
386
387   using Blob     = MeshDefinition::Blob;
388   using Accessor = MeshDefinition::Accessor;
389   const MeshDefinition meshGroundTruth[]{
390     {
391       nullptr,
392       0,
393       Geometry::TRIANGLES,
394       "AnimatedCube.bin",
395       Accessor{Blob{0, 0}, {}},
396       Accessor{Blob{0, 0}, {}},
397       Accessor{Blob{0, 0}, {}},
398       Accessor{Blob{0, 0}, {}},
399       Accessor{Blob{0, 0}, {}},
400       Accessor{Blob{0, 0}, {}},
401     },
402     {
403       nullptr,
404       0,
405       Geometry::TRIANGLES,
406       "AnimatedCube.bin",
407       Accessor{Blob{0, 0}, {}},
408       Accessor{Blob{0, 0}, {}},
409       Accessor{Blob{0, 0}, {}},
410       Accessor{Blob{0, 0}, {}},
411       Accessor{Blob{0, 0}, {}},
412       Accessor{Blob{0, 0}, {}},
413     },
414   };
415
416   auto iMesh = meshes.begin();
417   for(auto& m : meshGroundTruth)
418   {
419     printf("mesh %ld\n", iMesh - meshes.begin());
420
421     auto& md = iMesh->first;
422     DALI_TEST_EQUAL(md.mFlags, m.mFlags);
423     DALI_TEST_EQUAL(md.mPrimitiveType, m.mPrimitiveType);
424     for(auto mp : {
425           &MeshDefinition::mIndices,
426           &MeshDefinition::mPositions,
427           &MeshDefinition::mNormals,
428           &MeshDefinition::mTexCoords,
429           &MeshDefinition::mColors,
430           &MeshDefinition::mTangents,
431           &MeshDefinition::mJoints0,
432           &MeshDefinition::mWeights0})
433     {
434       DALI_TEST_EQUAL((md.*mp).IsDefined(), (m.*mp).IsDefined());
435       DALI_TEST_EQUAL((md.*mp).mBlob.IsDefined(), (m.*mp).mBlob.IsDefined());
436     }
437
438     DALI_TEST_EQUAL(md.mBlendShapeHeader.IsDefined(), m.mBlendShapeHeader.IsDefined());
439
440     ++iMesh;
441   }
442
443   DALI_TEST_EQUAL(2u, ctx.resources.mShaders.size());
444   DALI_TEST_EQUAL(0u, ctx.resources.mSkeletons.size());
445
446   DALI_TEST_EQUAL(6u, ctx.cameras.size());
447   DALI_TEST_EQUAL(0u, ctx.lights.size());
448   DALI_TEST_EQUAL(1u, ctx.animations.size());
449   DALI_TEST_EQUAL(0u, ctx.animationGroups.size());
450
451   END_TEST;
452 }
453
454 int UtcDaliGltfLoaderSuccess2(void)
455 {
456   Context                 ctx;
457   ShaderDefinitionFactory sdf;
458   sdf.SetResources(ctx.resources);
459
460   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AnimatedCubeStride.gltf", ctx.loadResult);
461
462   DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
463   DALI_TEST_EQUAL(1u, ctx.scene.GetNodeCount());
464
465   TestApplication app;
466
467   Customization::Choices choices;
468   for(auto iRoot : ctx.scene.GetRoots())
469   {
470     auto resourceRefs = ctx.resources.CreateRefCounter();
471     ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs);
472     ctx.resources.mReferenceCounts = std::move(resourceRefs);
473     ctx.resources.LoadResources(ctx.pathProvider);
474   }
475
476   DALI_TEST_EQUAL(true, ctx.resources.mMeshes[0u].first.mPositions.IsDefined());
477   DALI_TEST_EQUAL(432, ctx.resources.mMeshes[0u].first.mPositions.mBlob.mLength);
478
479   END_TEST;
480 }
481
482 int UtcDaliGltfLoaderSuccessShort(void)
483 {
484   TestApplication app;
485
486   const std::string resourcePath = TEST_RESOURCE_DIR "/";
487   auto              pathProvider = [resourcePath](ResourceType::Value)
488   {
489     return resourcePath;
490   };
491
492   Customization::Choices choices;
493   for(auto modelName : {
494         "2CylinderEngine",
495         "AnimatedMorphCube",
496         "AnimatedMorphCubeAnimateNonZeroFrame",
497         "AnimatedMorphSphere",
498         "AnimatedTriangle",
499         "BoxAnimated",
500         "CesiumMan",
501         "CesiumMilkTruck",
502         "EnvironmentTest",
503         "MetalRoughSpheres",
504         "MorphPrimitivesTest",
505         "MRendererTest",
506         "SimpleSparseAccessor",
507         "AnimatedCube",
508       })
509   {
510     Context ctx;
511
512     auto& resources = ctx.resources;
513     resources.mEnvironmentMaps.push_back({});
514
515     printf("%s\n", modelName);
516     ctx.loader.LoadModel(resourcePath + modelName + ".gltf", ctx.loadResult);
517     DALI_TEST_CHECK(ctx.scene.GetNodeCount() > 0);
518
519     auto& scene = ctx.scene;
520     for(auto iRoot : scene.GetRoots())
521     {
522       struct Visitor : NodeDefinition::IVisitor
523       {
524         struct ResourceReceiver : IResourceReceiver
525         {
526           std::vector<bool> mCounts;
527
528           void Register(ResourceType::Value type, Index id) override
529           {
530             if(type == ResourceType::Mesh)
531             {
532               mCounts[id] = true;
533             }
534           }
535         } receiver;
536
537         void Start(NodeDefinition& n) override
538         {
539           for(auto& renderable : n.mRenderables)
540           {
541             renderable->RegisterResources(receiver);
542           }
543         }
544
545         void Finish(NodeDefinition& n) override
546         {
547         }
548       } visitor;
549       visitor.receiver.mCounts.resize(resources.mMeshes.size(), false);
550
551       scene.Visit(iRoot, choices, visitor);
552       for(uint32_t i0 = 0, i1 = resources.mMeshes.size(); i0 < i1; ++i0)
553       {
554         if(visitor.receiver.mCounts[i0])
555         {
556           auto raw = resources.mMeshes[i0].first.LoadRaw(resourcePath, resources.mBuffers);
557           DALI_TEST_CHECK(!raw.mAttribs.empty());
558
559           resources.mMeshes[i0].second = resources.mMeshes[i0].first.Load(std::move(raw));
560           DALI_TEST_CHECK(resources.mMeshes[i0].second.geometry);
561         }
562       }
563     }
564   }
565
566   END_TEST;
567 }
568
569 int UtcDaliGltfLoaderMRendererTest(void)
570 {
571   Context ctx;
572
573   ShaderDefinitionFactory sdf;
574   sdf.SetResources(ctx.resources);
575   auto& resources = ctx.resources;
576
577   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/MRendererTest.gltf", ctx.loadResult);
578
579   auto& scene = ctx.scene;
580   auto& roots = scene.GetRoots();
581   DALI_TEST_EQUAL(roots.size(), 1u);
582   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "RootNode");
583   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mScale, Vector3(1.0f, 1.0f, 1.0f));
584
585   DALI_TEST_EQUAL(scene.GetNodeCount(), 1u);
586
587   ViewProjection viewProjection;
588   Transforms     xforms{
589     MatrixStack{},
590     viewProjection};
591   NodeDefinition::CreateParams nodeParams{
592     resources,
593     xforms,
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.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
612       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
613       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
614       root.Add(actor);
615     }
616   }
617
618   DALI_TEST_EQUAL(root.GetChildCount(), 1u);
619   Actor child = root.GetChildAt(0);
620
621   DALI_TEST_EQUAL(child.GetProperty(Actor::Property::NAME).Get<std::string>(), "RootNode");
622   DALI_TEST_EQUAL(child.GetProperty(Actor::Property::SCALE).Get<Vector3>(), Vector3(1.0f, 1.0f, 1.0f));
623   DALI_TEST_EQUAL(child.GetRendererCount(), 1u);
624   DALI_TEST_EQUAL(child.GetRendererAt(0).GetTextures().GetTextureCount(), 4u);
625
626   DALI_TEST_EQUAL(child.GetRendererCount(), 1u);
627   DALI_TEST_EQUAL(child.GetRendererAt(0u).GetProperty<decltype(BlendMode::ON)>(Renderer::Property::BLEND_MODE), BlendMode::ON);
628
629   END_TEST;
630 }
631
632 int UtcDaliGltfLoaderAnimationLoadingTest(void)
633 {
634   TestApplication app;
635   Context ctx;
636
637   auto& resources = ctx.resources;
638
639   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/CesiumMan_e.gltf", ctx.loadResult);
640
641   auto& scene = ctx.scene;
642   auto& roots = scene.GetRoots();
643   DALI_TEST_EQUAL(roots.size(), 1u);
644
645   ViewProjection viewProjection;
646   Transforms     xforms{
647     MatrixStack{},
648     viewProjection};
649   NodeDefinition::CreateParams nodeParams{
650     resources,
651     xforms,
652   };
653
654   Customization::Choices choices;
655
656   Actor root = Actor::New();
657   SetActorCentered(root);
658   for(auto iRoot : roots)
659   {
660     auto resourceRefs = resources.CreateRefCounter();
661     scene.CountResourceRefs(iRoot, choices, resourceRefs);
662     resources.mReferenceCounts = std::move(resourceRefs);
663     resources.CountEnvironmentReferences();
664     resources.LoadResources(ctx.pathProvider);
665     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
666     {
667       scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
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].mProperties.size(), 57u);
676
677   uint32_t id = ctx.loadResult.mScene.GetNode(ctx.loadResult.mAnimationDefinitions[0].mProperties[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   ShaderDefinitionFactory sdf;
688   sdf.SetResources(ctx.resources);
689   auto& resources = ctx.resources;
690
691   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/EnvironmentTest_b.gltf", ctx.loadResult);
692
693   auto& scene = ctx.scene;
694   auto& roots = scene.GetRoots();
695   DALI_TEST_EQUAL(roots.size(), 1u);
696
697   ViewProjection viewProjection;
698   Transforms     xforms{
699     MatrixStack{},
700     viewProjection};
701   NodeDefinition::CreateParams nodeParams{
702     resources,
703     xforms,
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.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
722       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
723       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
724       root.Add(actor);
725     }
726   }
727
728   DALI_TEST_CHECK(resources.mMaterials[0].second.GetTextureCount() > 1);
729   DALI_TEST_EQUAL(resources.mMaterials[0].second.GetTexture(0).GetWidth(), 256);
730   DALI_TEST_EQUAL(resources.mMaterials[0].second.GetTexture(0).GetHeight(), 256);
731
732   END_TEST;
733 }
734
735 int UtcDaliGltfLoaderUint8Indices(void)
736 {
737   Context ctx;
738
739   auto& resources = ctx.resources;
740
741   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AlphaBlendModeTest.gltf", ctx.loadResult);
742
743   auto& scene = ctx.scene;
744   auto& roots = scene.GetRoots();
745   DALI_TEST_EQUAL(roots.size(), 1u);
746
747   ViewProjection viewProjection;
748   Transforms     xforms{
749     MatrixStack{},
750     viewProjection};
751   NodeDefinition::CreateParams nodeParams{
752     resources,
753     xforms,
754   };
755
756   Customization::Choices choices;
757
758   TestApplication app;
759
760   Actor root = Actor::New();
761   SetActorCentered(root);
762   for(auto iRoot : roots)
763   {
764     auto resourceRefs = resources.CreateRefCounter();
765     scene.CountResourceRefs(iRoot, choices, resourceRefs);
766     resources.mReferenceCounts = std::move(resourceRefs);
767     resources.CountEnvironmentReferences();
768     resources.LoadResources(ctx.pathProvider);
769     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
770     {
771       scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
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 }