Parse gltf mesh extra and extensions + Get BlendShape index by name
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / loader / gltf2-util.cpp
index 4c46c3a..90deac9 100644 (file)
@@ -19,6 +19,7 @@
 #include <dali-scene3d/internal/loader/gltf2-util.h>
 
 // EXTERNAL INCLUDES
+#include <dali/devel-api/threading/mutex.h>
 #include <dali/integration-api/debug.h>
 
 using namespace Dali::Scene3D::Loader;
@@ -280,6 +281,44 @@ const json::Reader<gltf2::Mesh::Primitive>& GetMeshPrimitiveReader()
   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)
+    {
+      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>()
@@ -287,7 +326,9 @@ const json::Reader<gltf2::Mesh>& GetMeshReader()
                                               .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("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;
 }
 
@@ -556,12 +597,14 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
   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)));
   }
 
@@ -617,8 +660,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;
@@ -755,6 +798,12 @@ void ConvertMeshes(const gltf2::Document& document, ConversionContext& context)
             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);
           }
+          if(iFind->first == gltf2::Attribute::WEIGHTS_0)
+          {
+            meshDefinition.mFlags |= (iFind->second->mComponentType == gltf2::Component::UNSIGNED_SHORT) * MeshDefinition::U16_WEIGHT;
+            meshDefinition.mFlags |= (iFind->second->mComponentType == gltf2::Component::UNSIGNED_BYTE) * MeshDefinition::U8_WEIGHT;
+            DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U16_WEIGHT) || MaskMatch(meshDefinition.mFlags, MeshDefinition::U8_WEIGHT) || iFind->second->mComponentType == gltf2::Component::FLOAT);
+          }
         }
         else if(needNormalsTangents)
         {
@@ -786,6 +835,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;
@@ -812,7 +862,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;
         }
       }
 
@@ -1074,7 +1139,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;
@@ -1090,7 +1155,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);
@@ -1110,6 +1175,8 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation
     }
 
     animatedProperty.mTimePeriod = {0.f, duration};
+
+    animationDefinition.SetProperty(propertyIndex++, std::move(animatedProperty));
   }
 
   return duration;
@@ -1118,8 +1185,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;
 
@@ -1127,6 +1193,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;
 }
 
@@ -1142,7 +1209,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;
@@ -1157,7 +1224,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)
@@ -1184,7 +1251,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;
         }
@@ -1195,7 +1262,7 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte
         }
       }
 
-      animationDefinition.mDuration = std::max(duration, animationDefinition.mDuration);
+      animationDefinition.SetDuration(std::max(duration, animationDefinition.GetDuration()));
 
       ++propertyIndex;
     }
@@ -1320,6 +1387,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());