Fix many svace issues at dali-toolkit (integer overflow + etc)
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / loader / gltf2-util.cpp
index 670af82..6e572b7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali-scene3d/internal/loader/gltf2-util.h>
 
 // EXTERNAL INCLUDES
+#include <dali-scene3d/public-api/loader/utils.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/devel-api/threading/mutex.h>
 #include <dali/integration-api/debug.h>
+#include <limits> ///< for std::numeric_limits
 
 using namespace Dali::Scene3D::Loader;
 
@@ -44,19 +48,15 @@ static const Geometry::Type GLTF2_TO_DALI_PRIMITIVES[]{
   Geometry::TRIANGLE_STRIP,
   Geometry::TRIANGLE_FAN}; //...because Dali swaps the last two.
 
-static struct AttributeMapping
-{
-  gltf2::Attribute::Type   mType;
-  MeshDefinition::Accessor MeshDefinition::*mAccessor;
-  uint16_t                                  mElementSizeRequired;
-} ATTRIBUTE_MAPPINGS[]{
-  {gltf2::Attribute::NORMAL, &MeshDefinition::mNormals, sizeof(Vector3)},
-  {gltf2::Attribute::TANGENT, &MeshDefinition::mTangents, sizeof(Vector3)},
-  {gltf2::Attribute::TEXCOORD_0, &MeshDefinition::mTexCoords, sizeof(Vector2)},
-  {gltf2::Attribute::COLOR_0, &MeshDefinition::mColors, sizeof(Vector4)},
-  {gltf2::Attribute::JOINTS_0, &MeshDefinition::mJoints0, sizeof(Vector4)},
-  {gltf2::Attribute::WEIGHTS_0, &MeshDefinition::mWeights0, sizeof(Vector4)},
+static const Dali::Scripting::StringEnum EXTENSION_STRING_TABLE[] =
+  {
+    {"NONE", gltf2::ExtensionFlags::NONE},
+    {"KHR_mesh_quantization", gltf2::ExtensionFlags::KHR_MESH_QUANTIZATION},
+    {"KHR_texture_transform", gltf2::ExtensionFlags::KHR_TEXTURE_TRANSFORM},
+    {"KHR_materials_ior", gltf2::ExtensionFlags::KHR_MATERIALS_IOR},
+    {"KHR_materials_specular", gltf2::ExtensionFlags::KHR_MATERIALS_SPECULAR},
 };
+static const unsigned int EXTENSION_STRING_TABLE_COUNT = sizeof(EXTENSION_STRING_TABLE) / sizeof(EXTENSION_STRING_TABLE[0]);
 
 std::vector<gltf2::Animation> ReadAnimationArray(const json_value_s& j)
 {
@@ -83,161 +83,196 @@ void ApplyAccessorMinMax(const gltf2::Accessor& accessor, float* values)
 const json::Reader<gltf2::Buffer>& GetBufferReader()
 {
   static const auto BUFFER_READER = std::move(json::Reader<gltf2::Buffer>()
-                                       .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::Buffer::mByteLength))
-                                       .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Buffer::mUri)));
+                                                .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::Buffer::mByteLength))
+                                                .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Buffer::mUri)));
   return BUFFER_READER;
 }
 
 const json::Reader<gltf2::BufferView>& GetBufferViewReader()
 {
   static const auto BUFFER_VIEW_READER = std::move(json::Reader<gltf2::BufferView>()
-                                            .Register(*json::MakeProperty("buffer", gltf2::RefReader<gltf2::Document>::Read<gltf2::Buffer, &gltf2::Document::mBuffers>, &gltf2::BufferView::mBuffer))
-                                            .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteOffset))
-                                            .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteLength))
-                                            .Register(*json::MakeProperty("byteStride", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteStride))
-                                            .Register(*json::MakeProperty("target", json::Read::Number<uint32_t>, &gltf2::BufferView::mTarget)));
+                                                     .Register(*json::MakeProperty("buffer", gltf2::RefReader<gltf2::Document>::Read<gltf2::Buffer, &gltf2::Document::mBuffers>, &gltf2::BufferView::mBuffer))
+                                                     .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteOffset))
+                                                     .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteLength))
+                                                     .Register(*json::MakeProperty("byteStride", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteStride))
+                                                     .Register(*json::MakeProperty("target", json::Read::Number<uint32_t>, &gltf2::BufferView::mTarget)));
   return BUFFER_VIEW_READER;
 }
 
 const json::Reader<gltf2::BufferViewClient>& GetBufferViewClientReader()
 {
   static const auto BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::BufferViewClient>()
-                                                   .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::BufferViewClient::mBufferView))
-                                                   .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferViewClient::mByteOffset)));
+                                                            .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::BufferViewClient::mBufferView))
+                                                            .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferViewClient::mByteOffset)));
   return BUFFER_VIEW_CLIENT_READER;
 }
 
 const json::Reader<gltf2::ComponentTypedBufferViewClient>& GetComponentTypedBufferViewClientReader()
 {
   static const auto COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::ComponentTypedBufferViewClient>()
-                                                                   .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, gltf2::Ref<gltf2::BufferView>>("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::ComponentTypedBufferViewClient::mBufferView))
-                                                                   .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, uint32_t>("byteOffset", json::Read::Number<uint32_t>, &gltf2::ComponentTypedBufferViewClient::mByteOffset))
-                                                                   .Register(*json::MakeProperty("componentType", json::Read::Enum<gltf2::Component::Type>, &gltf2::ComponentTypedBufferViewClient::mComponentType)));
+                                                                            .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, gltf2::Ref<gltf2::BufferView>>("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::ComponentTypedBufferViewClient::mBufferView))
+                                                                            .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, uint32_t>("byteOffset", json::Read::Number<uint32_t>, &gltf2::ComponentTypedBufferViewClient::mByteOffset))
+                                                                            .Register(*json::MakeProperty("componentType", json::Read::Enum<gltf2::Component::Type>, &gltf2::ComponentTypedBufferViewClient::mComponentType)));
   return COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER;
 }
 
 const json::Reader<gltf2::Accessor::Sparse>& GetAccessorSparseReader()
 {
   static const auto ACCESSOR_SPARSE_READER = std::move(json::Reader<gltf2::Accessor::Sparse>()
-                                                .Register(*json::MakeProperty("count", json::Read::Number<uint32_t>, &gltf2::Accessor::Sparse::mCount))
-                                                .Register(*json::MakeProperty("indices", json::ObjectReader<gltf2::ComponentTypedBufferViewClient>::Read, &gltf2::Accessor::Sparse::mIndices))
-                                                .Register(*json::MakeProperty("values", json::ObjectReader<gltf2::BufferViewClient>::Read, &gltf2::Accessor::Sparse::mValues)));
+                                                         .Register(*json::MakeProperty("count", json::Read::Number<uint32_t>, &gltf2::Accessor::Sparse::mCount))
+                                                         .Register(*json::MakeProperty("indices", json::ObjectReader<gltf2::ComponentTypedBufferViewClient>::Read, &gltf2::Accessor::Sparse::mIndices))
+                                                         .Register(*json::MakeProperty("values", json::ObjectReader<gltf2::BufferViewClient>::Read, &gltf2::Accessor::Sparse::mValues)));
   return ACCESSOR_SPARSE_READER;
 }
 
 const json::Reader<gltf2::Accessor>& GetAccessorReader()
 {
   static const auto ACCESSOR_READER = std::move(json::Reader<gltf2::Accessor>()
-                                         .Register(*new json::Property<gltf2::Accessor, gltf2::Ref<gltf2::BufferView>>("bufferView",
-                                                                                                                       gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>,
-                                                                                                                       &gltf2::Accessor::mBufferView))
-                                         .Register(*new json::Property<gltf2::Accessor, uint32_t>("byteOffset",
-                                                                                                  json::Read::Number<uint32_t>,
-                                                                                                  &gltf2::Accessor::mByteOffset))
-                                         .Register(*new json::Property<gltf2::Accessor, gltf2::Component::Type>("componentType",
-                                                                                                                json::Read::Enum<gltf2::Component::Type>,
-                                                                                                                &gltf2::Accessor::mComponentType))
-                                         .Register(*new json::Property<gltf2::Accessor, std::string_view>("name", json::Read::StringView, &gltf2::Accessor::mName))
-                                         .Register(*json::MakeProperty("count", json::Read::Number<uint32_t>, &gltf2::Accessor::mCount))
-                                         .Register(*json::MakeProperty("normalized", json::Read::Boolean, &gltf2::Accessor::mNormalized))
-                                         .Register(*json::MakeProperty("type", gltf2::ReadStringEnum<gltf2::AccessorType>, &gltf2::Accessor::mType))
-                                         .Register(*json::MakeProperty("min", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMin))
-                                         .Register(*json::MakeProperty("max", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMax))
-                                         .Register(*new json::Property<gltf2::Accessor, gltf2::Accessor::Sparse>("sparse", json::ObjectReader<gltf2::Accessor::Sparse>::Read, &gltf2::Accessor::SetSparse)));
+                                                  .Register(*new json::Property<gltf2::Accessor, gltf2::Ref<gltf2::BufferView>>("bufferView",
+                                                                                                                                gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>,
+                                                                                                                                &gltf2::Accessor::mBufferView))
+                                                  .Register(*new json::Property<gltf2::Accessor, uint32_t>("byteOffset", json::Read::Number<uint32_t>, &gltf2::Accessor::mByteOffset))
+                                                  .Register(*new json::Property<gltf2::Accessor, gltf2::Component::Type>("componentType",
+                                                                                                                         json::Read::Enum<gltf2::Component::Type>,
+                                                                                                                         &gltf2::Accessor::mComponentType))
+                                                  .Register(*new json::Property<gltf2::Accessor, std::string_view>("name", json::Read::StringView, &gltf2::Accessor::mName))
+                                                  .Register(*json::MakeProperty("count", json::Read::Number<uint32_t>, &gltf2::Accessor::mCount))
+                                                  .Register(*json::MakeProperty("normalized", json::Read::Boolean, &gltf2::Accessor::mNormalized))
+                                                  .Register(*json::MakeProperty("type", gltf2::ReadStringEnum<gltf2::AccessorType>, &gltf2::Accessor::mType))
+                                                  .Register(*json::MakeProperty("min", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMin))
+                                                  .Register(*json::MakeProperty("max", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMax))
+                                                  .Register(*new json::Property<gltf2::Accessor, gltf2::Accessor::Sparse>("sparse", json::ObjectReader<gltf2::Accessor::Sparse>::Read, &gltf2::Accessor::SetSparse)));
   return ACCESSOR_READER;
 }
 
 const json::Reader<gltf2::Image>& GetImageReader()
 {
   static const auto IMAGE_READER = std::move(json::Reader<gltf2::Image>()
-                                      .Register(*new json::Property<gltf2::Image, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
-                                      .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Image::mUri))
-                                      .Register(*json::MakeProperty("mimeType", json::Read::StringView, &gltf2::Image::mMimeType))
-                                      .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::Image::mBufferView)));
+                                               .Register(*new json::Property<gltf2::Image, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
+                                               .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Image::mUri))
+                                               .Register(*json::MakeProperty("mimeType", json::Read::StringView, &gltf2::Image::mMimeType))
+                                               .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::Image::mBufferView)));
   return IMAGE_READER;
 }
 
 const json::Reader<gltf2::Sampler>& GetSamplerReader()
 {
   static const auto SAMPLER_READER = std::move(json::Reader<gltf2::Sampler>()
-                                        .Register(*json::MakeProperty("minFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMinFilter))
-                                        .Register(*json::MakeProperty("magFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMagFilter))
-                                        .Register(*json::MakeProperty("wrapS", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapS))
-                                        .Register(*json::MakeProperty("wrapT", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapT)));
+                                                 .Register(*json::MakeProperty("minFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMinFilter))
+                                                 .Register(*json::MakeProperty("magFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMagFilter))
+                                                 .Register(*json::MakeProperty("wrapS", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapS))
+                                                 .Register(*json::MakeProperty("wrapT", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapT)));
   return SAMPLER_READER;
 }
 
 const json::Reader<gltf2::Texture>& GetTextureReader()
 {
   static const auto TEXURE_READER = std::move(json::Reader<gltf2::Texture>()
-                                       .Register(*json::MakeProperty("source", gltf2::RefReader<gltf2::Document>::Read<gltf2::Image, &gltf2::Document::mImages>, &gltf2::Texture::mSource))
-                                       .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Document>::Read<gltf2::Sampler, &gltf2::Document::mSamplers>, &gltf2::Texture::mSampler)));
+                                                .Register(*json::MakeProperty("source", gltf2::RefReader<gltf2::Document>::Read<gltf2::Image, &gltf2::Document::mImages>, &gltf2::Texture::mSource))
+                                                .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Document>::Read<gltf2::Sampler, &gltf2::Document::mSamplers>, &gltf2::Texture::mSampler)));
   return TEXURE_READER;
 }
 
+const json::Reader<gltf2::TextureTransform>& GetTextureTransformReader()
+{
+  static const auto TEXURE_TRANSFORM_READER = std::move(json::Reader<gltf2::TextureTransform>()
+                                                          .Register(*json::MakeProperty("rotation", json::Read::Number<float>, &gltf2::TextureTransform::mRotation))
+                                                          .Register(*json::MakeProperty("offset", gltf2::ReadDaliVector<Vector2>, &gltf2::TextureTransform::mUvOffset))
+                                                          .Register(*json::MakeProperty("scale", gltf2::ReadDaliVector<Vector2>, &gltf2::TextureTransform::mUvScale))
+                                                          .Register(*json::MakeProperty("texCoord", json::Read::Number<uint32_t>, &gltf2::TextureTransform::mTexCoord)));
+  return TEXURE_TRANSFORM_READER;
+}
+
+const json::Reader<gltf2::TextureExtensions>& GetTextureExtensionsReader()
+{
+  static const auto TEXTURE_EXTENSION_READER = std::move(json::Reader<gltf2::TextureExtensions>()
+                                                           .Register(*json::MakeProperty("KHR_texture_transform", json::ObjectReader<gltf2::TextureTransform>::Read, &gltf2::TextureExtensions::mTextureTransform)));
+  return TEXTURE_EXTENSION_READER;
+}
+
 const json::Reader<gltf2::TextureInfo>& GetTextureInfoReader()
 {
   static const auto TEXURE_INFO_READER = std::move(json::Reader<gltf2::TextureInfo>()
-                                            .Register(*json::MakeProperty("index", gltf2::RefReader<gltf2::Document>::Read<gltf2::Texture, &gltf2::Document::mTextures>, &gltf2::TextureInfo::mTexture))
-                                            .Register(*json::MakeProperty("texCoord", json::Read::Number<uint32_t>, &gltf2::TextureInfo::mTexCoord))
-                                            .Register(*json::MakeProperty("scale", json::Read::Number<float>, &gltf2::TextureInfo::mScale))
-                                            .Register(*json::MakeProperty("strength", json::Read::Number<float>, &gltf2::TextureInfo::mStrength)));
+                                                     .Register(*json::MakeProperty("index", gltf2::RefReader<gltf2::Document>::Read<gltf2::Texture, &gltf2::Document::mTextures>, &gltf2::TextureInfo::mTexture))
+                                                     .Register(*json::MakeProperty("texCoord", json::Read::Number<uint32_t>, &gltf2::TextureInfo::mTexCoord))
+                                                     .Register(*json::MakeProperty("scale", json::Read::Number<float>, &gltf2::TextureInfo::mScale))
+                                                     .Register(*json::MakeProperty("strength", json::Read::Number<float>, &gltf2::TextureInfo::mStrength))
+                                                     .Register(*json::MakeProperty("extensions", json::ObjectReader<gltf2::TextureExtensions>::Read, &gltf2::TextureInfo::mTextureExtensions)));
   return TEXURE_INFO_READER;
 }
 
 const json::Reader<gltf2::Material::Pbr>& GetMaterialPbrReader()
 {
   static const auto MATERIAL_PBR_READER = std::move(json::Reader<gltf2::Material::Pbr>()
-                                             .Register(*json::MakeProperty("baseColorFactor", gltf2::ReadDaliVector<Vector4>, &gltf2::Material::Pbr::mBaseColorFactor))
-                                             .Register(*json::MakeProperty("baseColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mBaseColorTexture))
-                                             .Register(*json::MakeProperty("metallicFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mMetallicFactor))
-                                             .Register(*json::MakeProperty("roughnessFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mRoughnessFactor))
-                                             .Register(*json::MakeProperty("metallicRoughnessTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mMetallicRoughnessTexture)));
+                                                      .Register(*json::MakeProperty("baseColorFactor", gltf2::ReadDaliVector<Vector4>, &gltf2::Material::Pbr::mBaseColorFactor))
+                                                      .Register(*json::MakeProperty("baseColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mBaseColorTexture))
+                                                      .Register(*json::MakeProperty("metallicFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mMetallicFactor))
+                                                      .Register(*json::MakeProperty("roughnessFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mRoughnessFactor))
+                                                      .Register(*json::MakeProperty("metallicRoughnessTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mMetallicRoughnessTexture)));
   return MATERIAL_PBR_READER;
 }
 
 const json::Reader<gltf2::MaterialSpecular>& GetMaterialSpecularReader()
 {
   static const auto MATERIAL_SPECULAR_READER = std::move(json::Reader<gltf2::MaterialSpecular>()
-                                                  .Register(*json::MakeProperty("specularFactor", json::Read::Number<float>, &gltf2::MaterialSpecular::mSpecularFactor))
-                                                  .Register(*json::MakeProperty("specularTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularTexture))
-                                                  .Register(*json::MakeProperty("specularColorFactor", gltf2::ReadDaliVector<Vector3>, &gltf2::MaterialSpecular::mSpecularColorFactor))
-                                                  .Register(*json::MakeProperty("specularColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularColorTexture)));
+                                                           .Register(*json::MakeProperty("specularFactor", json::Read::Number<float>, &gltf2::MaterialSpecular::mSpecularFactor))
+                                                           .Register(*json::MakeProperty("specularTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularTexture))
+                                                           .Register(*json::MakeProperty("specularColorFactor", gltf2::ReadDaliVector<Vector3>, &gltf2::MaterialSpecular::mSpecularColorFactor))
+                                                           .Register(*json::MakeProperty("specularColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularColorTexture)));
   return MATERIAL_SPECULAR_READER;
 }
 
 const json::Reader<gltf2::MaterialIor>& GetMaterialIorReader()
 {
   static const auto MATERIAL_IOR_READER = std::move(json::Reader<gltf2::MaterialIor>()
-                                             .Register(*json::MakeProperty("ior", json::Read::Number<float>, &gltf2::MaterialIor::mIor)));
+                                                      .Register(*json::MakeProperty("ior", json::Read::Number<float>, &gltf2::MaterialIor::mIor)));
   return MATERIAL_IOR_READER;
 }
 
 const json::Reader<gltf2::MaterialExtensions>& GetMaterialExtensionsReader()
 {
   static const auto MATERIAL_EXTENSION_READER = std::move(json::Reader<gltf2::MaterialExtensions>()
-                                                   .Register(*json::MakeProperty("KHR_materials_ior", json::ObjectReader<gltf2::MaterialIor>::Read, &gltf2::MaterialExtensions::mMaterialIor))
-                                                   .Register(*json::MakeProperty("KHR_materials_specular", json::ObjectReader<gltf2::MaterialSpecular>::Read, &gltf2::MaterialExtensions::mMaterialSpecular)));
+                                                            .Register(*json::MakeProperty("KHR_materials_ior", json::ObjectReader<gltf2::MaterialIor>::Read, &gltf2::MaterialExtensions::mMaterialIor))
+                                                            .Register(*json::MakeProperty("KHR_materials_specular", json::ObjectReader<gltf2::MaterialSpecular>::Read, &gltf2::MaterialExtensions::mMaterialSpecular)));
   return MATERIAL_EXTENSION_READER;
 }
 
 const json::Reader<gltf2::Material>& GetMaterialReader()
 {
   static const auto MATERIAL_READER = std::move(json::Reader<gltf2::Material>()
-                                         .Register(*new json::Property<gltf2::Material, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
-                                         .Register(*json::MakeProperty("pbrMetallicRoughness", json::ObjectReader<gltf2::Material::Pbr>::Read, &gltf2::Material::mPbrMetallicRoughness))
-                                         .Register(*json::MakeProperty("normalTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mNormalTexture))
-                                         .Register(*json::MakeProperty("occlusionTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mOcclusionTexture))
-                                         .Register(*json::MakeProperty("emissiveTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mEmissiveTexture))
-                                         .Register(*json::MakeProperty("emissiveFactor", gltf2::ReadDaliVector<Vector3>, &gltf2::Material::mEmissiveFactor))
-                                         .Register(*json::MakeProperty("alphaMode", gltf2::ReadStringEnum<gltf2::AlphaMode>, &gltf2::Material::mAlphaMode))
-                                         .Register(*json::MakeProperty("alphaCutoff", json::Read::Number<float>, &gltf2::Material::mAlphaCutoff))
-                                         .Register(*json::MakeProperty("doubleSided", json::Read::Boolean, &gltf2::Material::mDoubleSided))
-                                         .Register(*json::MakeProperty("extensions", json::ObjectReader<gltf2::MaterialExtensions>::Read, &gltf2::Material::mMaterialExtensions)));
+                                                  .Register(*new json::Property<gltf2::Material, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
+                                                  .Register(*json::MakeProperty("pbrMetallicRoughness", json::ObjectReader<gltf2::Material::Pbr>::Read, &gltf2::Material::mPbrMetallicRoughness))
+                                                  .Register(*json::MakeProperty("normalTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mNormalTexture))
+                                                  .Register(*json::MakeProperty("occlusionTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mOcclusionTexture))
+                                                  .Register(*json::MakeProperty("emissiveTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mEmissiveTexture))
+                                                  .Register(*json::MakeProperty("emissiveFactor", gltf2::ReadDaliVector<Vector3>, &gltf2::Material::mEmissiveFactor))
+                                                  .Register(*json::MakeProperty("alphaMode", gltf2::ReadStringEnum<gltf2::AlphaMode>, &gltf2::Material::mAlphaMode))
+                                                  .Register(*json::MakeProperty("alphaCutoff", json::Read::Number<float>, &gltf2::Material::mAlphaCutoff))
+                                                  .Register(*json::MakeProperty("doubleSided", json::Read::Boolean, &gltf2::Material::mDoubleSided))
+                                                  .Register(*json::MakeProperty("extensions", json::ObjectReader<gltf2::MaterialExtensions>::Read, &gltf2::Material::mMaterialExtensions)));
   return MATERIAL_READER;
 }
 
-std::map<gltf2::Attribute::Type, gltf2::Ref<gltf2::Accessor>> ReadMeshPrimitiveAttributes(const json_value_s& j)
+std::map<gltf2::Attribute::HashType, gltf2::Ref<gltf2::Accessor>> ReadMeshPrimitiveAttributes(const json_value_s& j)
+{
+  auto&                                                             jsonObject = json::Cast<json_object_s>(j);
+  std::map<gltf2::Attribute::HashType, gltf2::Ref<gltf2::Accessor>> result;
+
+  auto element = jsonObject.start;
+  while(element)
+  {
+    auto jsonString = *element->name;
+
+    gltf2::Attribute::HashType hash = gltf2::Attribute::HashFromString(jsonString.string, jsonString.string_size);
+
+    result[hash] =
+      gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>(*element->value);
+    element = element->next;
+  }
+  return result;
+}
+
+std::map<gltf2::Attribute::Type, gltf2::Ref<gltf2::Accessor>> ReadMeshPrimitiveAttributes2(const json_value_s& j)
 {
   auto&                                                         jsonObject = json::Cast<json_object_s>(j);
   std::map<gltf2::Attribute::Type, gltf2::Ref<gltf2::Accessor>> result;
@@ -245,9 +280,11 @@ std::map<gltf2::Attribute::Type, gltf2::Ref<gltf2::Accessor>> ReadMeshPrimitiveA
   auto element = jsonObject.start;
   while(element)
   {
-    auto jsonString                                                                 = *element->name;
-    result[gltf2::Attribute::FromString(jsonString.string, jsonString.string_size)] = gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>(*element->value);
-    element                                                                         = element->next;
+    auto jsonString = *element->name;
+
+    result[gltf2::Attribute::TargetFromString(jsonString.string, jsonString.string_size)] = gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>(*element->value);
+
+    element = element->next;
   }
   return result;
 }
@@ -262,7 +299,7 @@ std::vector<std::map<gltf2::Attribute::Type, gltf2::Ref<gltf2::Accessor>>> ReadM
   auto element = jsonObject.start;
   while(element)
   {
-    result.push_back(std::move(ReadMeshPrimitiveAttributes(*element->value)));
+    result.push_back(std::move(ReadMeshPrimitiveAttributes2(*element->value)));
     element = element->next;
   }
 
@@ -272,177 +309,224 @@ std::vector<std::map<gltf2::Attribute::Type, gltf2::Ref<gltf2::Accessor>>> ReadM
 const json::Reader<gltf2::Mesh::Primitive>& GetMeshPrimitiveReader()
 {
   static const auto MESH_PRIMITIVE_READER = std::move(json::Reader<gltf2::Mesh::Primitive>()
-                                               .Register(*json::MakeProperty("attributes", ReadMeshPrimitiveAttributes, &gltf2::Mesh::Primitive::mAttributes))
-                                               .Register(*json::MakeProperty("indices", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Mesh::Primitive::mIndices))
-                                               .Register(*json::MakeProperty("material", gltf2::RefReader<gltf2::Document>::Read<gltf2::Material, &gltf2::Document::mMaterials>, &gltf2::Mesh::Primitive::mMaterial))
-                                               .Register(*json::MakeProperty("mode", json::Read::Enum<gltf2::Mesh::Primitive::Mode>, &gltf2::Mesh::Primitive::mMode))
-                                               .Register(*json::MakeProperty("targets", ReadMeshPrimitiveTargets, &gltf2::Mesh::Primitive::mTargets)));
+                                                        .Register(*json::MakeProperty("attributes", ReadMeshPrimitiveAttributes, &gltf2::Mesh::Primitive::mAttributes))
+                                                        .Register(*json::MakeProperty("indices", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Mesh::Primitive::mIndices))
+                                                        .Register(*json::MakeProperty("material", gltf2::RefReader<gltf2::Document>::Read<gltf2::Material, &gltf2::Document::mMaterials>, &gltf2::Mesh::Primitive::mMaterial))
+                                                        .Register(*json::MakeProperty("mode", json::Read::Enum<gltf2::Mesh::Primitive::Mode>, &gltf2::Mesh::Primitive::mMode))
+                                                        .Register(*json::MakeProperty("targets", ReadMeshPrimitiveTargets, &gltf2::Mesh::Primitive::mTargets)));
   return MESH_PRIMITIVE_READER;
 }
 
+const json::Reader<gltf2::Mesh::Extras>& GetMeshExtrasReader()
+{
+  static const auto MESH_EXTRAS_READER = std::move(json::Reader<gltf2::Mesh::Extras>()
+                                                     .Register(*json::MakeProperty("targetNames", json::Read::Array<std::string_view, json::Read::StringView>, &gltf2::Mesh::Extras::mTargetNames)));
+  return MESH_EXTRAS_READER;
+}
+
+std::vector<std::string_view> ReadMeshExtensionsTargetsName(const json_value_s& j)
+{
+  auto&                         jsonObject = json::Cast<json_object_s>(j);
+  std::vector<std::string_view> result;
+
+  auto element = jsonObject.start;
+  while(element)
+  {
+    auto     jsonString = *element->name;
+    uint32_t index      = json::Read::Number<uint32_t>(*element->value);
+
+    if(result.size() <= index)
+    {
+      DALI_ASSERT_ALWAYS(index < std::numeric_limits<uint32_t>::max());
+      result.resize(index + 1u);
+    }
+
+    result[index] = json::Read::StringView(jsonString);
+
+    element = element->next;
+  }
+  return result;
+}
+
+const json::Reader<gltf2::Mesh::Extensions>& GetMeshExtensionsReader()
+{
+  static const auto MESH_EXTENSIONS_READER = std::move(json::Reader<gltf2::Mesh::Extensions>()
+                                                         .Register(*json::MakeProperty("SXR_targets_names", ReadMeshExtensionsTargetsName, &gltf2::Mesh::Extensions::mSXRTargetsNames))
+                                                         .Register(*json::MakeProperty("avatar_shape_names", ReadMeshExtensionsTargetsName, &gltf2::Mesh::Extensions::mAvatarShapeNames)));
+  return MESH_EXTENSIONS_READER;
+}
+
 const json::Reader<gltf2::Mesh>& GetMeshReader()
 {
   static const auto MESH_READER = std::move(json::Reader<gltf2::Mesh>()
-                                     .Register(*new json::Property<gltf2::Mesh, std::string_view>("name", json::Read::StringView, &gltf2::Mesh::mName))
-                                     .Register(*json::MakeProperty("primitives",
-                                                                   json::Read::Array<gltf2::Mesh::Primitive, json::ObjectReader<gltf2::Mesh::Primitive>::Read>,
-                                                                   &gltf2::Mesh::mPrimitives))
-                                     .Register(*json::MakeProperty("weights", json::Read::Array<float, json::Read::Number>, &gltf2::Mesh::mWeights)));
+                                              .Register(*new json::Property<gltf2::Mesh, std::string_view>("name", json::Read::StringView, &gltf2::Mesh::mName))
+                                              .Register(*json::MakeProperty("primitives",
+                                                                            json::Read::Array<gltf2::Mesh::Primitive, json::ObjectReader<gltf2::Mesh::Primitive>::Read>,
+                                                                            &gltf2::Mesh::mPrimitives))
+                                              .Register(*json::MakeProperty("weights", json::Read::Array<float, json::Read::Number>, &gltf2::Mesh::mWeights))
+                                              .Register(*json::MakeProperty("extras", json::ObjectReader<gltf2::Mesh::Extras>::Read, &gltf2::Mesh::mExtras))
+                                              .Register(*json::MakeProperty("extensions", json::ObjectReader<gltf2::Mesh::Extensions>::Read, &gltf2::Mesh::mExtensions)));
   return MESH_READER;
 }
 
 const json::Reader<gltf2::Skin>& GetSkinReader()
 {
   static const auto SKIN_READER = std::move(json::Reader<gltf2::Skin>()
-                                     .Register(*new json::Property<gltf2::Skin, std::string_view>("name", json::Read::StringView, &gltf2::Skin::mName))
-                                     .Register(*json::MakeProperty("inverseBindMatrices",
-                                                                   gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>,
-                                                                   &gltf2::Skin::mInverseBindMatrices))
-                                     .Register(*json::MakeProperty("skeleton",
-                                                                   gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>,
-                                                                   &gltf2::Skin::mSkeleton))
-                                     .Register(*json::MakeProperty("joints",
-                                                                   json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
-                                                                   &gltf2::Skin::mJoints)));
+                                              .Register(*new json::Property<gltf2::Skin, std::string_view>("name", json::Read::StringView, &gltf2::Skin::mName))
+                                              .Register(*json::MakeProperty("inverseBindMatrices",
+                                                                            gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>,
+                                                                            &gltf2::Skin::mInverseBindMatrices))
+                                              .Register(*json::MakeProperty("skeleton",
+                                                                            gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>,
+                                                                            &gltf2::Skin::mSkeleton))
+                                              .Register(*json::MakeProperty("joints",
+                                                                            json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
+                                                                            &gltf2::Skin::mJoints)));
   return SKIN_READER;
 }
 
 const json::Reader<gltf2::Camera::Perspective>& GetCameraPerspectiveReader()
 {
   static const auto CAMERA_PERSPECTIVE_READER = std::move(json::Reader<gltf2::Camera::Perspective>()
-                                                   .Register(*json::MakeProperty("aspectRatio", json::Read::Number<float>, &gltf2::Camera::Perspective::mAspectRatio))
-                                                   .Register(*json::MakeProperty("yfov", json::Read::Number<float>, &gltf2::Camera::Perspective::mYFov))
-                                                   .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Perspective::mZFar))
-                                                   .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Perspective::mZNear))); // TODO: infinite perspective projection, where znear is omitted
+                                                            .Register(*json::MakeProperty("aspectRatio", json::Read::Number<float>, &gltf2::Camera::Perspective::mAspectRatio))
+                                                            .Register(*json::MakeProperty("yfov", json::Read::Number<float>, &gltf2::Camera::Perspective::mYFov))
+                                                            .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Perspective::mZFar))
+                                                            .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Perspective::mZNear))); // TODO: infinite perspective projection, where znear is omitted
   return CAMERA_PERSPECTIVE_READER;
 }
 
 const json::Reader<gltf2::Camera::Orthographic>& GetCameraOrthographicReader()
 {
   static const auto CAMERA_ORTHOGRAPHIC_READER = std::move(json::Reader<gltf2::Camera::Orthographic>()
-                                                    .Register(*json::MakeProperty("xmag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mXMag))
-                                                    .Register(*json::MakeProperty("ymag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mYMag))
-                                                    .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZFar))
-                                                    .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZNear)));
+                                                             .Register(*json::MakeProperty("xmag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mXMag))
+                                                             .Register(*json::MakeProperty("ymag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mYMag))
+                                                             .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZFar))
+                                                             .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZNear)));
   return CAMERA_ORTHOGRAPHIC_READER;
 }
 
 const json::Reader<gltf2::Camera>& GetCameraReader()
 {
   static const auto CAMERA_READER = std::move(json::Reader<gltf2::Camera>()
-                                       .Register(*new json::Property<gltf2::Camera, std::string_view>("name", json::Read::StringView, &gltf2::Camera::mName))
-                                       .Register(*json::MakeProperty("type", json::Read::StringView, &gltf2::Camera::mType))
-                                       .Register(*json::MakeProperty("perspective", json::ObjectReader<gltf2::Camera::Perspective>::Read, &gltf2::Camera::mPerspective))
-                                       .Register(*json::MakeProperty("orthographic", json::ObjectReader<gltf2::Camera::Orthographic>::Read, &gltf2::Camera::mOrthographic)));
+                                                .Register(*new json::Property<gltf2::Camera, std::string_view>("name", json::Read::StringView, &gltf2::Camera::mName))
+                                                .Register(*json::MakeProperty("type", json::Read::StringView, &gltf2::Camera::mType))
+                                                .Register(*json::MakeProperty("perspective", json::ObjectReader<gltf2::Camera::Perspective>::Read, &gltf2::Camera::mPerspective))
+                                                .Register(*json::MakeProperty("orthographic", json::ObjectReader<gltf2::Camera::Orthographic>::Read, &gltf2::Camera::mOrthographic)));
   return CAMERA_READER;
 }
 
 const json::Reader<gltf2::Node>& GetNodeReader()
 {
   static const auto NODE_READER = std::move(json::Reader<gltf2::Node>()
-                                     .Register(*new json::Property<gltf2::Node, std::string_view>("name", json::Read::StringView, &gltf2::Node::mName))
-                                     .Register(*json::MakeProperty("translation", gltf2::ReadDaliVector<Vector3>, &gltf2::Node::mTranslation))
-                                     .Register(*json::MakeProperty("rotation", gltf2::ReadQuaternion, &gltf2::Node::mRotation))
-                                     .Register(*json::MakeProperty("scale", gltf2::ReadDaliVector<Vector3>, &gltf2::Node::mScale))
-                                     .Register(*new json::Property<gltf2::Node, Matrix>("matrix", gltf2::ReadDaliVector<Matrix>, &gltf2::Node::SetMatrix))
-                                     .Register(*json::MakeProperty("camera", gltf2::RefReader<gltf2::Document>::Read<gltf2::Camera, &gltf2::Document::mCameras>, &gltf2::Node::mCamera))
-                                     .Register(*json::MakeProperty("children", json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>, &gltf2::Node::mChildren))
-                                     .Register(*json::MakeProperty("mesh", gltf2::RefReader<gltf2::Document>::Read<gltf2::Mesh, &gltf2::Document::mMeshes>, &gltf2::Node::mMesh))
-                                     .Register(*json::MakeProperty("skin", gltf2::RefReader<gltf2::Document>::Read<gltf2::Skin, &gltf2::Document::mSkins>, &gltf2::Node::mSkin)));
+                                              .Register(*new json::Property<gltf2::Node, std::string_view>("name", json::Read::StringView, &gltf2::Node::mName))
+                                              .Register(*json::MakeProperty("translation", gltf2::ReadDaliVector<Vector3>, &gltf2::Node::mTranslation))
+                                              .Register(*json::MakeProperty("rotation", gltf2::ReadQuaternion, &gltf2::Node::mRotation))
+                                              .Register(*json::MakeProperty("scale", gltf2::ReadDaliVector<Vector3>, &gltf2::Node::mScale))
+                                              .Register(*new json::Property<gltf2::Node, Matrix>("matrix", gltf2::ReadDaliVector<Matrix>, &gltf2::Node::SetMatrix))
+                                              .Register(*json::MakeProperty("camera", gltf2::RefReader<gltf2::Document>::Read<gltf2::Camera, &gltf2::Document::mCameras>, &gltf2::Node::mCamera))
+                                              .Register(*json::MakeProperty("children", json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>, &gltf2::Node::mChildren))
+                                              .Register(*json::MakeProperty("mesh", gltf2::RefReader<gltf2::Document>::Read<gltf2::Mesh, &gltf2::Document::mMeshes>, &gltf2::Node::mMesh))
+                                              .Register(*json::MakeProperty("skin", gltf2::RefReader<gltf2::Document>::Read<gltf2::Skin, &gltf2::Document::mSkins>, &gltf2::Node::mSkin)));
   return NODE_READER;
 }
 
 const json::Reader<gltf2::Animation::Sampler>& GetAnimationSamplerReader()
 {
   static const auto ANIMATION_SAMPLER_READER = std::move(json::Reader<gltf2::Animation::Sampler>()
-                                                  .Register(*json::MakeProperty("input", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mInput))
-                                                  .Register(*json::MakeProperty("output", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mOutput))
-                                                  .Register(*json::MakeProperty("interpolation", gltf2::ReadStringEnum<gltf2::Animation::Sampler::Interpolation>, &gltf2::Animation::Sampler::mInterpolation)));
+                                                           .Register(*json::MakeProperty("input", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mInput))
+                                                           .Register(*json::MakeProperty("output", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mOutput))
+                                                           .Register(*json::MakeProperty("interpolation", gltf2::ReadStringEnum<gltf2::Animation::Sampler::Interpolation>, &gltf2::Animation::Sampler::mInterpolation)));
   return ANIMATION_SAMPLER_READER;
 }
 
 const json::Reader<gltf2::Animation::Channel::Target>& GetAnimationChannelTargetReader()
 {
   static const auto ANIMATION_TARGET_READER = std::move(json::Reader<gltf2::Animation::Channel::Target>()
-                                                 .Register(*json::MakeProperty("node", gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>, &gltf2::Animation::Channel::Target::mNode))
-                                                 .Register(*json::MakeProperty("path", gltf2::ReadStringEnum<gltf2::Animation::Channel::Target>, &gltf2::Animation::Channel::Target::mPath)));
+                                                          .Register(*json::MakeProperty("node", gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>, &gltf2::Animation::Channel::Target::mNode))
+                                                          .Register(*json::MakeProperty("path", gltf2::ReadStringEnum<gltf2::Animation::Channel::Target>, &gltf2::Animation::Channel::Target::mPath)));
   return ANIMATION_TARGET_READER;
 }
 
 const json::Reader<gltf2::Animation::Channel>& GetAnimationChannelReader()
 {
   static const auto ANIMATION_CHANNEL_READER = std::move(json::Reader<gltf2::Animation::Channel>()
-                                                  .Register(*json::MakeProperty("target", json::ObjectReader<gltf2::Animation::Channel::Target>::Read, &gltf2::Animation::Channel::mTarget))
-                                                  .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Animation>::Read<gltf2::Animation::Sampler, &gltf2::Animation::mSamplers>, &gltf2::Animation::Channel::mSampler)));
+                                                           .Register(*json::MakeProperty("target", json::ObjectReader<gltf2::Animation::Channel::Target>::Read, &gltf2::Animation::Channel::mTarget))
+                                                           .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Animation>::Read<gltf2::Animation::Sampler, &gltf2::Animation::mSamplers>, &gltf2::Animation::Channel::mSampler)));
   return ANIMATION_CHANNEL_READER;
 }
 
 const json::Reader<gltf2::Animation>& GetAnimationReader()
 {
   static const auto ANIMATION_READER = std::move(json::Reader<gltf2::Animation>()
-                                          .Register(*new json::Property<gltf2::Animation, std::string_view>("name", json::Read::StringView, &gltf2::Animation::mName))
-                                          .Register(*json::MakeProperty("samplers",
-                                                                        json::Read::Array<gltf2::Animation::Sampler, json::ObjectReader<gltf2::Animation::Sampler>::Read>,
-                                                                        &gltf2::Animation::mSamplers))
-                                          .Register(*json::MakeProperty("channels",
-                                                                        json::Read::Array<gltf2::Animation::Channel, json::ObjectReader<gltf2::Animation::Channel>::Read>,
-                                                                        &gltf2::Animation::mChannels)));
+                                                   .Register(*new json::Property<gltf2::Animation, std::string_view>("name", json::Read::StringView, &gltf2::Animation::mName))
+                                                   .Register(*json::MakeProperty("samplers",
+                                                                                 json::Read::Array<gltf2::Animation::Sampler, json::ObjectReader<gltf2::Animation::Sampler>::Read>,
+                                                                                 &gltf2::Animation::mSamplers))
+                                                   .Register(*json::MakeProperty("channels",
+                                                                                 json::Read::Array<gltf2::Animation::Channel, json::ObjectReader<gltf2::Animation::Channel>::Read>,
+                                                                                 &gltf2::Animation::mChannels)));
   return ANIMATION_READER;
 }
 
 const json::Reader<gltf2::Scene>& GetSceneReader()
 {
   static const auto SCENE_READER = std::move(json::Reader<gltf2::Scene>()
-                                      .Register(*new json::Property<gltf2::Scene, std::string_view>("name", json::Read::StringView, &gltf2::Scene::mName))
-                                      .Register(*json::MakeProperty("nodes",
-                                                                    json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
-                                                                    &gltf2::Scene::mNodes)));
+                                               .Register(*new json::Property<gltf2::Scene, std::string_view>("name", json::Read::StringView, &gltf2::Scene::mName))
+                                               .Register(*json::MakeProperty("nodes",
+                                                                             json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
+                                                                             &gltf2::Scene::mNodes)));
   return SCENE_READER;
 }
 
 const json::Reader<gltf2::Document>& GetDocumentReader()
 {
   static const auto DOCUMENT_READER = std::move(json::Reader<gltf2::Document>()
-                                         .Register(*json::MakeProperty("buffers",
-                                                                       json::Read::Array<gltf2::Buffer, json::ObjectReader<gltf2::Buffer>::Read>,
-                                                                       &gltf2::Document::mBuffers))
-                                         .Register(*json::MakeProperty("bufferViews",
-                                                                       json::Read::Array<gltf2::BufferView, json::ObjectReader<gltf2::BufferView>::Read>,
-                                                                       &gltf2::Document::mBufferViews))
-                                         .Register(*json::MakeProperty("accessors",
-                                                                       json::Read::Array<gltf2::Accessor, json::ObjectReader<gltf2::Accessor>::Read>,
-                                                                       &gltf2::Document::mAccessors))
-                                         .Register(*json::MakeProperty("images",
-                                                                       json::Read::Array<gltf2::Image, json::ObjectReader<gltf2::Image>::Read>,
-                                                                       &gltf2::Document::mImages))
-                                         .Register(*json::MakeProperty("samplers",
-                                                                       json::Read::Array<gltf2::Sampler, json::ObjectReader<gltf2::Sampler>::Read>,
-                                                                       &gltf2::Document::mSamplers))
-                                         .Register(*json::MakeProperty("textures",
-                                                                       json::Read::Array<gltf2::Texture, json::ObjectReader<gltf2::Texture>::Read>,
-                                                                       &gltf2::Document::mTextures))
-                                         .Register(*json::MakeProperty("materials",
-                                                                       json::Read::Array<gltf2::Material, json::ObjectReader<gltf2::Material>::Read>,
-                                                                       &gltf2::Document::mMaterials))
-                                         .Register(*json::MakeProperty("meshes",
-                                                                       json::Read::Array<gltf2::Mesh, json::ObjectReader<gltf2::Mesh>::Read>,
-                                                                       &gltf2::Document::mMeshes))
-                                         .Register(*json::MakeProperty("skins",
-                                                                       json::Read::Array<gltf2::Skin, json::ObjectReader<gltf2::Skin>::Read>,
-                                                                       &gltf2::Document::mSkins))
-                                         .Register(*json::MakeProperty("cameras",
-                                                                       json::Read::Array<gltf2::Camera, json::ObjectReader<gltf2::Camera>::Read>,
-                                                                       &gltf2::Document::mCameras))
-                                         .Register(*json::MakeProperty("nodes",
-                                                                       json::Read::Array<gltf2::Node, json::ObjectReader<gltf2::Node>::Read>,
-                                                                       &gltf2::Document::mNodes))
-                                         .Register(*json::MakeProperty("animations",
-                                                                       ReadAnimationArray,
-                                                                       &gltf2::Document::mAnimations))
-                                         .Register(*json::MakeProperty("scenes",
-                                                                       json::Read::Array<gltf2::Scene, json::ObjectReader<gltf2::Scene>::Read>,
-                                                                       &gltf2::Document::mScenes))
-                                         .Register(*json::MakeProperty("scene", gltf2::RefReader<gltf2::Document>::Read<gltf2::Scene, &gltf2::Document::mScenes>, &gltf2::Document::mScene)));
+                                                  .Register(*json::MakeProperty("buffers",
+                                                                                json::Read::Array<gltf2::Buffer, json::ObjectReader<gltf2::Buffer>::Read>,
+                                                                                &gltf2::Document::mBuffers))
+                                                  .Register(*json::MakeProperty("bufferViews",
+                                                                                json::Read::Array<gltf2::BufferView, json::ObjectReader<gltf2::BufferView>::Read>,
+                                                                                &gltf2::Document::mBufferViews))
+                                                  .Register(*json::MakeProperty("accessors",
+                                                                                json::Read::Array<gltf2::Accessor, json::ObjectReader<gltf2::Accessor>::Read>,
+                                                                                &gltf2::Document::mAccessors))
+                                                  .Register(*json::MakeProperty("images",
+                                                                                json::Read::Array<gltf2::Image, json::ObjectReader<gltf2::Image>::Read>,
+                                                                                &gltf2::Document::mImages))
+                                                  .Register(*json::MakeProperty("samplers",
+                                                                                json::Read::Array<gltf2::Sampler, json::ObjectReader<gltf2::Sampler>::Read>,
+                                                                                &gltf2::Document::mSamplers))
+                                                  .Register(*json::MakeProperty("textures",
+                                                                                json::Read::Array<gltf2::Texture, json::ObjectReader<gltf2::Texture>::Read>,
+                                                                                &gltf2::Document::mTextures))
+                                                  .Register(*json::MakeProperty("materials",
+                                                                                json::Read::Array<gltf2::Material, json::ObjectReader<gltf2::Material>::Read>,
+                                                                                &gltf2::Document::mMaterials))
+                                                  .Register(*json::MakeProperty("meshes",
+                                                                                json::Read::Array<gltf2::Mesh, json::ObjectReader<gltf2::Mesh>::Read>,
+                                                                                &gltf2::Document::mMeshes))
+                                                  .Register(*json::MakeProperty("skins",
+                                                                                json::Read::Array<gltf2::Skin, json::ObjectReader<gltf2::Skin>::Read>,
+                                                                                &gltf2::Document::mSkins))
+                                                  .Register(*json::MakeProperty("cameras",
+                                                                                json::Read::Array<gltf2::Camera, json::ObjectReader<gltf2::Camera>::Read>,
+                                                                                &gltf2::Document::mCameras))
+                                                  .Register(*json::MakeProperty("nodes",
+                                                                                json::Read::Array<gltf2::Node, json::ObjectReader<gltf2::Node>::Read>,
+                                                                                &gltf2::Document::mNodes))
+                                                  .Register(*json::MakeProperty("animations",
+                                                                                ReadAnimationArray,
+                                                                                &gltf2::Document::mAnimations))
+                                                  .Register(*json::MakeProperty("extensionsRequired",
+                                                                                json::Read::Array<std::string_view, json::Read::StringView>,
+                                                                                &gltf2::Document::mExtensionsRequired))
+                                                  .Register(*json::MakeProperty("extensionsUsed",
+                                                                                json::Read::Array<std::string_view, json::Read::StringView>,
+                                                                                &gltf2::Document::mExtensionsUsed))
+                                                  .Register(*json::MakeProperty("scenes",
+                                                                                json::Read::Array<gltf2::Scene, json::ObjectReader<gltf2::Scene>::Read>,
+                                                                                &gltf2::Document::mScenes))
+                                                  .Register(*json::MakeProperty("scene", gltf2::RefReader<gltf2::Document>::Read<gltf2::Scene, &gltf2::Document::mScenes>, &gltf2::Document::mScene)));
   return DOCUMENT_READER;
 }
 
@@ -518,22 +602,27 @@ TextureDefinition ConvertTextureInfo(const gltf2::TextureInfo& textureInfo, Conv
     {
       auto& stream = context.mOutput.mResources.mBuffers[bufferIndex].GetBufferStream();
       stream.clear();
-      stream.seekg(textureInfo.mTexture->mSource->mBufferView->mByteOffset, stream.beg);
+      stream.seekg(static_cast<std::streamoff>(static_cast<std::size_t>(textureInfo.mTexture->mSource->mBufferView->mByteOffset)), stream.beg);
       std::vector<uint8_t> dataBuffer;
       dataBuffer.resize(textureInfo.mTexture->mSource->mBufferView->mByteLength);
       stream.read(reinterpret_cast<char*>(dataBuffer.data()), static_cast<std::streamsize>(static_cast<size_t>(textureInfo.mTexture->mSource->mBufferView->mByteLength)));
-      return TextureDefinition{std::move(dataBuffer), ConvertSampler(textureInfo.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode};
+      return TextureDefinition{std::move(dataBuffer), ConvertSampler(textureInfo.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode, textureInfo.mTextureExtensions.mTextureTransform.GetTransform()};
     }
     return TextureDefinition();
   }
   else
   {
-    return TextureDefinition{uri, ConvertSampler(textureInfo.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode};
+    return TextureDefinition{uri, ConvertSampler(textureInfo.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode, textureInfo.mTextureExtensions.mTextureTransform.GetTransform()};
   }
 }
 
 void AddTextureStage(uint32_t semantic, MaterialDefinition& materialDefinition, gltf2::TextureInfo textureInfo, const Dali::Scene3D::Loader::ImageMetadata& metaData, ConversionContext& context)
 {
+  // Overrides the textureInfo texCoord value if KHR_texture_transform extension is supported and texCoord value is supplied.
+  if(textureInfo.mTextureExtensions && textureInfo.mTexCoord != textureInfo.mTextureExtensions.mTextureTransform.mTexCoord && textureInfo.mTextureExtensions.mTextureTransform.mTexCoord != 0u)
+  {
+    textureInfo.mTexCoord = textureInfo.mTextureExtensions.mTextureTransform.mTexCoord;
+  }
   materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(textureInfo, context, metaData)});
   materialDefinition.mFlags |= semantic;
 }
@@ -553,15 +642,20 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
 
   MaterialDefinition materialDefinition;
 
+  materialDefinition.mFlags |= MaterialDefinition::GLTF_CHANNELS;
+  materialDefinition.mShadowAvailable = true;
+
   auto& pbr = material.mPbrMetallicRoughness;
   if(material.mAlphaMode == gltf2::AlphaMode::BLEND)
   {
-    materialDefinition.mIsOpaque = false;
+    materialDefinition.mAlphaModeType = Scene3D::Material::AlphaModeType::BLEND;
+    materialDefinition.mIsOpaque      = false;
     materialDefinition.mFlags |= MaterialDefinition::TRANSPARENCY;
   }
   else if(material.mAlphaMode == gltf2::AlphaMode::MASK)
   {
-    materialDefinition.mIsMask = true;
+    materialDefinition.mAlphaModeType = Scene3D::Material::AlphaModeType::MASK;
+    materialDefinition.mIsMask        = true;
     materialDefinition.SetAlphaCutoff(std::min(1.f, std::max(0.f, material.mAlphaCutoff)));
   }
 
@@ -582,7 +676,7 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
 
   if(pbr.mMetallicRoughnessTexture)
   {
-    AddTextureStage(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+    AddTextureStage(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS,
                     materialDefinition,
                     pbr.mMetallicRoughnessTexture,
                     getTextureMetaData(imageMetaData, pbr.mMetallicRoughnessTexture),
@@ -617,8 +711,8 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
 
   if(!Dali::Equals(material.mMaterialExtensions.mMaterialIor.mIor, gltf2::UNDEFINED_FLOAT_VALUE))
   {
-    float ior                              = material.mMaterialExtensions.mMaterialIor.mIor;
-    materialDefinition.mDielectricSpecular = powf((ior - 1.0f) / (ior + 1.0f), 2.0f);
+    materialDefinition.mIor                = material.mMaterialExtensions.mMaterialIor.mIor;
+    materialDefinition.mDielectricSpecular = powf((materialDefinition.mIor - 1.0f) / (materialDefinition.mIor + 1.0f), 2.0f);
   }
   materialDefinition.mSpecularFactor      = material.mMaterialExtensions.mMaterialSpecular.mSpecularFactor;
   materialDefinition.mSpecularColorFactor = material.mMaterialExtensions.mMaterialSpecular.mSpecularColorFactor;
@@ -702,11 +796,162 @@ MeshDefinition::Accessor ConvertMeshPrimitiveAccessor(const gltf2::Accessor& acc
                                    accessor.mMin,
                                    accessor.mMax}),
     std::move(sparseBlob),
-    accessor.mBufferView ? accessor.mBufferView->mBuffer.GetIndex() : 0};
+    accessor.mBufferView ? accessor.mBufferView->mBuffer.GetIndex() : 0,
+    accessor.mNormalized};
+}
+
+MeshDefinition::Accessor* GetAccessorFromAttribute(gltf2::Attribute::HashType attributeHash,
+                                                   MeshDefinition&            meshDefinition,
+                                                   bool&                      needNormals,
+                                                   bool&                      needTangents)
+{
+  MeshDefinition::Accessor* accessorDest{nullptr};
+
+  switch(gltf2::Attribute::TypeFromHash(attributeHash))
+  {
+    case gltf2::Attribute::POSITION:
+    {
+      accessorDest = &meshDefinition.mPositions;
+      break;
+    }
+    case gltf2::Attribute::NORMAL:
+    {
+      accessorDest = &meshDefinition.mNormals;
+      needNormals  = false;
+      break;
+    }
+    case gltf2::Attribute::TANGENT:
+    {
+      accessorDest = &meshDefinition.mTangents;
+      needTangents = false;
+      break;
+    }
+    case gltf2::Attribute::TEXCOORD_N:
+    {
+      meshDefinition.mTexCoords.emplace_back(MeshDefinition::Accessor{});
+      accessorDest = &meshDefinition.mTexCoords.back();
+      break;
+    }
+    case gltf2::Attribute::COLOR_N:
+    {
+      meshDefinition.mColors.emplace_back(MeshDefinition::Accessor{});
+      accessorDest = &meshDefinition.mColors.back();
+      break;
+    }
+    case gltf2::Attribute::JOINTS_N:
+    {
+      if(meshDefinition.mJoints.size() < MeshDefinition::MAX_NUMBER_OF_JOINT_SETS)
+      {
+        meshDefinition.mJoints.emplace_back(MeshDefinition::Accessor{});
+        accessorDest = &meshDefinition.mJoints.back();
+      }
+      break;
+    }
+    case gltf2::Attribute::WEIGHTS_N:
+    {
+      if(meshDefinition.mWeights.size() < MeshDefinition::MAX_NUMBER_OF_JOINT_SETS)
+      {
+        meshDefinition.mWeights.emplace_back(MeshDefinition::Accessor{});
+        accessorDest = &meshDefinition.mWeights.back();
+      }
+      break;
+    }
+    case gltf2::Attribute::INVALID:
+    {
+      accessorDest = nullptr;
+      break;
+    }
+  }
+  return accessorDest;
+}
+
+void SetFlagsFromComponentType(const gltf2::Accessor&     accessor,
+                               gltf2::Attribute::HashType attributeHash,
+                               MeshDefinition&            meshDefinition,
+                               bool                       isQuantized)
+{
+  switch(gltf2::Attribute::TypeFromHash(attributeHash))
+  {
+    case gltf2::Attribute::POSITION:
+    {
+      if(isQuantized)
+      {
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::BYTE) * MeshDefinition::S8_POSITION;
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::UNSIGNED_BYTE) * MeshDefinition::U8_POSITION;
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::SHORT) * MeshDefinition::S16_POSITION;
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::UNSIGNED_SHORT) * MeshDefinition::U16_POSITION;
+      }
+      DALI_ASSERT_DEBUG((isQuantized && (MaskMatch(meshDefinition.mFlags, MeshDefinition::S8_POSITION) || MaskMatch(meshDefinition.mFlags, MeshDefinition::U8_POSITION) || MaskMatch(meshDefinition.mFlags, MeshDefinition::S16_POSITION) || MaskMatch(meshDefinition.mFlags, MeshDefinition::U16_POSITION))) || accessor.mComponentType == gltf2::Component::FLOAT);
+      break;
+    }
+    case gltf2::Attribute::NORMAL:
+    {
+      if(isQuantized)
+      {
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::BYTE) * MeshDefinition::S8_NORMAL;
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::SHORT) * MeshDefinition::S16_NORMAL;
+      }
+
+      DALI_ASSERT_DEBUG((isQuantized && (MaskMatch(meshDefinition.mFlags, MeshDefinition::S8_NORMAL) || MaskMatch(meshDefinition.mFlags, MeshDefinition::S16_NORMAL))) || accessor.mComponentType == gltf2::Component::FLOAT);
+      break;
+    }
+    case gltf2::Attribute::TANGENT:
+    {
+      if(isQuantized)
+      {
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::BYTE) * MeshDefinition::S8_TANGENT;
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::SHORT) * MeshDefinition::S16_TANGENT;
+      }
+
+      DALI_ASSERT_DEBUG((isQuantized && (MaskMatch(meshDefinition.mFlags, MeshDefinition::S8_TANGENT) || MaskMatch(meshDefinition.mFlags, MeshDefinition::S16_TANGENT))) || accessor.mComponentType == gltf2::Component::FLOAT);
+      break;
+    }
+    case gltf2::Attribute::TEXCOORD_N:
+    {
+      if(isQuantized)
+      {
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::BYTE) * MeshDefinition::S8_TEXCOORD;
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::UNSIGNED_BYTE) * MeshDefinition::U8_TEXCOORD;
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::SHORT) * MeshDefinition::S16_TEXCOORD;
+        meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::UNSIGNED_SHORT) * MeshDefinition::U16_TEXCOORD;
+      }
+      DALI_ASSERT_DEBUG((isQuantized && (MaskMatch(meshDefinition.mFlags, MeshDefinition::S8_TEXCOORD) || MaskMatch(meshDefinition.mFlags, MeshDefinition::U8_TEXCOORD) || MaskMatch(meshDefinition.mFlags, MeshDefinition::S16_TEXCOORD) || MaskMatch(meshDefinition.mFlags, MeshDefinition::U16_TEXCOORD))) || accessor.mComponentType == gltf2::Component::FLOAT);
+      break;
+    }
+    case gltf2::Attribute::COLOR_N:
+    {
+      break;
+    }
+    case gltf2::Attribute::JOINTS_N:
+    {
+      meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::UNSIGNED_SHORT) * MeshDefinition::U16_JOINT_IDS;
+      meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::UNSIGNED_BYTE) * MeshDefinition::U8_JOINT_IDS;
+      DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U16_JOINT_IDS) ||
+                        MaskMatch(meshDefinition.mFlags, MeshDefinition::U8_JOINT_IDS) ||
+                        accessor.mComponentType == gltf2::Component::FLOAT);
+      break;
+    }
+    case gltf2::Attribute::WEIGHTS_N:
+    {
+      meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::UNSIGNED_SHORT) * MeshDefinition::U16_WEIGHT;
+      meshDefinition.mFlags |= (accessor.mComponentType == gltf2::Component::UNSIGNED_BYTE) * MeshDefinition::U8_WEIGHT;
+      DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U16_WEIGHT) ||
+                        MaskMatch(meshDefinition.mFlags, MeshDefinition::U8_WEIGHT) ||
+                        accessor.mComponentType == gltf2::Component::FLOAT);
+
+      break;
+    }
+    case gltf2::Attribute::INVALID:
+    {
+      break;
+    }
+  }
 }
 
 void ConvertMeshes(const gltf2::Document& document, ConversionContext& context)
 {
+  bool isQuantized = MaskMatch(document.mExtensionFlags, gltf2::ExtensionFlags::KHR_MESH_QUANTIZATION);
+
   uint32_t meshCount = 0;
   context.mMeshIds.reserve(document.mMeshes.size());
   for(auto& mesh : document.mMeshes)
@@ -726,44 +971,40 @@ void ConvertMeshes(const gltf2::Document& document, ConversionContext& context)
       auto& attribs                 = primitive.mAttributes;
       meshDefinition.mPrimitiveType = GLTF2_TO_DALI_PRIMITIVES[primitive.mMode];
 
-      auto& accPositions        = *attribs.find(gltf2::Attribute::POSITION)->second;
-      meshDefinition.mPositions = ConvertMeshPrimitiveAccessor(accPositions);
+      auto positionIter = attribs.find(gltf2::Attribute::ToHash(gltf2::Attribute::POSITION, false, 0));
+      if(positionIter == attribs.end())
+      {
+        DALI_LOG_ERROR("Primitive mesh dosn't have POSITION atrributes!");
+        continue;
+      }
+
+      auto& positionsAccessor = *positionIter->second;
+
       // glTF2 support vector4 tangent for mesh.
       // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#meshes-overview
       meshDefinition.mTangentType = Property::VECTOR4;
 
-      const bool needNormalsTangents = accPositions.mType == gltf2::AccessorType::VEC3;
-      for(auto& attributeMapping : ATTRIBUTE_MAPPINGS)
+      bool needNormals  = (positionsAccessor.mType == gltf2::AccessorType::VEC3);
+      bool needTangents = (positionsAccessor.mType == gltf2::AccessorType::VEC3);
+
+      for(const auto& [attributeHash, accessor] : attribs)
       {
-        auto iFind = attribs.find(attributeMapping.mType);
-        if(iFind != attribs.end())
+        MeshDefinition::Accessor* accessorDest = GetAccessorFromAttribute(attributeHash, meshDefinition, needNormals, needTangents);
+        if(accessorDest == nullptr)
         {
-          auto& accessor = meshDefinition.*(attributeMapping.mAccessor);
-          accessor       = ConvertMeshPrimitiveAccessor(*iFind->second);
-
-          if(iFind->first == gltf2::Attribute::JOINTS_0)
-          {
-            meshDefinition.mFlags |= (iFind->second->mComponentType == gltf2::Component::UNSIGNED_SHORT) * MeshDefinition::U16_JOINT_IDS;
-            meshDefinition.mFlags |= (iFind->second->mComponentType == gltf2::Component::UNSIGNED_BYTE) * MeshDefinition::U8_JOINT_IDS;
-            DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U16_JOINT_IDS) || MaskMatch(meshDefinition.mFlags, MeshDefinition::U8_JOINT_IDS) || iFind->second->mComponentType == gltf2::Component::FLOAT);
-          }
+          continue;
         }
