[dali_2.1.26] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene-loader / public-api / gltf2-loader.cpp
index 18923cf..8af87a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -42,6 +42,11 @@ const std::string POSITION_PROPERTY("position");
 const std::string ORIENTATION_PROPERTY("orientation");
 const std::string SCALE_PROPERTY("scale");
 const std::string BLEND_SHAPE_WEIGHTS_UNIFORM("uBlendShapeWeight");
+const std::string MRENDERER_MODEL_IDENTIFICATION("M-Renderer");
+const std::string ROOT_NODE_NAME("RootNode");
+const Vector3     SCALE_TO_ADJUST(100.0f, 100.0f, 100.0f);
+
+constexpr float DEFAULT_INTENSITY = 0.5f;
 
 const Geometry::Type GLTF2_TO_DALI_PRIMITIVES[]{
   Geometry::POINTS,
@@ -61,6 +66,7 @@ struct AttributeMapping
   {gt::Attribute::NORMAL, &MeshDefinition::mNormals, sizeof(Vector3)},
   {gt::Attribute::TANGENT, &MeshDefinition::mTangents, sizeof(Vector3)},
   {gt::Attribute::TEXCOORD_0, &MeshDefinition::mTexCoords, sizeof(Vector2)},
+  {gt::Attribute::COLOR_0, &MeshDefinition::mColors, sizeof(Vector4)},
   {gt::Attribute::JOINTS_0, &MeshDefinition::mJoints0, sizeof(Vector4)},
   {gt::Attribute::WEIGHTS_0, &MeshDefinition::mWeights0, sizeof(Vector4)},
 };
@@ -152,7 +158,8 @@ const auto TEXURE_READER = std::move(js::Reader<gt::Texture>()
 const auto TEXURE_INFO_READER = std::move(js::Reader<gt::TextureInfo>()
                                             .Register(*js::MakeProperty("index", gt::RefReader<gt::Document>::Read<gt::Texture, &gt::Document::mTextures>, &gt::TextureInfo::mTexture))
                                             .Register(*js::MakeProperty("texCoord", js::Read::Number<uint32_t>, &gt::TextureInfo::mTexCoord))
-                                            .Register(*js::MakeProperty("scale", js::Read::Number<float>, &gt::TextureInfo::mScale)));
+                                            .Register(*js::MakeProperty("scale", js::Read::Number<float>, &gt::TextureInfo::mScale))
+                                            .Register(*js::MakeProperty("strength", js::Read::Number<float>, &gt::TextureInfo::mStrength)));
 
 const auto MATERIAL_PBR_READER = std::move(js::Reader<gt::Material::Pbr>()
                                              .Register(*js::MakeProperty("baseColorFactor", gt::ReadDaliVector<Vector4>, &gt::Material::Pbr::mBaseColorFactor))
@@ -433,9 +440,9 @@ void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials)
     matDef.SetAlphaCutoff(std::min(1.f, std::max(0.f, m.mAlphaCutoff)));
   }
 
-  matDef.mColor = pbr.mBaseColorFactor;
+  matDef.mBaseColorFactor = pbr.mBaseColorFactor;
 
-  matDef.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!m.mNormalTexture);
+  matDef.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!m.mNormalTexture + !!m.mOcclusionTexture + !!m.mEmissiveTexture);
   if(pbr.mBaseColorTexture)
   {
     const auto semantic = MaterialDefinition::ALBEDO;
@@ -443,6 +450,10 @@ void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials)
     // TODO: and there had better be one
     matDef.mFlags |= semantic;
   }
+  else
+  {
+    matDef.mNeedAlbedoTexture = false;
+  }
 
   matDef.mMetallic  = pbr.mMetallicFactor;
   matDef.mRoughness = pbr.mRoughnessFactor;
@@ -455,7 +466,12 @@ void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials)
     // TODO: and there had better be one
     matDef.mFlags |= semantic;
   }
+  else
+  {
+    matDef.mNeedMetallicRoughnessTexture = false;
+  }
 
