Add macro defs to shader regen
[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     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   Dali::Scene3D::Loader::Internal::Gltf2LoaderImpl loader;
81 };
82
83 struct ExceptionMessageStartsWith
84 {
85   const std::string_view expected;
86
87   bool operator()(const std::runtime_error& e)
88   {
89     const bool success = (0 == strncmp(e.what(), expected.data(), expected.size()));
90     if(!success)
91     {
92       printf("Expected: %s, got: %s.\n", expected.data(), e.what());
93     }
94     return success;
95   }
96 };
97
98 } // namespace
99
100 int UtcDaliGltfLoaderFailedToLoad1(void)
101 {
102   Context ctx;
103
104   DALI_TEST_EQUAL(ctx.loader.LoadModel("non-existent.gltf", ctx.loadResult), false);
105
106   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
107   DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
108
109   DALI_TEST_EQUAL(0, ctx.resources.mEnvironmentMaps.size());
110   DALI_TEST_EQUAL(0, ctx.resources.mMaterials.size());
111   DALI_TEST_EQUAL(0, ctx.resources.mMeshes.size());
112   DALI_TEST_EQUAL(0, ctx.resources.mShaders.size());
113   DALI_TEST_EQUAL(0, ctx.resources.mSkeletons.size());
114
115   DALI_TEST_EQUAL(0, ctx.cameras.size());
116   DALI_TEST_EQUAL(0, ctx.lights.size());
117   DALI_TEST_EQUAL(0, ctx.animations.size());
118   DALI_TEST_EQUAL(0, ctx.animationGroups.size());
119
120   END_TEST;
121 }
122
123 int UtcDaliGltfLoaderFailedToLoad2(void)
124 {
125   Context ctx;
126
127   try
128   {
129     DALI_TEST_EQUAL(ctx.loader.LoadModel(TEST_RESOURCE_DIR "/UnsupportedExtension.gltf", ctx.loadResult), false);
130   }
131   catch(...)
132   {
133     printf("Unsupported glTF extension required.\n");
134   }
135
136   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
137   DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
138
139   DALI_TEST_EQUAL(0, ctx.resources.mEnvironmentMaps.size());
140   DALI_TEST_EQUAL(0, ctx.resources.mMaterials.size());
141   DALI_TEST_EQUAL(0, ctx.resources.mMeshes.size());
142   DALI_TEST_EQUAL(0, ctx.resources.mShaders.size());
143   DALI_TEST_EQUAL(0, ctx.resources.mSkeletons.size());
144
145   DALI_TEST_EQUAL(0, ctx.cameras.size());
146   DALI_TEST_EQUAL(0, ctx.lights.size());
147   DALI_TEST_EQUAL(0, ctx.animations.size());
148   DALI_TEST_EQUAL(0, ctx.animationGroups.size());
149
150   END_TEST;
151 }
152
153 int UtcDaliGltfLoaderFailedToParse(void)
154 {
155   Context ctx;
156
157   DALI_TEST_EQUAL(ctx.loader.LoadModel(TEST_RESOURCE_DIR "/invalid.gltf", ctx.loadResult), false);
158
159   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
160   DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
161
162   DALI_TEST_EQUAL(0, ctx.resources.mEnvironmentMaps.size());
163   DALI_TEST_EQUAL(0, ctx.resources.mMaterials.size());
164   DALI_TEST_EQUAL(0, ctx.resources.mMeshes.size());
165   DALI_TEST_EQUAL(0, ctx.resources.mSkeletons.size());
166
167   DALI_TEST_EQUAL(0, ctx.cameras.size());
168   DALI_TEST_EQUAL(0, ctx.lights.size());
169   DALI_TEST_EQUAL(0, ctx.animations.size());
170   DALI_TEST_EQUAL(0, ctx.animationGroups.size());
171
172   END_TEST;
173 }
174
175 int UtcDaliGltfLoaderSuccess1(void)
176 {
177   Context ctx;
178
179   LoadSceneMetadata(TEST_RESOURCE_DIR "/AnimatedCube.metadata", ctx.metaData);
180
181   std::unordered_map<std::string, ImageMetadata> imageMetadataGroundTruth;
182   imageMetadataGroundTruth["AnimatedCube_BaseColor.png"]         = ImageMetadata{ImageDimensions(256, 256), Dali::SamplingMode::BOX_THEN_NEAREST};
183   imageMetadataGroundTruth["AnimatedCube_MetallicRoughness.png"] = ImageMetadata{ImageDimensions(256, 256), Dali::SamplingMode::NEAREST};
184
185   auto metaData = ctx.metaData.mImageMetadata.begin();
186   for(auto& groundTruth : imageMetadataGroundTruth)
187   {
188     DALI_TEST_EQUAL(groundTruth.first, metaData->first);
189     DALI_TEST_EQUAL(groundTruth.second.mMinSize, metaData->second.mMinSize);
190     DALI_TEST_EQUAL(groundTruth.second.mSamplingMode, metaData->second.mSamplingMode);
191     ++metaData;
192   }
193
194   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AnimatedCube.gltf", ctx.loadResult);
195
196   DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
197   DALI_TEST_EQUAL(9u, ctx.scene.GetNodeCount());
198
199   // Default envmap is used
200   DALI_TEST_EQUAL(1u, ctx.resources.mEnvironmentMaps.size());
201
202   TestApplication app;
203
204   Customization::Choices choices;
205   for(auto iRoot : ctx.scene.GetRoots())
206   {
207     auto resourceRefs = ctx.resources.CreateRefCounter();
208     ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs);
209     ctx.resources.mReferenceCounts = std::move(resourceRefs);
210     ctx.resources.CountEnvironmentReferences();
211     ctx.resources.LoadResources(ctx.pathProvider);
212   }
213
214   auto& materials = ctx.resources.mMaterials;
215   DALI_TEST_EQUAL(2u, materials.size());
216   const MaterialDefinition materialGroundTruth[]{
217     {nullptr,
218      MaterialDefinition::ALBEDO | MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
219        MaterialDefinition::NORMAL | MaterialDefinition::SPECULAR | MaterialDefinition::SPECULAR_COLOR |
220        MaterialDefinition::GLTF_CHANNELS | (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
221      0,
222      Color::WHITE,
223      1.f,
224      0.f,
225      Vector4(1.000, 0.766, 0.336, 1.0),
226      1.f,
227      1.f,
228      Vector3(0.2, 0.1, 0.0),
229      1.0f,
230      0.0f,
231      0.5f,
232      Vector3(0, 0, 1),
233      true,
234      false,
235      true,
236      false,
237      Scene3D::Material::AlphaModeType::MASK,
238      true,
239      true,
240      true,
241      {
242        {
243          MaterialDefinition::ALBEDO,
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::NORMAL,
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::OCCLUSION,
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::EMISSIVE,
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          MaterialDefinition::SPECULAR,
280          {
281            "AnimatedCube_BaseColor.png",
282            SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
283            ImageDimensions(256, 256),
284            SamplingMode::BOX_THEN_NEAREST,
285          },
286        },
287        {
288          MaterialDefinition::SPECULAR_COLOR,
289          {
290            "AnimatedCube_BaseColor.png",
291            SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
292            ImageDimensions(256, 256),
293            SamplingMode::BOX_THEN_NEAREST,
294          },
295        },
296      },
297      nullptr},
298     {
299       nullptr,
300       MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
301         MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION | MaterialDefinition::NORMAL |
302         MaterialDefinition::GLTF_CHANNELS,
303       0,
304       Color::WHITE,
305       1.f,
306       0.f,
307       Vector4(1.000, 0.766, 0.336, 1.0),
308       1.f,
309       1.f,
310       Vector3(0.2, 0.1, 0.0),
311       -1.0f,
312       0.04f,
313       1.0f,
314       Vector3::ONE,
315       true,
316       true,
317       true,
318       false,
319       Scene3D::Material::AlphaModeType::OPAQUE,
320       true,
321       false,
322       true,
323       {
324         {
325           MaterialDefinition::ALBEDO,
326           {
327             "AnimatedCube_BaseColor.png",
328             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
329             ImageDimensions(256, 256),
330             SamplingMode::BOX_THEN_NEAREST,
331           },
332         },
333         {
334           MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS,
335           {
336             "AnimatedCube_MetallicRoughness.png",
337             SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT),
338             ImageDimensions(256, 256),
339             SamplingMode::NEAREST,
340           },
341         },
342         {
343           MaterialDefinition::NORMAL,
344           {
345             "AnimatedCube_BaseColor.png",
346             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
347             ImageDimensions(256, 256),
348             SamplingMode::BOX_THEN_NEAREST,
349           },
350         },
351         {
352           MaterialDefinition::OCCLUSION,
353           {
354             "AnimatedCube_BaseColor.png",
355             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
356             ImageDimensions(256, 256),
357             SamplingMode::BOX_THEN_NEAREST,
358           },
359         },
360         {
361           MaterialDefinition::EMISSIVE,
362           {
363             "AnimatedCube_BaseColor.png",
364             SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
365             ImageDimensions(256, 256),
366             SamplingMode::BOX_THEN_NEAREST,
367           },
368         },
369       },
370       nullptr,
371     },
372   };
373
374   auto iMaterial = materials.begin();
375   auto iMetadata = ctx.metaData.mImageMetadata.begin();
376   for(auto& m : materialGroundTruth)
377   {
378     printf("material %ld\n", iMaterial - materials.begin());
379     auto& md = iMaterial->first;
380     DALI_TEST_EQUAL(md.mFlags, m.mFlags);
381     DALI_TEST_EQUAL(md.mEnvironmentIdx, m.mEnvironmentIdx);
382     DALI_TEST_EQUAL(md.mColor, m.mColor);
383     DALI_TEST_EQUAL(md.mMetallic, m.mMetallic);
384     DALI_TEST_EQUAL(md.mRoughness, m.mRoughness);
385     DALI_TEST_EQUAL(md.mBaseColorFactor, m.mBaseColorFactor);
386     DALI_TEST_EQUAL(md.mNormalScale, m.mNormalScale);
387     DALI_TEST_EQUAL(md.mOcclusionStrength, m.mOcclusionStrength);
388     DALI_TEST_EQUAL(md.mEmissiveFactor, m.mEmissiveFactor);
389     DALI_TEST_EQUAL(md.mIor, m.mIor);
390     DALI_TEST_EQUAL(md.mDielectricSpecular, m.mDielectricSpecular);
391     DALI_TEST_EQUAL(md.mSpecularFactor, m.mSpecularFactor);
392     DALI_TEST_EQUAL(md.mSpecularColorFactor, m.mSpecularColorFactor);
393     DALI_TEST_EQUAL(md.mNeedAlbedoTexture, m.mNeedAlbedoTexture);
394     DALI_TEST_EQUAL(md.mNeedMetallicRoughnessTexture, m.mNeedMetallicRoughnessTexture);
395     DALI_TEST_EQUAL(md.mNeedNormalTexture, m.mNeedNormalTexture);
396     DALI_TEST_EQUAL(md.mAlphaModeType, m.mAlphaModeType);
397     DALI_TEST_EQUAL(md.mIsOpaque, m.mIsOpaque);
398     DALI_TEST_EQUAL(md.mIsMask, m.mIsMask);
399
400     DALI_TEST_EQUAL(md.mTextureStages.size(), m.mTextureStages.size());
401     auto iTexture = md.mTextureStages.begin();
402     for(auto& ts : m.mTextureStages)
403     {
404       printf("texture %ld\n", iTexture - md.mTextureStages.begin());
405       DALI_TEST_EQUAL(iTexture->mSemantic, ts.mSemantic);
406       DALI_TEST_EQUAL(iTexture->mTexture.mImageUri, ts.mTexture.mImageUri);
407       DALI_TEST_EQUAL(uint32_t(iTexture->mTexture.mSamplerFlags), uint32_t(ts.mTexture.mSamplerFlags)); // don't interpret it as a character
408       DALI_TEST_EQUAL(iTexture->mTexture.mMinImageDimensions, ts.mTexture.mMinImageDimensions);
409       DALI_TEST_EQUAL(iTexture->mTexture.mSamplingMode, ts.mTexture.mSamplingMode);
410
411       ++iTexture;
412     }
413     ++iMaterial;
414     ++iMetadata;
415   }
416
417   auto& meshes = ctx.resources.mMeshes;
418   DALI_TEST_EQUAL(2u, meshes.size());
419
420   using Blob     = MeshDefinition::Blob;
421   using Accessor = MeshDefinition::Accessor;
422   MeshDefinition meshGroundTruth[]{
423     {
424       nullptr,
425       0,
426       Geometry::TRIANGLES,
427       "AnimatedCube.bin",
428       Accessor{Blob{0, 0}, {}},
429       Accessor{Blob{0, 0}, {}},
430       Accessor{Blob{0, 0}, {}},
431       Accessor{Blob{0, 0}, {}},
432     },
433     {
434       nullptr,
435       0,
436       Geometry::TRIANGLES,
437       "AnimatedCube.bin",
438       Accessor{Blob{0, 0}, {}},
439       Accessor{Blob{0, 0}, {}},
440       Accessor{Blob{0, 0}, {}},
441       Accessor{Blob{0, 0}, {}},
442     },
443   };
444   meshGroundTruth[0].mColors.push_back(Accessor{Blob{0, 0}, {}});
445   meshGroundTruth[0].mTexCoords.push_back(Accessor{Blob{0, 0}, {}});
446   meshGroundTruth[1].mColors.push_back(Accessor{Blob{0, 0}, {}});
447   meshGroundTruth[1].mTexCoords.push_back(Accessor{Blob{0, 0}, {}});
448
449   auto iMesh = meshes.begin();
450   for(auto& m : meshGroundTruth)
451   {
452     printf("mesh %ld\n", iMesh - meshes.begin());
453
454     auto& md = iMesh->first;
455     DALI_TEST_EQUAL(md.mFlags, m.mFlags);
456     DALI_TEST_EQUAL(md.mPrimitiveType, m.mPrimitiveType);
457
458     DALI_TEST_EQUAL((md.mIndices).IsDefined(), (m.mIndices).IsDefined());
459     DALI_TEST_EQUAL((md.mIndices).mBlob.IsDefined(), (m.mIndices).mBlob.IsDefined());
460
461     DALI_TEST_EQUAL((md.mPositions).IsDefined(), (m.mPositions).IsDefined());
462     DALI_TEST_EQUAL((md.mPositions).mBlob.IsDefined(), (m.mPositions).mBlob.IsDefined());
463
464     DALI_TEST_EQUAL((md.mNormals).IsDefined(), (m.mNormals).IsDefined());
465     DALI_TEST_EQUAL((md.mNormals).mBlob.IsDefined(), (m.mNormals).mBlob.IsDefined());
466
467     DALI_TEST_EQUAL((md.mTangents).IsDefined(), (m.mTangents).IsDefined());
468     DALI_TEST_EQUAL((md.mTangents).mBlob.IsDefined(), (m.mTangents).mBlob.IsDefined());
469
470     DALI_TEST_EQUAL(md.mTexCoords.empty(), m.mTexCoords.empty());
471     DALI_TEST_EQUAL(md.mColors.empty(), m.mColors.empty());
472
473     DALI_TEST_EQUAL(md.mJoints.empty(), (m.mJoints.empty()));
474     DALI_TEST_EQUAL(md.mWeights.empty(), (m.mWeights.empty()));
475
476     DALI_TEST_EQUAL(md.mBlendShapeHeader.IsDefined(), m.mBlendShapeHeader.IsDefined());
477
478     ++iMesh;
479   }
480
481   DALI_TEST_EQUAL(0u, ctx.resources.mSkeletons.size());
482
483   DALI_TEST_EQUAL(6u, ctx.cameras.size());
484   DALI_TEST_EQUAL(0u, ctx.lights.size());
485   DALI_TEST_EQUAL(1u, ctx.animations.size());
486   DALI_TEST_EQUAL(0u, ctx.animationGroups.size());
487
488   END_TEST;
489 }
490
491 int UtcDaliGltfLoaderSuccess2(void)
492 {
493   Context ctx;
494
495   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AnimatedCubeStride.gltf", ctx.loadResult);
496
497   DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
498   DALI_TEST_EQUAL(1u, ctx.scene.GetNodeCount());
499
500   TestApplication app;
501
502   Customization::Choices choices;
503   for(auto iRoot : ctx.scene.GetRoots())
504   {
505     auto resourceRefs = ctx.resources.CreateRefCounter();
506     ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs);
507     ctx.resources.mReferenceCounts = std::move(resourceRefs);
508     ctx.resources.LoadResources(ctx.pathProvider);
509   }
510
511   DALI_TEST_EQUAL(true, ctx.resources.mMeshes[0u].first.mPositions.IsDefined());
512   DALI_TEST_EQUAL(432, ctx.resources.mMeshes[0u].first.mPositions.mBlob.mLength);
513
514   END_TEST;
515 }
516
517 int UtcDaliGltfLoaderSuccessShort(void)
518 {
519   TestApplication app;
520
521   const std::string resourcePath = TEST_RESOURCE_DIR "/";
522   auto              pathProvider = [resourcePath](ResourceType::Value) {
523     return resourcePath;
524   };
525
526   Customization::Choices choices;
527   for(auto modelName : {
528         "2CylinderEngine",
529         "AnimatedMorphCube",
530         "AnimatedMorphCubeAnimateNonZeroFrame",
531         "AnimatedMorphSphere",
532         "AnimatedTriangle",
533         "BoxAnimated",
534         "CesiumMan",
535         "CesiumMilkTruck",
536         "EnvironmentTest",
537         "MetalRoughSpheres",
538         "MorphPrimitivesTest",
539         "MRendererTest",
540         "SimpleSparseAccessor",
541         "AnimatedCube",
542         /**
543          * For the Avocado glTF file and its Assets
544          * Donated by Microsoft for glTF testing
545          * Take from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Avocado/glTF-Quantized
546          */
547         "AvocadoQuantized",
548         /**
549          * For the AnimatedMorphCube glTF file and its Assets
550          * Donated by Microsoft for glTF testing
551          * Take from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/AnimatedMorphCube/glTF-Quantized
552          */
553         "AnimatedMorphCubeQuantized",
554         /**
555          * For the MorphPrimitivesTest glTF file and its Assets
556          * Created by @ft-lab
557          * Licensed under the terms of the CC BY 4.0 license: https://creativecommons.org/licenses/by/4.0/
558          * Take from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/MorphPrimitivesTest/glTF
559          * Modified using gltfpack 0.18.
560          */
561         "MorphPrimitivesTestQuantized",
562         /**
563          * For the CesiumMilkTruck glTF file and its Assets
564          * Donated by Cesium for glTF testing
565          * Licensed under the terms of the CC BY 4.0 license: http://creativecommons.org/licenses/by/4.0/
566          * Take from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/CesiumMilkTruck/glTF
567          * Modified using gltfpack 0.18.
568          */
569         "CesiumMilkTruckQuantized",
570       })
571   {
572     Context ctx;
573
574     auto& resources = ctx.resources;
575     resources.mEnvironmentMaps.push_back({});
576
577     printf("%s\n", modelName);
578     ctx.loader.LoadModel(resourcePath + modelName + ".gltf", ctx.loadResult);
579     DALI_TEST_CHECK(ctx.scene.GetNodeCount() > 0);
580
581     auto& scene = ctx.scene;
582     for(auto iRoot : scene.GetRoots())
583     {
584       struct Visitor : NodeDefinition::IVisitor
585       {
586         struct ResourceReceiver : IResourceReceiver
587         {
588           std::vector<bool> mCounts;
589
590           void Register(ResourceType::Value type, Index id) override
591           {
592             if(type == ResourceType::Mesh)
593             {
594               mCounts[id] = true;
595             }
596           }
597         } receiver;
598
599         void Start(NodeDefinition& n) override
600         {
601           for(auto& renderable : n.mRenderables)
602           {
603             renderable->RegisterResources(receiver);
604           }
605         }
606
607         void Finish(NodeDefinition& n) override
608         {
609         }
610       } visitor;
611       visitor.receiver.mCounts.resize(resources.mMeshes.size(), false);
612
613       scene.Visit(iRoot, choices, visitor);
614       for(uint32_t i0 = 0, i1 = resources.mMeshes.size(); i0 < i1; ++i0)
615       {
616         if(visitor.receiver.mCounts[i0])
617         {
618           auto raw = resources.mMeshes[i0].first.LoadRaw(resourcePath, resources.mBuffers);
619           DALI_TEST_CHECK(!raw.mAttribs.empty());
620
621           resources.mMeshes[i0].second = resources.mMeshes[i0].first.Load(std::move(raw));
622           DALI_TEST_CHECK(resources.mMeshes[i0].second.geometry);
623         }
624       }
625     }
626   }
627
628   END_TEST;
629 }
630
631 int UtcDaliGltfLoaderMRendererTest(void)
632 {
633   Context ctx;
634   auto&   resources = ctx.resources;
635
636   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/MRendererTest.gltf", ctx.loadResult);
637
638   auto& scene = ctx.scene;
639   auto& roots = scene.GetRoots();
640   DALI_TEST_EQUAL(roots.size(), 1u);
641   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "RootNode");
642   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mScale, Vector3(1.0f, 1.0f, 1.0f));
643
644   DALI_TEST_EQUAL(scene.GetNodeCount(), 1u);
645
646   Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
647   ViewProjection                    viewProjection;
648   Transforms                        xforms{
649     MatrixStack{},
650     viewProjection};
651   NodeDefinition::CreateParams nodeParams{
652     resources,
653     xforms,
654     shaderManager,
655   };
656
657   Customization::Choices choices;
658
659   TestApplication app;
660
661   Actor root = Actor::New();
662   SetActorCentered(root);
663   for(auto iRoot : roots)
664   {
665     auto resourceRefs = resources.CreateRefCounter();
666     scene.CountResourceRefs(iRoot, choices, resourceRefs);
667     ctx.resources.mReferenceCounts = std::move(resourceRefs);
668     ctx.resources.CountEnvironmentReferences();
669     ctx.resources.LoadResources(ctx.pathProvider);
670     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
671     {
672       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
673       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
674       root.Add(actor);
675     }
676   }
677
678   DALI_TEST_EQUAL(root.GetChildCount(), 1u);
679   Actor child = root.GetChildAt(0);
680
681   DALI_TEST_EQUAL(child.GetProperty(Actor::Property::NAME).Get<std::string>(), "RootNode");
682   DALI_TEST_EQUAL(child.GetProperty(Actor::Property::SCALE).Get<Vector3>(), Vector3(1.0f, 1.0f, 1.0f));
683   DALI_TEST_EQUAL(child.GetRendererCount(), 1u);
684   DALI_TEST_EQUAL(child.GetRendererAt(0).GetTextures().GetTextureCount(), 5u);
685
686   DALI_TEST_EQUAL(child.GetRendererCount(), 1u);
687   DALI_TEST_EQUAL(child.GetRendererAt(0u).GetProperty<decltype(BlendMode::ON)>(Renderer::Property::BLEND_MODE), BlendMode::ON);
688
689   END_TEST;
690 }
691
692 int UtcDaliGltfLoaderAnimationLoadingTest(void)
693 {
694   TestApplication app;
695   Context         ctx;
696
697   auto& resources = ctx.resources;
698
699   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/CesiumMan_e.gltf", ctx.loadResult);
700
701   auto& scene = ctx.scene;
702   auto& roots = scene.GetRoots();
703   DALI_TEST_EQUAL(roots.size(), 1u);
704
705   Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
706   ViewProjection                    viewProjection;
707   Transforms                        xforms{
708     MatrixStack{},
709     viewProjection};
710   NodeDefinition::CreateParams nodeParams{
711     resources,
712     xforms,
713     shaderManager,
714   };
715
716   Customization::Choices choices;
717
718   Actor root = Actor::New();
719   SetActorCentered(root);
720   for(auto iRoot : roots)
721   {
722     auto resourceRefs = resources.CreateRefCounter();
723     scene.CountResourceRefs(iRoot, choices, resourceRefs);
724     resources.mReferenceCounts = std::move(resourceRefs);
725     resources.CountEnvironmentReferences();
726     resources.LoadResources(ctx.pathProvider);
727     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
728     {
729       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
730       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
731       root.Add(actor);
732     }
733   }
734
735   DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions.size(), 1u);
736   DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions[0].GetPropertyCount(), 57u);
737
738   uint32_t id = ctx.loadResult.mScene.GetNode(ctx.loadResult.mAnimationDefinitions[0].GetPropertyAt(0).mNodeIndex)->mNodeId;
739   DALI_TEST_EQUAL(id, root.FindChildByName("Skeleton_torso_joint_1").GetProperty<int32_t>(Dali::Actor::Property::ID));
740
741   END_TEST;
742 }
743
744 int UtcDaliGltfLoaderImageFromBufferView(void)
745 {
746   Context ctx;
747
748   auto& resources = ctx.resources;
749
750   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/EnvironmentTest_b.gltf", ctx.loadResult);
751
752   auto& scene = ctx.scene;
753   auto& roots = scene.GetRoots();
754   DALI_TEST_EQUAL(roots.size(), 1u);
755
756   Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
757   ViewProjection                    viewProjection;
758   Transforms                        xforms{
759     MatrixStack{},
760     viewProjection};
761   NodeDefinition::CreateParams nodeParams{
762     resources,
763     xforms,
764     shaderManager,
765   };
766
767   Customization::Choices choices;
768
769   TestApplication app;
770
771   Actor root = Actor::New();
772   SetActorCentered(root);
773   for(auto iRoot : roots)
774   {
775     auto resourceRefs = resources.CreateRefCounter();
776     scene.CountResourceRefs(iRoot, choices, resourceRefs);
777     resources.mReferenceCounts = std::move(resourceRefs);
778     resources.CountEnvironmentReferences();
779     resources.LoadResources(ctx.pathProvider);
780     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
781     {
782       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
783       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
784       root.Add(actor);
785     }
786   }
787
788   DALI_TEST_CHECK(resources.mMaterials[0].second.GetTextureCount() > 1);
789   DALI_TEST_EQUAL(resources.mMaterials[0].second.GetTexture(0).GetWidth(), 256);
790   DALI_TEST_EQUAL(resources.mMaterials[0].second.GetTexture(0).GetHeight(), 256);
791
792   END_TEST;
793 }
794
795 int UtcDaliGltfLoaderUint8Indices(void)
796 {
797   Context ctx;
798
799   auto& resources = ctx.resources;
800
801   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AlphaBlendModeTest.gltf", ctx.loadResult);
802
803   auto& scene = ctx.scene;
804   auto& roots = scene.GetRoots();
805   DALI_TEST_EQUAL(roots.size(), 1u);
806
807   Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
808   ViewProjection                    viewProjection;
809   Transforms                        xforms{
810     MatrixStack{},
811     viewProjection};
812   NodeDefinition::CreateParams nodeParams{
813     resources,
814     xforms,
815     shaderManager,
816   };
817
818   Customization::Choices choices;
819
820   TestApplication app;
821
822   Actor root = Actor::New();
823   SetActorCentered(root);
824   for(auto iRoot : roots)
825   {
826     auto resourceRefs = resources.CreateRefCounter();
827     scene.CountResourceRefs(iRoot, choices, resourceRefs);
828     resources.mReferenceCounts = std::move(resourceRefs);
829     resources.CountEnvironmentReferences();
830     resources.LoadResources(ctx.pathProvider);
831     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
832     {
833       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
834       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
835       root.Add(actor);
836     }
837   }
838
839   DALI_TEST_CHECK(root.FindChildByName("Bed"));
840   DALI_TEST_CHECK(root.FindChildByName("DecalBlend"));
841   DALI_TEST_CHECK(root.FindChildByName("DecalOpaque"));
842
843   END_TEST;
844 }
845
846 int UtcDaliGltfLoaderQuantizedMesh(void)
847 {
848   Context ctx;
849
850   auto& resources = ctx.resources;
851
852   /**
853    * For the Avocado glTF file and its Assets
854    * Donated by Microsoft for glTF testing
855    * Take from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Avocado/glTF-Quantized
856    */
857   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AvocadoQuantized.gltf", ctx.loadResult);
858
859   auto& scene = ctx.scene;
860   DALI_TEST_EQUAL(1u, scene.GetRoots().size());
861   DALI_TEST_EQUAL(1u, scene.GetNodeCount());
862
863   auto& roots = scene.GetRoots();
864   DALI_TEST_EQUAL(roots.size(), 1u);
865
866   Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
867   ViewProjection                    viewProjection;
868   Transforms                        xforms{
869     MatrixStack{},
870     viewProjection};
871   NodeDefinition::CreateParams nodeParams{
872     resources,
873     xforms,
874     shaderManager,
875   };
876
877   Customization::Choices choices;
878
879   TestApplication app;
880
881   Actor root = Actor::New();
882   SetActorCentered(root);
883   for(auto iRoot : roots)
884   {
885     auto resourceRefs = resources.CreateRefCounter();
886     scene.CountResourceRefs(iRoot, choices, resourceRefs);
887     resources.mReferenceCounts = std::move(resourceRefs);
888     resources.CountEnvironmentReferences();
889     resources.LoadResources(ctx.pathProvider);
890     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
891     {
892       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
893       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
894       root.Add(actor);
895     }
896   }
897
898   auto& meshes = ctx.resources.mMeshes;
899   DALI_TEST_EQUAL(1u, meshes.size());
900
901   auto& md = meshes[0u].first;
902
903   DALI_TEST_EQUAL(MeshDefinition::Flags::U16_POSITION | MeshDefinition::Flags::S8_NORMAL | MeshDefinition::Flags::S8_TANGENT | MeshDefinition::Flags::U16_TEXCOORD, md.mFlags);
904
905   DALI_TEST_EQUAL(true, md.mPositions.IsDefined());
906   DALI_TEST_EQUAL(false, md.mPositions.mNormalized);
907   DALI_TEST_EQUAL(sizeof(uint16_t) * 3, md.mPositions.mBlob.mElementSizeHint);
908   DALI_TEST_EQUAL(true, md.mPositions.mBlob.IsDefined());
909   DALI_TEST_EQUAL(2436, md.mPositions.mBlob.mLength);
910   DALI_TEST_EQUAL(3u, md.mPositions.mBlob.mMin.size());
911   DALI_TEST_EQUAL(0.0f, md.mPositions.mBlob.mMin[0]);
912   DALI_TEST_EQUAL(0.0f, md.mPositions.mBlob.mMin[1]);
913   DALI_TEST_EQUAL(0.0f, md.mPositions.mBlob.mMin[2]);
914   DALI_TEST_EQUAL(3u, md.mPositions.mBlob.mMax.size());
915   DALI_TEST_EQUAL(11086.0f, md.mPositions.mBlob.mMax[0]);
916   DALI_TEST_EQUAL(16383.0f, md.mPositions.mBlob.mMax[1]);
917   DALI_TEST_EQUAL(7194.0f, md.mPositions.mBlob.mMax[2]);
918
919   DALI_TEST_EQUAL(true, md.mNormals.IsDefined());
920   DALI_TEST_EQUAL(true, md.mNormals.mNormalized);
921   DALI_TEST_EQUAL(sizeof(int8_t) * 3, md.mNormals.mBlob.mElementSizeHint);
922   DALI_TEST_EQUAL(true, md.mNormals.mBlob.IsDefined());
923   DALI_TEST_EQUAL(1218, md.mNormals.mBlob.mLength);
924   DALI_TEST_EQUAL(0u, md.mNormals.mBlob.mMin.size());
925   DALI_TEST_EQUAL(0u, md.mNormals.mBlob.mMax.size());
926
927   DALI_TEST_EQUAL(true, md.mTangents.IsDefined());
928   DALI_TEST_EQUAL(true, md.mTangents.mNormalized);
929   DALI_TEST_EQUAL(Property::VECTOR4, md.mTangentType);
930   DALI_TEST_EQUAL(sizeof(int8_t) * 4, md.mTangents.mBlob.mElementSizeHint);
931   DALI_TEST_EQUAL(true, md.mTangents.mBlob.IsDefined());
932   DALI_TEST_EQUAL(1624, md.mTangents.mBlob.mLength);
933   DALI_TEST_EQUAL(0u, md.mTangents.mBlob.mMin.size());
934   DALI_TEST_EQUAL(0u, md.mTangents.mBlob.mMax.size());
935
936   DALI_TEST_EQUAL(false, md.mTexCoords.empty());
937   DALI_TEST_EQUAL(true, md.mTexCoords[0].IsDefined());
938   DALI_TEST_EQUAL(false, md.mTexCoords[0].mNormalized);
939   DALI_TEST_EQUAL(sizeof(uint16_t) * 2, md.mTexCoords[0].mBlob.mElementSizeHint);
940   DALI_TEST_EQUAL(true, md.mTexCoords[0].mBlob.IsDefined());
941   DALI_TEST_EQUAL(1624, md.mTexCoords[0].mBlob.mLength);
942   DALI_TEST_EQUAL(0u, md.mTexCoords[0].mBlob.mMin.size());
943   DALI_TEST_EQUAL(0u, md.mTexCoords[0].mBlob.mMax.size());
944
945   END_TEST;
946 }