[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / loader / gltf2-asset.h
1 #ifndef DALI_SCENE3D_LOADER_GLTF2_ASSET_H_
2 #define DALI_SCENE3D_LOADER_GLTF2_ASSET_H_
3 /*
4  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 // EXTERNAL INCLUDES
21 #include <dali/devel-api/common/map-wrapper.h>
22 #include <dali/public-api/common/vector-wrapper.h>
23 #include <dali/public-api/math/matrix3.h>
24 #include <dali/public-api/math/quaternion.h>
25 #include <dali/public-api/math/vector2.h>
26 #include <dali/public-api/math/vector4.h>
27 #include <cstdint>
28 #include <memory>
29
30 // INTERNAL INCLUDES
31 #include <dali-scene3d/internal/loader/json-reader.h>
32 #include <dali-scene3d/public-api/loader/index.h>
33 #include <dali-scene3d/public-api/loader/utils.h>
34
35 #define ENUM_STRING_MAPPING(t, x) \
36   {                               \
37 #x, t::x                      \
38   }
39
40 #define ENUM_TYPE_FROM_STRING(structName, table)                             \
41   structName::Type structName::FromString(const char* s, size_t len)         \
42   {                                                                          \
43     std::string target(s, len);                                              \
44     std::transform(target.begin(), target.end(), target.begin(), ::toupper); \
45                                                                              \
46     auto iFind = table.find(std::string_view(target.c_str(), len));          \
47     if(iFind != table.end())                                                 \
48     {                                                                        \
49       return iFind->second;                                                  \
50     }                                                                        \
51     return structName::INVALID;                                              \
52   }
53
54 namespace gltf2
55 {
56 using Index                           = Dali::Scene3D::Loader::Index;
57 constexpr float UNDEFINED_FLOAT_VALUE = -1.0f; ///< Special marker for some non-negative only float values.
58
59 template<typename T>
60 class Ref
61 {
62 public:
63   Ref() = default;
64   Ref(std::vector<T>& v, Index i)
65   : mVector(&v),
66     mIndex(i)
67   {
68   }
69
70   /**
71    * @return The index of the object into the vector.
72    * @note It is client code responsibility to ensure that the vector is unambiguous. It should be in
73    *  a glTF document, since there's one vector for each type.
74    */
75   Index GetIndex() const
76   {
77     return mIndex;
78   }
79
80   /**
81    * @brief There may be scenarios in which the object, whose vector we're populating, changes, e.g.
82    *  when we don't have a final one at the time of reading the references.
83    */
84   void UpdateVector(std::vector<T>& v)
85   {
86     mVector = &v;
87   }
88
89   operator bool() const
90   {
91     return mVector != nullptr;
92   }
93   T* operator->() const
94   {
95     return &(*mVector)[mIndex];
96   }
97   T& operator*() const
98   {
99     return (*mVector)[mIndex];
100   }
101
102   bool operator==(const Ref<T>& other) const
103   {
104     return mVector == other.mVector && mIndex == other.mIndex;
105   }
106
107   bool operator!=(const Ref<T>& other) const
108   {
109     return !operator==(other);
110   }
111
112 private:
113   std::vector<T>* mVector = nullptr;
114   Index           mIndex  = Dali::Scene3D::Loader::INVALID_INDEX;
115 };
116
117 struct Asset
118 {
119   std::string_view mGenerator;
120   std::string_view mVersion;
121 };
122
123 struct Component
124 {
125   enum Type
126   {
127     BYTE           = 5120,
128     UNSIGNED_BYTE  = 5121,
129     SHORT          = 5122,
130     UNSIGNED_SHORT = 5123,
131     UNSIGNED_INT   = 5125,
132     FLOAT          = 5126,
133     INVALID        = -1
134   };
135
136   static bool     IsUnsigned(Type t);
137   static uint32_t Size(Type t);
138
139   Component() = delete;
140 };
141
142 struct AccessorType
143 {
144   enum Type
145   {
146     SCALAR,
147     VEC2,
148     VEC3,
149     VEC4,
150     MAT2,
151     MAT3,
152     MAT4,
153     INVALID
154   };
155
156   static uint32_t ElementCount(Type t);
157
158   static Type FromString(const char* s, size_t len);
159
160   AccessorType() = delete;
161 };
162
163 struct AlphaMode
164 {
165   enum Type
166   {
167     OPAQUE,
168     MASK,
169     BLEND,
170     INVALID
171   };
172
173   static Type FromString(const char* s, size_t len);
174
175   AlphaMode() = delete;
176 };
177
178 struct Attribute
179 {
180   enum Type
181   {
182     POSITION,
183     NORMAL,
184     TANGENT,
185     TEXCOORD_N,
186     COLOR_N,
187     JOINTS_N,
188     WEIGHTS_N,
189     INVALID
190   };
191
192   using HashType = uint32_t;
193
194   // Hash bit layout
195   // +--+--+--+--+--+--+--+
196   // |31|30|29|28|27|..| 0| bit index
197   // +--+--+--+--+--+--+--+
198   //  \_/ - Set is used
199   //     \______/ - Type enum
200   //              \_______/ - Set ID
201   static const HashType SET_SHIFT{31};
202   static const HashType TYPE_SHIFT{28};
203   static const HashType SET_MASK{0x01u << SET_SHIFT};
204   static const HashType TYPE_MASK{0x07 << TYPE_SHIFT};
205   static const HashType SET_ID_MASK{0x0fffffff};
206
207   static HashType ToHash(Type type, bool set, HashType setIndex)
208   {
209     return ((set << SET_SHIFT) & SET_MASK) | ((static_cast<HashType>(type) << TYPE_SHIFT) & TYPE_MASK) | (setIndex & SET_ID_MASK);
210   }
211
212   static Attribute::Type TypeFromHash(HashType hash)
213   {
214     return static_cast<Type>((hash & TYPE_MASK) >> TYPE_SHIFT);
215   }
216
217   static bool SetFromHash(HashType hash)
218   {
219     return (hash & SET_SHIFT) != 0;
220   }
221
222   static HashType SetIdFromHash(HashType hash)
223   {
224     return (hash & SET_ID_MASK);
225   }
226
227   /**
228    * Convert to Type + setIndex, where setIndex is N for that attr, e.g. "JOINTS_1" => {JOINTS_N, 1}
229    */
230   static HashType HashFromString(const char* s, size_t len);
231
232   /**
233    * Convert to type only, there is no set for POSITION, NORMALS or TANGENT.
234    */
235   static Attribute::Type TargetFromString(const char* s, size_t len);
236
237   Attribute() = delete;
238 };
239
240 struct Buffer
241 {
242   uint32_t         mByteLength;
243   std::string_view mUri;
244   //TODO: extensions
245   //TODO: extras
246 };
247
248 struct BufferView
249 {
250   struct Target
251   {
252     enum Type
253     {
254       NONE,
255       ARRAY_BUFFER         = 34962,
256       ELEMENT_ARRAY_BUFFER = 34963
257     };
258
259     Target() = delete;
260   };
261
262   Ref<Buffer> mBuffer;
263   uint32_t    mByteOffset = 0;
264   uint32_t    mByteLength;
265   uint32_t    mByteStride = 0; // if 0 after reading, it needs to be calculated
266   uint32_t    mTarget;
267   //TODO: extensions
268   //TODO: extras
269 };
270
271 struct BufferViewClient
272 {
273   Ref<BufferView> mBufferView;
274   uint32_t        mByteOffset = 0;
275 };
276
277 struct ComponentTypedBufferViewClient : BufferViewClient
278 {
279   Component::Type mComponentType = Component::INVALID;
280
281   uint32_t GetBytesPerComponent() const;
282 };
283
284 struct Named
285 {
286   std::string_view mName;
287
288 protected:
289   Named() = default;
290 };
291
292 struct Accessor : ComponentTypedBufferViewClient, Named
293 {
294   struct Sparse
295   {
296     uint32_t                       mCount;
297     ComponentTypedBufferViewClient mIndices;
298     BufferViewClient               mValues;
299     //TODO: extensions
300     //TODO: extras
301   };
302
303   uint32_t                mCount;
304   bool                    mNormalized = false;
305   AccessorType::Type      mType       = AccessorType::INVALID;
306   std::vector<float>      mMin;
307   std::vector<float>      mMax;
308   std::unique_ptr<Sparse> mSparse;
309   //TODO: extensions
310   //TODO: extras
311
312   uint32_t GetElementSizeBytes() const
313   {
314     return GetBytesPerComponent() * AccessorType::ElementCount(mType);
315   }
316
317   uint32_t GetBytesLength() const
318   {
319     return GetElementSizeBytes() * mCount;
320   }
321
322   void SetSparse(const Sparse& s)
323   {
324     mSparse.reset(new Sparse(s));
325   }
326 };
327
328 struct Image : Named
329 {
330   std::string_view mUri;
331   std::string_view mMimeType;
332   Ref<BufferView>  mBufferView;
333   //TODO: extensions
334   //TODO: extras
335 };
336
337 struct Filter
338 {
339   enum Type
340   {
341     NEAREST                = 9728,
342     LINEAR                 = 9729,
343     NEAREST_MIPMAP_NEAREST = 9984,
344     NEAREST_MIPMAP_LINEAR  = 9985,
345     LINEAR_MIPMAP_NEAREST  = 9986,
346     LINEAR_MIPMAP_LINEAR   = 9987,
347   };
348
349   Filter() = delete;
350 };
351
352 struct Wrap
353 {
354   enum Type
355   {
356     REPEAT          = 10497,
357     CLAMP_TO_EDGE   = 33071,
358     MIRRORED_REPEAT = 33648,
359   };
360
361   Wrap() = delete;
362 };
363
364 struct Sampler
365 {
366   Filter::Type mMinFilter = Filter::LINEAR;
367   Filter::Type mMagFilter = Filter::LINEAR;
368   Wrap::Type   mWrapS     = Wrap::REPEAT;
369   Wrap::Type   mWrapT     = Wrap::REPEAT;
370   //TODO: extensions
371   //TODO: extras
372 };
373
374 struct Texture
375 {
376   Ref<Image>   mSource;
377   Ref<Sampler> mSampler;
378 };
379
380 struct TextureTransform
381 {
382   float         mRotation = 0.0f;
383   Dali::Vector2 mUvOffset = Dali::Vector2::ZERO;
384   Dali::Vector2 mUvScale  = Dali::Vector2::ONE;
385   uint32_t      mTexCoord = 0u;
386
387   operator bool() const
388   {
389     return !Dali::EqualsZero(mRotation) || mUvOffset != Dali::Vector2::ZERO || mUvScale != Dali::Vector2::ONE || mTexCoord != 0u;
390   }
391
392   const Dali::Matrix3 GetTransform() const
393   {
394     // See: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform
395     Dali::Matrix3 translation = Dali::Matrix3(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, mUvOffset.x, mUvOffset.y, 1.0f);
396     Dali::Matrix3 rotation    = Dali::Matrix3(cos(-mRotation), sin(-mRotation), 0.0f, -sin(-mRotation), cos(-mRotation), 0.0f, 0.0f, 0.0f, 1.0f);
397     Dali::Matrix3 scale       = Dali::Matrix3(mUvScale.x, 0.0f, 0.0f, 0.0f, mUvScale.y, 0.0f, 0.0f, 0.0f, 1.0f);
398
399     return translation * rotation * scale;
400   }
401 };
402
403 struct TextureExtensions
404 {
405   TextureTransform mTextureTransform;
406
407   operator bool() const
408   {
409     return mTextureTransform;
410   }
411 };
412
413 struct TextureInfo
414 {
415   Ref<gltf2::Texture> mTexture;
416   uint32_t            mTexCoord = 0;
417   float               mScale    = 1.f;
418   float               mStrength = 1.f;
419
420   TextureExtensions mTextureExtensions;
421
422   operator bool() const
423   {
424     return mTexture;
425   }
426 };
427
428 /**
429  * Material Ior is supported with KHR_materials_ior extension.
430  * https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_ior
431  */
432 struct MaterialIor
433 {
434   float mIor = UNDEFINED_FLOAT_VALUE;
435 };
436
437 /**
438  * Material Specular is supported with KHR_materials_ior extension.
439  * https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_specular
440  */
441 struct MaterialSpecular
442 {
443   float         mSpecularFactor = 1.0f;
444   TextureInfo   mSpecularTexture;
445   Dali::Vector3 mSpecularColorFactor = Dali::Vector3::ONE;
446   TextureInfo   mSpecularColorTexture;
447 };
448
449 struct MaterialExtensions
450 {
451   MaterialSpecular mMaterialSpecular;
452   MaterialIor      mMaterialIor;
453 };
454
455 struct Material : Named
456 {
457   struct Pbr // MetallicRoughness
458   {
459     Dali::Vector4 mBaseColorFactor = Dali::Vector4::ONE;
460     TextureInfo   mBaseColorTexture;
461     float         mMetallicFactor  = 1.f;
462     float         mRoughnessFactor = 1.f;
463     TextureInfo   mMetallicRoughnessTexture;
464     //TODO: extensions
465     //TODO: extras
466   };
467
468   Pbr             mPbrMetallicRoughness;
469   TextureInfo     mNormalTexture;
470   TextureInfo     mOcclusionTexture;
471   TextureInfo     mEmissiveTexture;
472   Dali::Vector3   mEmissiveFactor;
473   AlphaMode::Type mAlphaMode   = AlphaMode::OPAQUE;
474   float           mAlphaCutoff = .5f;
475   bool            mDoubleSided = false;
476
477   //extensions
478   MaterialExtensions mMaterialExtensions;
479   //TODO: extras
480 };
481
482 struct Mesh : Named
483 {
484   struct Primitive
485   {
486     enum Mode
487     {
488       POINTS,
489       LINES,
490       LINE_LOOP,
491       LINE_STRIP,
492       TRIANGLES,
493       TRIANGLE_STRIP,
494       TRIANGLE_FAN,
495       INVALID
496     };
497
498     std::map<Attribute::HashType, Ref<Accessor>>          mAttributes;
499     std::vector<std::map<Attribute::Type, Ref<Accessor>>> mTargets;
500     Ref<Accessor>                                         mIndices;
501     Ref<Material>                                         mMaterial;
502     Mode                                                  mMode = TRIANGLES;
503
504     //TODO: [morph] targets
505     //TODO: extras
506     //TODO: extensions
507   };
508
509   struct Extras
510   {
511     std::vector<std::string_view> mTargetNames;
512
513     //TODO: extras
514   };
515
516   struct Extensions
517   {
518     std::vector<std::string_view> mSXRTargetsNames;
519     std::vector<std::string_view> mAvatarShapeNames;
520
521     //TODO: extensions
522   };
523
524   std::vector<Primitive> mPrimitives;
525   std::vector<float>     mWeights;
526   Extras                 mExtras;
527   Extensions             mExtensions;
528 };
529
530 struct Node;
531
532 struct Skin : Named
533 {
534   Ref<Accessor>          mInverseBindMatrices;
535   Ref<Node>              mSkeleton;
536   std::vector<Ref<Node>> mJoints;
537   //TODO: extras
538   //TODO: extensions
539 };
540
541 struct Camera : Named
542 {
543   struct Perspective
544   {
545     float mAspectRatio = UNDEFINED_FLOAT_VALUE;
546     float mYFov        = UNDEFINED_FLOAT_VALUE;
547     float mZFar        = UNDEFINED_FLOAT_VALUE;
548     float mZNear       = UNDEFINED_FLOAT_VALUE;
549     //TODO: extras
550     //TODO: extensions
551   };
552
553   struct Orthographic
554   {
555     float mXMag  = UNDEFINED_FLOAT_VALUE;
556     float mYMag  = UNDEFINED_FLOAT_VALUE;
557     float mZFar  = UNDEFINED_FLOAT_VALUE;
558     float mZNear = UNDEFINED_FLOAT_VALUE;
559     //TODO: extras
560     //TODO: extensions
561   };
562
563   std::string_view mType;
564   Perspective      mPerspective;
565   Orthographic     mOrthographic;
566   //TODO: extras
567   //TODO: extensions
568 };
569
570 struct Node : Named
571 {
572   Dali::Vector3    mTranslation = Dali::Vector3::ZERO;
573   Dali::Quaternion mRotation    = Dali::Quaternion::IDENTITY;
574   Dali::Vector3    mScale       = Dali::Vector3::ONE;
575
576   Ref<Camera>            mCamera;
577   std::vector<Ref<Node>> mChildren;
578   Ref<Mesh>              mMesh;
579
580   Ref<Skin> mSkin;
581   //TODO: [morph] weights
582   //TODO: extras
583   //TODO: extensions
584
585   void SetMatrix(const Dali::Matrix& m);
586 };
587
588 struct Animation : Named
589 {
590   struct Sampler
591   {
592     struct Interpolation
593     {
594       enum Type
595       {
596         STEP,
597         LINEAR,
598         CUBICSPLINE,
599         INVALID
600       };
601       static Type FromString(const char* s, size_t len);
602     };
603
604     Ref<Accessor>       mInput;
605     Ref<Accessor>       mOutput;
606     Interpolation::Type mInterpolation;
607
608     //TODO: extras
609     //TODO: extensions
610   };
611
612   struct Channel
613   {
614     struct Target
615     {
616       enum Type
617       {
618         TRANSLATION,
619         ROTATION,
620         SCALE,
621         WEIGHTS,
622         INVALID
623       };
624
625       static Type FromString(const char* s, size_t len);
626
627       Ref<Node> mNode;
628       Type      mPath;
629     };
630
631     Ref<Sampler> mSampler;
632     Target       mTarget;
633     //TODO: extras
634     //TODO: extensions
635   };
636
637   std::vector<Sampler> mSamplers;
638   std::vector<Channel> mChannels;
639 };
640
641 struct Scene : Named
642 {
643   std::vector<Ref<Node>> mNodes;
644 };
645
646 enum ExtensionFlags : uint32_t
647 {
648   NONE                   = Dali::Scene3D::Loader::NthBit(0),
649   KHR_MESH_QUANTIZATION  = Dali::Scene3D::Loader::NthBit(1), // See https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_texture_transform
650   KHR_TEXTURE_TRANSFORM  = Dali::Scene3D::Loader::NthBit(2), // See https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_mesh_quantization
651   KHR_MATERIALS_IOR      = Dali::Scene3D::Loader::NthBit(3), // See https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_ior
652   KHR_MATERIALS_SPECULAR = Dali::Scene3D::Loader::NthBit(4), // See https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_specular
653
654 };
655
656 struct Document
657 {
658   Asset mAsset;
659
660   std::vector<Buffer>     mBuffers;
661   std::vector<BufferView> mBufferViews;
662   std::vector<Accessor>   mAccessors;
663
664   std::vector<Image>    mImages;
665   std::vector<Sampler>  mSamplers;
666   std::vector<Texture>  mTextures;
667   std::vector<Material> mMaterials;
668
669   std::vector<Mesh> mMeshes;
670   std::vector<Skin> mSkins;
671
672   std::vector<Camera> mCameras;
673   std::vector<Node>   mNodes;
674
675   std::vector<Animation> mAnimations;
676
677   std::vector<std::string_view> mExtensionsUsed;
678   std::vector<std::string_view> mExtensionsRequired;
679
680   uint32_t mExtensionFlags{0};
681
682   std::vector<Scene> mScenes;
683   Ref<Scene>         mScene;
684
685   Document()                = default;
686   Document(const Document&) = delete;
687   Document(Document&&)      = default;
688
689   Document& operator=(const Document&) = delete;
690   Document& operator=(Document&&) = default;
691 };
692
693 /**
694  * @brief Provides a json::Property<T>::ReadFn for interpreting unsigned integers
695  *  as a Ref<U> into a std::vector<U> data member of a type T.
696  */
697 template<typename T>
698 struct RefReader
699 {
700   static T* sObject;
701
702   template<typename U, std::vector<U> T::*V>
703   static Ref<U> Read(const json_value_s& j)
704   {
705     uint32_t index = json::Read::Number<uint32_t>(j);
706     return Ref<U>(sObject->*V, index);
707   }
708 };
709
710 template<typename T>
711 T* RefReader<T>::sObject = nullptr;
712
713 /**
714  * @brief Convenience method to set the object for RefReader.
715  */
716 template<typename T>
717 void SetRefReaderObject(T& object)
718 {
719   RefReader<T>::sObject = &object;
720 }
721
722 /**
723  * @brief Reads a string and attempts to convert it to an enum.
724  * @note The enum must: 1, be called Type, nested to T, 2, provide a FromString static method taking a const char*
725  *  (string data) and a size_t (string length) and returning T::Type.
726  */
727 template<typename T> // T must have a nested enum called Type and a static Type FromString(const char*) method.
728 typename T::Type ReadStringEnum(const json_value_s& j)
729 {
730   auto str = json::Read::StringView(j);
731
732   return T::FromString(str.data(), str.size());
733 }
734
735 /**
736  * @brief Convenience method to attempt to create a Dali vector type T from an array of floats.
737  * @note T must provide an AsFloat() member method returning the non-const array of its
738  *  float components.
739  */
740 template<typename T>
741 inline T ReadDaliVector(const json_value_s& j)
742 {
743   std::vector<float> floats = json::Read::Array<float, json::Read::Number<float>>(j);
744   T                  result;
745   std::copy(floats.begin(), std::min(floats.end(), floats.begin() + sizeof(T) / sizeof(float)), result.AsFloat());
746   return result;
747 }
748
749 /**
750  * @brief Convenience method to attemt to read a Quaternion, which implicitly converts
751  *  to Vector4 but fails to provide an AsFloat() method.
752  */
753 Dali::Quaternion ReadQuaternion(const json_value_s& j);
754
755 } // namespace gltf2
756
757 #endif //DALI_SCENE3D_LOADER_GLTF2_ASSET_H_