+  matDef.mNormalScale = m.mNormalTexture.mScale;
   if(m.mNormalTexture)
   {
     const auto semantic = MaterialDefinition::NORMAL;
@@ -463,8 +479,29 @@ void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials)
     // TODO: and there had better be one
     matDef.mFlags |= semantic;
   }
+  else
+  {
+    matDef.mNeedNormalTexture = false;
+  }
 
   // TODO: handle doubleSided
+  if(m.mOcclusionTexture)
+  {
+    const auto semantic = MaterialDefinition::OCCLUSION;
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mOcclusionTexture)});
+    // TODO: and there had better be one
+    matDef.mFlags |= semantic;
+    matDef.mOcclusionStrength = m.mOcclusionTexture.mStrength;
+  }
+
+  if(m.mEmissiveTexture)
+  {
+    const auto semantic = MaterialDefinition::EMISSIVE;
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mEmissiveTexture)});
+    // TODO: and there had better be one
+    matDef.mFlags |= semantic;
+    matDef.mEmissiveFactor = m.mEmissiveFactor;
+  }
 
   outMaterials.emplace_back(std::move(matDef), TextureSet());
 }
@@ -557,6 +594,9 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& cctx)
 
       auto& accPositions = *attribs.find(gt::Attribute::POSITION)->second;
       meshDef.mPositions = ConvertMeshPrimitiveAccessor(accPositions);
+      // glTF2 support vector4 tangent for mesh.
+      // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#meshes-overview
+      meshDef.mTangentType = Property::VECTOR4;
 
       const bool needNormalsTangents = accPositions.mType == gt::AccessorType::VEC3;
       for(auto& am : ATTRIBUTE_MAPPINGS)
@@ -568,14 +608,6 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& cctx)
           auto& accessor = meshDef.*(am.mAccessor);
           accessor       = ConvertMeshPrimitiveAccessor(*iFind->second);
 
-          // Fixing up -- a few of glTF2 sample models have VEC4 tangents; we need VEC3s.
-          if(iFind->first == gt::Attribute::TANGENT && (accessor.mBlob.mElementSizeHint > am.mElementSizeRequired))
-          {
-            accessor.mBlob.mStride          = std::max(static_cast<uint16_t>(accessor.mBlob.mStride + accessor.mBlob.mElementSizeHint - am.mElementSizeRequired),
-                                              accessor.mBlob.mElementSizeHint);
-            accessor.mBlob.mElementSizeHint = am.mElementSizeRequired;
-          }
-
           if(iFind->first == gt::Attribute::JOINTS_0)
           {
             meshDef.mFlags |= (iFind->second->mComponentType == gt::Component::UNSIGNED_SHORT) * MeshDefinition::U16_JOINT_IDS;
@@ -692,7 +724,7 @@ void ConvertCamera(const gt::Camera& camera, CameraParameters& camParams)
   }
 }
 
-void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& cctx)
+void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& cctx, bool isMRendererModel)
 {
   auto& output    = cctx.mOutput;
   auto& scene     = output.mScene;
@@ -715,6 +747,11 @@ void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, Con
       nodeDef->mPosition    = node.mTranslation;
       nodeDef->mOrientation = node.mRotation;
       nodeDef->mScale       = node.mScale;
+
+      if(isMRendererModel && node.mName == ROOT_NODE_NAME && node.mScale == SCALE_TO_ADJUST)
+      {
+        nodeDef->mScale *= 0.01f;
+      }
     }
 
     return nodeDef;
@@ -774,11 +811,11 @@ void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, Con
 
   for(auto& n : node.mChildren)
   {
-    ConvertNode(*n, n.GetIndex(), idx, cctx);
+    ConvertNode(*n, n.GetIndex(), idx, cctx, isMRendererModel);
   }
 }
 
-void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx)
+void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx, bool isMRendererModel)
 {
   auto& outScene = cctx.mOutput.mScene;
   Index rootIdx  = outScene.GetNodeCount();
@@ -788,7 +825,7 @@ void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx)
       break;
 
     case 1:
