3D Scene Hit Testing
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / model-components / model-node-impl.cpp
index 257cbd0..d566163 100644 (file)
@@ -24,6 +24,8 @@
 #include <dali/public-api/object/type-registry.h>
 
 // INTERNAL INCLUDES
+#include <dali-scene3d/internal/controls/model/model-impl.h>
+#include <dali-scene3d/internal/light/light-impl.h>
 #include <dali-scene3d/internal/model-components/model-primitive-impl.h>
 
 namespace Dali
@@ -172,7 +174,7 @@ uint32_t ModelNode::GetModelPrimitiveCount() const
   return static_cast<uint32_t>(mModelPrimitiveContainer.size());
 }
 
-void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
+void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive, Loader::ShaderOption::HashType hash)
 {
   for(auto&& primitive : mModelPrimitiveContainer)
   {
@@ -186,11 +188,18 @@ void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
 
   Actor self = Self();
   GetImplementation(modelPrimitive).AddPrimitiveObserver(this);
+  if(mShadowMapTexture)
+  {
+    GetImplementation(modelPrimitive).SetShadowMapTexture(mShadowMapTexture);
+  }
+
   if(mDiffuseTexture && mSpecularTexture)
   {
     GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
   }
 
+  GetImplementation(modelPrimitive).UpdateShader(mShaderManager, hash);
+
   Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
   if(renderer)
   {
@@ -220,6 +229,7 @@ void ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitiv
     {
       continue;
     }
+
     RemoveModelPrimitive(i);
     break;
   }
@@ -232,6 +242,8 @@ void ModelNode::RemoveModelPrimitive(uint32_t index)
     return;
   }
 
+  GetImplementation(mModelPrimitiveContainer[index]).UpdateShader(nullptr, 0u);
+
   Actor self = Self();
   GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
 
@@ -259,6 +271,34 @@ Scene3D::ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName
   return Scene3D::ModelNode::DownCast(childActor);
 }
 
+void ModelNode::RetrieveBlendShapeNames(std::vector<std::string>& blendShapeNames) const
+{
+  blendShapeNames.reserve(blendShapeNames.size() + mBlendShapeIndexMap.size());
+  for(const auto& iter : mBlendShapeIndexMap)
+  {
+    blendShapeNames.push_back(iter.first);
+  }
+}
+
+Loader::BlendShapes::Index ModelNode::GetBlendShapeIndexByName(std::string_view blendShapeName) const
+{
+  auto iter = mBlendShapeIndexMap.find(std::string(blendShapeName));
+  if(iter != mBlendShapeIndexMap.end())
+  {
+    return iter->second;
+  }
+  return Loader::BlendShapes::INVALID_INDEX;
+}
+
+void ModelNode::SetShadowMapTexture(Dali::Texture shadowMapTexture)
+{
+  mShadowMapTexture = shadowMapTexture;
+  for(auto&& primitive : mModelPrimitiveContainer)
+  {
+    GetImplementation(primitive).SetShadowMapTexture(mShadowMapTexture);
+  }
+}
+
 void ModelNode::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
 {
   mDiffuseTexture       = diffuseTexture;
@@ -280,8 +320,32 @@ void ModelNode::SetImageBasedLightScaleFactor(float iblScaleFactor)
   }
 }
 
+void ModelNode::UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager)
+{
+  if(mShaderManager != shaderManager)
+  {
+    mShaderManager = shaderManager;
+    for(auto&& primitive : mModelPrimitiveContainer)
+    {
+      GetImplementation(primitive).UpdateShader(mShaderManager, 0u);
+    }
+  }
+}
+
 void ModelNode::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
 {
+  // Update mBlendShapeIndexMap
+  mBlendShapeIndexMap.clear();
+  const auto blendShapeCount = data.names.size();
+  for(Loader::BlendShapes::Index index = 0u; index < blendShapeCount; ++index)
+  {
+    auto& name = data.names[index];
+    if(!name.empty())
+    {
+      mBlendShapeIndexMap[name] = index;
+    }
+  }
+
   GetImplementation(primitive).SetBlendShapeData(data);
 }
 
@@ -319,35 +383,75 @@ void ModelNode::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive)
       continue;
     }
 
-    Dali::Shader shader = renderer.GetShader();
-    if(!shader)
-    {
-      continue;
-    }
-
     if(boneData.constraint)
     {
       boneData.constraint.Remove();
       boneData.constraint.Reset();
     }
 
-    if(shader.GetPropertyIndex(boneData.propertyName) == Property::INVALID_INDEX)
+    auto propBoneXform = renderer.GetPropertyIndex(boneData.propertyName);
+    if(propBoneXform == Property::INVALID_INDEX)
     {
-      auto propBoneXform = shader.RegisterProperty(boneData.propertyName, Matrix{false});
+      propBoneXform = renderer.RegisterProperty(boneData.propertyName, Matrix{false});
+    }
 
-      Matrix inverseMatrix = boneData.inverseMatrix;
-      // Constrain bone matrix to joint transform.
-      boneData.constraint = Constraint::New<Matrix>(shader, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs)
-                                                    { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
+    Matrix inverseMatrix = boneData.inverseMatrix;
+    // Constrain bone matrix to joint transform.
+    boneData.constraint = Constraint::New<Matrix>(renderer, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs) { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
 
-      Actor joint = Self();
-      boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX});
-      boneData.constraint.ApplyPost();
-    }
+    Actor joint = Self();
+    boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX});
+    boneData.constraint.ApplyPost();
     break;
   }
 }
 
+void ModelNode::SetColliderMesh(ColliderMeshUniquePtr&& colliderMesh)
+{
+  if(!colliderMesh && !mColliderMesh)
+  {
+    return;
+  }
+
+  if(!mParentModel) // find parent model if not set
+  {
+    auto parent = Self().GetParent();
+    while(parent)
+    {
+      auto modelHandle = Scene3D::Model::DownCast(parent);
+      if(modelHandle)
+      {
+        mParentModel = &GetImpl(modelHandle);
+        break;
+      }
+      parent = parent.GetParent();
+    }
+  }
+
+  // Resetting collider mesh if argument is nullptr
+  auto handle = Scene3D::ModelNode::DownCast(Self());
+  if(mParentModel)
+  {
+    if(mColliderMesh || colliderMesh == nullptr)
+    {
+      mParentModel->RemoveColliderMesh(handle);
+    }
+    mParentModel->RegisterColliderMesh(handle, *colliderMesh);
+  }
+
+  mColliderMesh = std::move(colliderMesh);
+}
+
+bool ModelNode::HasColliderMesh() const
+{
+  return mColliderMesh != nullptr;
+}
+
+const Scene3D::Algorithm::ColliderMesh& ModelNode::GetColliderMesh() const
+{
+  return *mColliderMesh;
+}
+
 } // namespace Internal
 
 } // namespace Scene3D