1 #ifndef DALI_SCENE3D_LOADER_GLTF2_ASSET_H_
2 #define DALI_SCENE3D_LOADER_GLTF2_ASSET_H_
4 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
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>
35 #define ENUM_STRING_MAPPING(t, x) \
40 #define ENUM_TYPE_FROM_STRING(structName, table) \
41 structName::Type structName::FromString(const char* s, size_t len) \
43 std::string target(s, len); \
44 std::transform(target.begin(), target.end(), target.begin(), ::toupper); \
46 auto iFind = table.find(std::string_view(target.c_str(), len)); \
47 if(iFind != table.end()) \
49 return iFind->second; \
51 return structName::INVALID; \
56 using Index = Dali::Scene3D::Loader::Index;
57 constexpr float UNDEFINED_FLOAT_VALUE = -1.0f; ///< Special marker for some non-negative only float values.
64 Ref(std::vector<T>& v, Index i)
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.
75 Index GetIndex() const
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.
84 void UpdateVector(std::vector<T>& v)
91 return mVector != nullptr;
95 return &(*mVector)[mIndex];
99 return (*mVector)[mIndex];
102 bool operator==(const Ref<T>& other) const
104 return mVector == other.mVector && mIndex == other.mIndex;
107 bool operator!=(const Ref<T>& other) const
109 return !operator==(other);
113 std::vector<T>* mVector = nullptr;
114 Index mIndex = Dali::Scene3D::Loader::INVALID_INDEX;
119 std::string_view mGenerator;
120 std::string_view mVersion;
128 UNSIGNED_BYTE = 5121,
130 UNSIGNED_SHORT = 5123,
136 static bool IsUnsigned(Type t);
137 static uint32_t Size(Type t);
139 Component() = delete;
156 static uint32_t ElementCount(Type t);
158 static Type FromString(const char* s, size_t len);
160 AccessorType() = delete;
173 static Type FromString(const char* s, size_t len);
175 AlphaMode() = delete;
192 using HashType = uint32_t;
195 // +--+--+--+--+--+--+--+
196 // |31|30|29|28|27|..| 0| bit index
197 // +--+--+--+--+--+--+--+
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};
207 static HashType ToHash(Type type, bool set, HashType setIndex)
209 return ((set << SET_SHIFT) & SET_MASK) | ((static_cast<HashType>(type) << TYPE_SHIFT) & TYPE_MASK) | (setIndex & SET_ID_MASK);
212 static Attribute::Type TypeFromHash(HashType hash)
214 return static_cast<Type>((hash & TYPE_MASK) >> TYPE_SHIFT);
217 static bool SetFromHash(HashType hash)
219 return (hash & SET_SHIFT) != 0;
222 static HashType SetIdFromHash(HashType hash)
224 return (hash & SET_ID_MASK);
228 * Convert to Type + setIndex, where setIndex is N for that attr, e.g. "JOINTS_1" => {JOINTS_N, 1}
230 static HashType HashFromString(const char* s, size_t len);
233 * Convert to type only, there is no set for POSITION, NORMALS or TANGENT.
235 static Attribute::Type TargetFromString(const char* s, size_t len);
237 Attribute() = delete;
242 uint32_t mByteLength;
243 std::string_view mUri;
255 ARRAY_BUFFER = 34962,
256 ELEMENT_ARRAY_BUFFER = 34963
263 uint32_t mByteOffset = 0;
264 uint32_t mByteLength;
265 uint32_t mByteStride = 0; // if 0 after reading, it needs to be calculated
271 struct BufferViewClient
273 Ref<BufferView> mBufferView;
274 uint32_t mByteOffset = 0;
277 struct ComponentTypedBufferViewClient : BufferViewClient
279 Component::Type mComponentType = Component::INVALID;
281 uint32_t GetBytesPerComponent() const;
286 std::string_view mName;
292 struct Accessor : ComponentTypedBufferViewClient, Named
297 ComponentTypedBufferViewClient mIndices;
298 BufferViewClient mValues;
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;
312 uint32_t GetElementSizeBytes() const
314 return GetBytesPerComponent() * AccessorType::ElementCount(mType);
317 uint32_t GetBytesLength() const
319 return GetElementSizeBytes() * mCount;
322 void SetSparse(const Sparse& s)
324 mSparse.reset(new Sparse(s));
330 std::string_view mUri;
331 std::string_view mMimeType;
332 Ref<BufferView> mBufferView;
343 NEAREST_MIPMAP_NEAREST = 9984,
344 NEAREST_MIPMAP_LINEAR = 9985,
345 LINEAR_MIPMAP_NEAREST = 9986,
346 LINEAR_MIPMAP_LINEAR = 9987,
357 CLAMP_TO_EDGE = 33071,
358 MIRRORED_REPEAT = 33648,
366 Filter::Type mMinFilter = Filter::LINEAR;
367 Filter::Type mMagFilter = Filter::LINEAR;
368 Wrap::Type mWrapS = Wrap::REPEAT;
369 Wrap::Type mWrapT = Wrap::REPEAT;
377 Ref<Sampler> mSampler;
380 struct TextureTransform
382 float mRotation = 0.0f;
383 Dali::Vector2 mUvOffset = Dali::Vector2::ZERO;
384 Dali::Vector2 mUvScale = Dali::Vector2::ONE;
385 uint32_t mTexCoord = 0u;
387 operator bool() const
389 return !Dali::EqualsZero(mRotation) || mUvOffset != Dali::Vector2::ZERO || mUvScale != Dali::Vector2::ONE || mTexCoord != 0u;
392 const Dali::Matrix3 GetTransform() const
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);
399 return translation * rotation * scale;
403 struct TextureExtensions
405 TextureTransform mTextureTransform;
407 operator bool() const
409 return mTextureTransform;
415 Ref<gltf2::Texture> mTexture;
416 uint32_t mTexCoord = 0;
418 float mStrength = 1.f;
420 TextureExtensions mTextureExtensions;
422 operator bool() const
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
434 float mIor = UNDEFINED_FLOAT_VALUE;
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
441 struct MaterialSpecular
443 float mSpecularFactor = 1.0f;
444 TextureInfo mSpecularTexture;
445 Dali::Vector3 mSpecularColorFactor = Dali::Vector3::ONE;
446 TextureInfo mSpecularColorTexture;
449 struct MaterialExtensions
451 MaterialSpecular mMaterialSpecular;
452 MaterialIor mMaterialIor;
455 struct Material : Named
457 struct Pbr // MetallicRoughness
459 Dali::Vector4 mBaseColorFactor = Dali::Vector4::ONE;
460 TextureInfo mBaseColorTexture;
461 float mMetallicFactor = 1.f;
462 float mRoughnessFactor = 1.f;
463 TextureInfo mMetallicRoughnessTexture;
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;
478 MaterialExtensions mMaterialExtensions;
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;
504 //TODO: [morph] targets
511 std::vector<std::string_view> mTargetNames;
518 std::vector<std::string_view> mSXRTargetsNames;
519 std::vector<std::string_view> mAvatarShapeNames;
524 std::vector<Primitive> mPrimitives;
525 std::vector<float> mWeights;
527 Extensions mExtensions;
534 Ref<Accessor> mInverseBindMatrices;
536 std::vector<Ref<Node>> mJoints;
541 struct Camera : Named
545 float mAspectRatio = UNDEFINED_FLOAT_VALUE;
546 float mYFov = UNDEFINED_FLOAT_VALUE;
547 float mZFar = UNDEFINED_FLOAT_VALUE;
548 float mZNear = UNDEFINED_FLOAT_VALUE;
555 float mXMag = UNDEFINED_FLOAT_VALUE;
556 float mYMag = UNDEFINED_FLOAT_VALUE;
557 float mZFar = UNDEFINED_FLOAT_VALUE;
558 float mZNear = UNDEFINED_FLOAT_VALUE;
563 std::string_view mType;
564 Perspective mPerspective;
565 Orthographic mOrthographic;
572 Dali::Vector3 mTranslation = Dali::Vector3::ZERO;
573 Dali::Quaternion mRotation = Dali::Quaternion::IDENTITY;
574 Dali::Vector3 mScale = Dali::Vector3::ONE;
577 std::vector<Ref<Node>> mChildren;
581 //TODO: [morph] weights
585 void SetMatrix(const Dali::Matrix& m);
588 struct Animation : Named
601 static Type FromString(const char* s, size_t len);
604 Ref<Accessor> mInput;
605 Ref<Accessor> mOutput;
606 Interpolation::Type mInterpolation;
625 static Type FromString(const char* s, size_t len);
631 Ref<Sampler> mSampler;
637 std::vector<Sampler> mSamplers;
638 std::vector<Channel> mChannels;
643 std::vector<Ref<Node>> mNodes;
646 enum ExtensionFlags : uint32_t
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
660 std::vector<Buffer> mBuffers;
661 std::vector<BufferView> mBufferViews;
662 std::vector<Accessor> mAccessors;
664 std::vector<Image> mImages;
665 std::vector<Sampler> mSamplers;
666 std::vector<Texture> mTextures;
667 std::vector<Material> mMaterials;
669 std::vector<Mesh> mMeshes;
670 std::vector<Skin> mSkins;
672 std::vector<Camera> mCameras;
673 std::vector<Node> mNodes;
675 std::vector<Animation> mAnimations;
677 std::vector<std::string_view> mExtensionsUsed;
678 std::vector<std::string_view> mExtensionsRequired;
680 uint32_t mExtensionFlags{0};
682 std::vector<Scene> mScenes;
685 Document() = default;
686 Document(const Document&) = delete;
687 Document(Document&&) = default;
689 Document& operator=(const Document&) = delete;
690 Document& operator=(Document&&) = default;
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.
702 template<typename U, std::vector<U> T::*V>
703 static Ref<U> Read(const json_value_s& j)
705 uint32_t index = json::Read::Number<uint32_t>(j);
706 return Ref<U>(sObject->*V, index);
711 T* RefReader<T>::sObject = nullptr;
714 * @brief Convenience method to set the object for RefReader.
717 void SetRefReaderObject(T& object)
719 RefReader<T>::sObject = &object;
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.
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)
730 auto str = json::Read::StringView(j);
732 return T::FromString(str.data(), str.size());
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
741 inline T ReadDaliVector(const json_value_s& j)
743 std::vector<float> floats = json::Read::Array<float, json::Read::Number<float>>(j);
745 std::copy(floats.begin(), std::min(floats.end(), floats.begin() + sizeof(T) / sizeof(float)), result.AsFloat());
750 * @brief Convenience method to attemt to read a Quaternion, which implicitly converts
751 * to Vector4 but fails to provide an AsFloat() method.
753 Dali::Quaternion ReadQuaternion(const json_value_s& j);
757 #endif //DALI_SCENE3D_LOADER_GLTF2_ASSET_H_