-      ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, cctx);
+      ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, cctx, isMRendererModel);
       outScene.AddRootNode(rootIdx);
       break;
 
@@ -802,25 +839,25 @@ void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx)
 
       for(auto& n : scene.mNodes)
       {
-        ConvertNode(*n, n.GetIndex(), rootIdx, cctx);
+        ConvertNode(*n, n.GetIndex(), rootIdx, cctx, isMRendererModel);
       }
       break;
     }
   }
 }
 
-void ConvertNodes(const gt::Document& doc, ConversionContext& cctx)
+void ConvertNodes(const gt::Document& doc, ConversionContext& cctx, bool isMRendererModel)
 {
-  ConvertSceneNodes(*doc.mScene, cctx);
+  ConvertSceneNodes(*doc.mScene, cctx, isMRendererModel);
 
   for(uint32_t i = 0, i1 = doc.mScene.GetIndex(); i < i1; ++i)
   {
-    ConvertSceneNodes(doc.mScenes[i], cctx);
+    ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel);
   }
 
   for(uint32_t i = doc.mScene.GetIndex() + 1; i < doc.mScenes.size(); ++i)
   {
-    ConvertSceneNodes(doc.mScenes[i], cctx);
+    ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel);
   }
 }
 
@@ -1128,6 +1165,14 @@ void SetObjectReaders()
   js::SetObjectReader(SCENE_READER);
 }
 
+void SetDefaultEnvironmentMap(const gt::Document& doc, ConversionContext& cctx)
+{
+  EnvironmentDefinition envDef;
+  envDef.mUseBrdfTexture = true;
+  envDef.mIblIntensity = DEFAULT_INTENSITY;
+  cctx.mOutput.mResources.mEnvironmentMaps.push_back({std::move(envDef), EnvironmentDefinition::Textures()});
+}
+
 } // namespace
 
 void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactory, LoadResult& params)
@@ -1155,10 +1200,23 @@ void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactor
 
   gt::Document doc;
 
-  auto& rootObj        = js::Cast<json_object_s>(*root);
-  auto  jsAsset        = js::FindObjectChild("asset", rootObj);
-  auto  jsAssetVersion = js::FindObjectChild("version", js::Cast<json_object_s>(*jsAsset));
-  doc.mAsset.mVersion  = js::Read::StringView(*jsAssetVersion);
+  auto& rootObj = js::Cast<json_object_s>(*root);
+  auto  jsAsset = js::FindObjectChild("asset", rootObj);
+
+  auto jsAssetVersion = js::FindObjectChild("version", js::Cast<json_object_s>(*jsAsset));
+  if(jsAssetVersion)
+  {
+    doc.mAsset.mVersion = js::Read::StringView(*jsAssetVersion);
+  }
+
+  bool isMRendererModel(false);
+  auto jsAssetGenerator = js::FindObjectChild("generator", js::Cast<json_object_s>(*jsAsset));
+  if(jsAssetGenerator)
+  {
+    doc.mAsset.mGenerator = js::Read::StringView(*jsAssetGenerator);
+    isMRendererModel      = (doc.mAsset.mGenerator.find(MRENDERER_MODEL_IDENTIFICATION) != std::string_view::npos);
+  }
+
 
   gt::SetRefReaderObject(doc);
   DOCUMENT_READER.Read(rootObj, doc);
@@ -1168,13 +1226,14 @@ void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactor
 
   ConvertMaterials(doc, cctx);
   ConvertMeshes(doc, cctx);
-  ConvertNodes(doc, cctx);
+  ConvertNodes(doc, cctx, isMRendererModel);
   ConvertAnimations(doc, cctx);
-
   ProcessSkins(doc, cctx);
-
   ProduceShaders(shaderFactory, params.mScene);
   params.mScene.EnsureUniqueSkinningShaderInstances(params.mResources);
+
+  // Set Default Environment map
+  SetDefaultEnvironmentMap(doc, cctx);
 }
 
 } // namespace SceneLoader