-        else if(needNormalsTangents)
-        {
-          switch(attributeMapping.mType)
-          {
-            case gltf2::Attribute::NORMAL:
-              meshDefinition.RequestNormals();
-              break;
-
-            case gltf2::Attribute::TANGENT:
-              meshDefinition.RequestTangents();
-              break;
+        *accessorDest = ConvertMeshPrimitiveAccessor(*accessor);
+        SetFlagsFromComponentType(*accessor, attributeHash, meshDefinition, isQuantized);
+      }
 
-            default:
-              break;
-          }
-        }
+      if(needNormals)
+      {
+        meshDefinition.RequestNormals();
+      }
+      if(needTangents)
+      {
+        meshDefinition.RequestTangents();
       }
 
       if(primitive.mIndices)
@@ -778,6 +1019,7 @@ void ConvertMeshes(const gltf2::Document& document, ConversionContext& context)
       {
         meshDefinition.mBlendShapes.reserve(primitive.mTargets.size());
         meshDefinition.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0;
+        uint32_t blendShapeIndex          = 0u;
         for(const auto& target : primitive.mTargets)
         {
           MeshDefinition::BlendShape blendShape;
@@ -786,17 +1028,44 @@ void ConvertMeshes(const gltf2::Document& document, ConversionContext& context)
           auto it    = target.find(gltf2::Attribute::POSITION);
           if(it != endIt)
           {
-            blendShape.deltas = ConvertMeshPrimitiveAccessor(*it->second);
+            blendShape.deltas             = ConvertMeshPrimitiveAccessor(*it->second);
+            blendShape.deltas.mNormalized = it->second->mNormalized;
+
+            if(isQuantized)
+            {
+              blendShape.mFlags |= (it->second->mComponentType == gltf2::Component::BYTE) * MeshDefinition::S8_POSITION;
+              blendShape.mFlags |= (it->second->mComponentType == gltf2::Component::SHORT) * MeshDefinition::S16_POSITION;
+            }
+
+            DALI_ASSERT_DEBUG((isQuantized && (MaskMatch(blendShape.mFlags, MeshDefinition::S8_POSITION) || MaskMatch(blendShape.mFlags, MeshDefinition::U8_POSITION) || MaskMatch(blendShape.mFlags, MeshDefinition::S16_POSITION) || MaskMatch(blendShape.mFlags, MeshDefinition::U16_POSITION))) || it->second->mComponentType == gltf2::Component::FLOAT);
           }
           it = target.find(gltf2::Attribute::NORMAL);
           if(it != endIt)
           {
-            blendShape.normals = ConvertMeshPrimitiveAccessor(*it->second);
+            blendShape.normals             = ConvertMeshPrimitiveAccessor(*it->second);
+            blendShape.normals.mNormalized = it->second->mNormalized;
+
+            if(isQuantized)
+            {
+              blendShape.mFlags |= (it->second->mComponentType == gltf2::Component::BYTE) * MeshDefinition::S8_NORMAL;
+              blendShape.mFlags |= (it->second->mComponentType == gltf2::Component::SHORT) * MeshDefinition::S16_NORMAL;
+            }
+
+            DALI_ASSERT_DEBUG((isQuantized && (MaskMatch(blendShape.mFlags, MeshDefinition::S8_NORMAL) || MaskMatch(blendShape.mFlags, MeshDefinition::S16_NORMAL))) || it->second->mComponentType == gltf2::Component::FLOAT);
           }
           it = target.find(gltf2::Attribute::TANGENT);
           if(it != endIt)
           {
-            blendShape.tangents = ConvertMeshPrimitiveAccessor(*it->second);
+            blendShape.tangents             = ConvertMeshPrimitiveAccessor(*it->second);
+            blendShape.tangents.mNormalized = it->second->mNormalized;
+
+            if(isQuantized)
+            {
+              blendShape.mFlags |= (it->second->mComponentType == gltf2::Component::BYTE) * MeshDefinition::S8_TANGENT;
+              blendShape.mFlags |= (it->second->mComponentType == gltf2::Component::SHORT) * MeshDefinition::S16_TANGENT;
+            }
+
+            DALI_ASSERT_DEBUG((isQuantized && (MaskMatch(blendShape.mFlags, MeshDefinition::S8_TANGENT) || MaskMatch(blendShape.mFlags, MeshDefinition::S16_TANGENT))) || it->second->mComponentType == gltf2::Component::FLOAT);
           }
 
           if(!mesh.mWeights.empty())
@@ -804,7 +1073,22 @@ void ConvertMeshes(const gltf2::Document& document, ConversionContext& context)
             blendShape.weight = mesh.mWeights[meshDefinition.mBlendShapes.size()];
           }
 
+          // Get blendshape name from extras / SXR_targets_names / avatar_shape_names.
+          if(blendShapeIndex < mesh.mExtras.mTargetNames.size())
+          {
+            blendShape.name = mesh.mExtras.mTargetNames[blendShapeIndex];
+          }
+          else if(blendShapeIndex < mesh.mExtensions.mSXRTargetsNames.size())
+          {
+            blendShape.name = mesh.mExtensions.mSXRTargetsNames[blendShapeIndex];
+          }
+          else if(blendShapeIndex < mesh.mExtensions.mAvatarShapeNames.size())
+          {
+            blendShape.name = mesh.mExtensions.mAvatarShapeNames[blendShapeIndex];
+          }
+
           meshDefinition.mBlendShapes.push_back(std::move(blendShape));
+          ++blendShapeIndex;
         }
       }
 
