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