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