@@ -817,8 +1101,6 @@ ModelRenderable* MakeModelRenderable(const gltf2::Mesh::Primitive& primitive, Co
 {
   auto modelRenderable = new ModelRenderable();
 
-  modelRenderable->mShaderIdx = 0; // TODO: further thought
-
   auto materialIdx = primitive.mMaterial.GetIndex();
   if(INVALID_INDEX == materialIdx)
   {
@@ -873,6 +1155,8 @@ void ConvertCamera(const gltf2::Camera& camera, CameraParameters& cameraParamete
     cameraParameters.zNear = ortho.mZNear;
     cameraParameters.zFar  = ortho.mZFar;
   }
+
+  cameraParameters.name = std::string(camera.mName);
 }
 
 void ConvertNode(gltf2::Node const& node, const Index gltfIndex, Index parentIndex, ConversionContext& context, bool isMRendererModel)
@@ -1020,7 +1304,7 @@ void LoadDataFromAccessor(ConversionContext& context, uint32_t bufferIndex, Vect
   }
   auto& stream = buffer.GetBufferStream();
   stream.clear();
-  stream.seekg(offset, stream.beg);
+  stream.seekg(static_cast<std::streamoff>(static_cast<std::size_t>(offset)), stream.beg);
   stream.read(reinterpret_cast<char*>(dataBuffer.Begin()), static_cast<std::streamsize>(static_cast<size_t>(size)));
 }
 
@@ -1041,6 +1325,11 @@ float LoadDataFromAccessors(ConversionContext& context, const gltf2::Accessor& i
   return inputDataBuffer[input.mCount - 1u];
 }
 
+bool IsFirstFrameValueEmpty(const uint32_t inputCount, const Vector<float>& inputBuffer)
+{
+  return (inputCount > 0 && !Dali::EqualsZero(inputBuffer[0]));
+}
+
 template<typename T>
 float LoadKeyFrames(ConversionContext& context, const gltf2::Animation::Channel& channel, KeyFrames& keyFrames, gltf2::Animation::Channel::Target::Type type)
 {
@@ -1052,8 +1341,7 @@ float LoadKeyFrames(ConversionContext& context, const gltf2::Animation::Channel&
 
   const float duration = std::max(LoadDataFromAccessors<T>(context, input, output, inputDataBuffer, outputDataBuffer), AnimationDefinition::MIN_DURATION_SECONDS);
 
-  // Set first frame value as first keyframe (gltf animation spec)
-  if(input.mCount > 0 && !Dali::EqualsZero(inputDataBuffer[0]))
+  if(IsFirstFrameValueEmpty(input.mCount, inputDataBuffer))
   {
     keyFrames.Add(0.0f, outputDataBuffer[0]);
   }
@@ -1066,7 +1354,7 @@ float LoadKeyFrames(ConversionContext& context, const gltf2::Animation::Channel&
   return duration;
 }
 
-float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation::Channel& channel, Index nodeIndex, uint32_t& propertyIndex, std::vector<Dali::Scene3D::Loader::AnimatedProperty>& properties)
+float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation::Channel& channel, Index nodeIndex, uint32_t& propertyIndex, AnimationDefinition& animationDefinition)
 {
   const gltf2::Accessor& input  = *channel.mSampler->mInput;
   const gltf2::Accessor& output = *channel.mSampler->mOutput;
@@ -1082,7 +1370,7 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation
   const auto  remainingSize = sizeof(weightNameBuffer) - prefixSize;
   for(uint32_t weightIndex = 0u, endWeightIndex = channel.mSampler->mOutput->mCount / channel.mSampler->mInput->mCount; weightIndex < endWeightIndex; ++weightIndex)
   {
-    AnimatedProperty& animatedProperty = properties[propertyIndex++];
+    AnimatedProperty animatedProperty;
 
     animatedProperty.mNodeIndex = nodeIndex;
     snprintf(pWeightName, remainingSize, "%d]", weightIndex);
@@ -1090,8 +1378,7 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation
 
     animatedProperty.mKeyFrames = KeyFrames::New();
 
-    // Set first frame value as first keyframe (gltf animation spec)
-    if(input.mCount > 0 && !Dali::EqualsZero(inputDataBuffer[0]))
+    if(IsFirstFrameValueEmpty(input.mCount, inputDataBuffer))
     {
       animatedProperty.mKeyFrames.Add(0.0f, outputDataBuffer[weightIndex]);
     }
@@ -1102,6 +1389,8 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation
     }
 
     animatedProperty.mTimePeriod = {0.f, duration};
+
+    animationDefinition.SetProperty(propertyIndex++, std::move(animatedProperty));
   }
 
   return duration;
@@ -1110,8 +1399,7 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation
 template<typename T>
 float LoadAnimation(AnimationDefinition& animationDefinition, Index nodeIndex, Index propertyIndex, const std::string& propertyName, const gltf2::Animation::Channel& channel, ConversionContext& context)
 {
-  AnimatedProperty& animatedProperty = animationDefinition.mProperties[propertyIndex];
-
+  AnimatedProperty animatedProperty;
   animatedProperty.mNodeIndex    = nodeIndex;
   animatedProperty.mPropertyName = propertyName;
 
@@ -1119,6 +1407,7 @@ float LoadAnimation(AnimationDefinition& animationDefinition, Index nodeIndex, I
   float duration               = LoadKeyFrames<T>(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
   animatedProperty.mTimePeriod = {0.f, duration};
 
+  animationDefinition.SetProperty(propertyIndex, std::move(animatedProperty));
   return duration;
 }
 
@@ -1134,7 +1423,7 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte
 
     if(!animation.mName.empty())
     {
-      animationDefinition.mName = animation.mName;
+      animationDefinition.SetName(animation.mName.data());
     }
 
     uint32_t numberOfProperties = 0u;
@@ -1149,7 +1438,7 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte
         numberOfProperties++;
       }
     }
-    animationDefinition.mProperties.resize(numberOfProperties);
+    animationDefinition.ReserveSize(numberOfProperties);
 
     Index propertyIndex = 0u;
     for(const auto& channel : animation.mChannels)
@@ -1176,7 +1465,7 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte
         }
         case gltf2::Animation::Channel::Target::WEIGHTS:
         {
-          duration = LoadBlendShapeKeyFrames(context, channel, nodeIndex, propertyIndex, animationDefinition.mProperties);
+          duration = LoadBlendShapeKeyFrames(context, channel, nodeIndex, propertyIndex, animationDefinition);
 
           break;
         }
@@ -1187,7 +1476,7 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte
         }
       }
 
-      animationDefinition.mDuration = std::max(duration, animationDefinition.mDuration);
+      animationDefinition.SetDuration(std::max(duration, animationDefinition.GetDuration()));
 
       ++propertyIndex;
     }
@@ -1225,7 +1514,7 @@ void ProcessSkins(const gltf2::Document& document, ConversionContext& context)
         DALI_LOG_ERROR("Failed to load from stream\n");
       }
       mStream.clear();
-      mStream.seekg(accessor.mBufferView->mByteOffset + accessor.mByteOffset, mStream.beg);
+      mStream.seekg(static_cast<std::streamoff>(static_cast<std::size_t>(accessor.mBufferView->mByteOffset + accessor.mByteOffset)), mStream.beg);
     }
 
     virtual void Provide(Matrix& inverseBindMatrix) override
@@ -1278,22 +1567,6 @@ void ProcessSkins(const gltf2::Document& document, ConversionContext& context)
   }
 }
 
-void ProduceShaders(ShaderDefinitionFactory& shaderFactory, Dali::Scene3D::Loader::SceneDefinition& scene)
-{
-  uint32_t nodeCount = scene.GetNodeCount();
-  for(uint32_t i = 0; i < nodeCount; ++i)
-  {
-    auto nodeDefinition = scene.GetNode(i);
-    for(auto& renderable : nodeDefinition->mRenderables)
-    {
-      if(shaderFactory.ProduceShader(*renderable) == INVALID_INDEX)
-      {
-        DALI_LOG_ERROR("Fail to produce shader\n");
-      }
-    }
-  }
-}
-
 void SetObjectReaders()
 {
   json::SetObjectReader(GetBufferReader());
@@ -1305,6 +1578,8 @@ void SetObjectReaders()
   json::SetObjectReader(GetImageReader());
   json::SetObjectReader(GetSamplerReader());
   json::SetObjectReader(GetTextureReader());
+  json::SetObjectReader(GetTextureTransformReader());
+  json::SetObjectReader(GetTextureExtensionsReader());
   json::SetObjectReader(GetTextureInfoReader());
   json::SetObjectReader(GetMaterialPbrReader());
   json::SetObjectReader(GetMaterialSpecularReader());
@@ -1312,6 +1587,8 @@ void SetObjectReaders()
   json::SetObjectReader(GetMaterialExtensionsReader());
   json::SetObjectReader(GetMaterialReader());
   json::SetObjectReader(GetMeshPrimitiveReader());
+  json::SetObjectReader(GetMeshExtrasReader());
+  json::SetObjectReader(GetMeshExtensionsReader());
   json::SetObjectReader(GetMeshReader());
   json::SetObjectReader(GetSkinReader());
   json::SetObjectReader(GetCameraPerspectiveReader());
@@ -1393,8 +1670,19 @@ bool GenerateDocument(json::unique_ptr& root, gt::Document& document, bool& isMR
 
 void ConvertGltfToContext(gt::Document& document, Gltf2Util::ConversionContext& context, bool isMRendererModel)
 {
-  Dali::Scene3D::Loader::ShaderDefinitionFactory shaderFactory;
-  shaderFactory.SetResources(context.mOutput.mResources);
+  for(auto& extension : document.mExtensionsRequired)
+  {
+    gltf2::ExtensionFlags flag;
+    if(Dali::Scripting::GetEnumeration<gltf2::ExtensionFlags>(extension.data(), EXTENSION_STRING_TABLE, EXTENSION_STRING_TABLE_COUNT, flag))
+    {
+      document.mExtensionFlags |= flag;
+    }
+    else
+    {
+      DALI_LOG_ERROR("Unsupported glTF extension required: %s\n", extension.data());
+      DALI_ASSERT_DEBUG(false && "Unsupported glTF extension required");
+    }
+  }
 
   Gltf2Util::ConvertBuffers(document, context);
   Gltf2Util::ConvertMaterials(document, context);
@@ -1402,8 +1690,6 @@ void ConvertGltfToContext(gt::Document& document, Gltf2Util::ConversionContext&
   Gltf2Util::ConvertNodes(document, context, isMRendererModel);
   Gltf2Util::ConvertAnimations(document, context);
   Gltf2Util::ProcessSkins(document, context);
-  Gltf2Util::ProduceShaders(shaderFactory, context.mOutput.mScene);
-  context.mOutput.mScene.EnsureUniqueSkinningShaderInstances(context.mOutput.mResources);
 
   // Set Default Environment map
   Gltf2Util::SetDefaultEnvironmentMap(document, context);
@@ -1411,4 +1697,4 @@ void ConvertGltfToContext(gt::Document& document, Gltf2Util::ConversionContext&
 
 } // namespace Gltf2Util
 
-} // namespace Dali::Scene3D::Loader::Internal
\ No newline at end of file
+} // namespace Dali::Scene3D::Loader::Internal