Merge changes I776588c1,I7292a2fb into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / controls / model / model-impl.cpp
index 7c82d4b..2763de6 100644 (file)
@@ -42,7 +42,7 @@
 #include <dali-scene3d/public-api/loader/load-result.h>
 #include <dali-scene3d/public-api/loader/node-definition.h>
 #include <dali-scene3d/public-api/loader/scene-definition.h>
-#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
 #include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
 
 using namespace Dali;
@@ -172,33 +172,35 @@ void AddModelTreeToAABB(BoundingVolume& AABB, const Dali::Scene3D::Loader::Scene
   }
 }
 
-void AddLightRecursively(Scene3D::ModelNode node, Scene3D::Light light, uint32_t lightIndex)
+void UpdateBlendShapeNodeMapRecursively(Model::BlendShapeModelNodeMap& resultMap, const Scene3D::ModelNode& node)
 {
   if(!node)
   {
     return;
   }
-  GetImplementation(node).AddLight(light, lightIndex);
+  const auto childCount = node.GetChildCount();
+  for(auto i = 0u; i < childCount; ++i)
+  {
+    UpdateBlendShapeNodeMapRecursively(resultMap, Scene3D::ModelNode::DownCast(node.GetChildAt(i)));
+  }
 
-  uint32_t childrenCount = node.GetChildCount();
-  for(uint32_t i = 0; i < childrenCount; ++i)
+  std::vector<std::string> blendShapeNames;
+  node.RetrieveBlendShapeNames(blendShapeNames);
+  for(const auto& iter : blendShapeNames)
   {
-    Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
-    if(childNode)
-    {
-      AddLightRecursively(childNode, light, lightIndex);
-    }
+    // Append or create new list.
+    resultMap[iter].push_back(node);
   }
 }
 
-void RemoveLightRecursively(Scene3D::ModelNode node, uint32_t lightIndex)
+void UpdateShaderRecursively(Scene3D::ModelNode node, Scene3D::Loader::ShaderManagerPtr shaderManager)
 {
   if(!node)
   {
     return;
   }
 
-  GetImplementation(node).RemoveLight(lightIndex);
+  GetImplementation(node).UpdateShader(shaderManager);
 
   uint32_t childrenCount = node.GetChildCount();
   for(uint32_t i = 0; i < childrenCount; ++i)
@@ -206,29 +208,28 @@ void RemoveLightRecursively(Scene3D::ModelNode node, uint32_t lightIndex)
     Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
     if(childNode)
     {
-      RemoveLightRecursively(childNode, lightIndex);
+      UpdateShaderRecursively(childNode, shaderManager);
     }
   }
 }
 
-void UpdateBlendShapeNodeMapRecursively(Model::BlendShapeModelNodeMap& resultMap, const Scene3D::ModelNode& node)
+void UpdateShadowMapTextureRecursively(Scene3D::ModelNode node, Dali::Texture shadowMapTexture)
 {
   if(!node)
   {
     return;
   }
-  const auto childCount = node.GetChildCount();
-  for(auto i = 0u; i < childCount; ++i)
-  {
-    UpdateBlendShapeNodeMapRecursively(resultMap, Scene3D::ModelNode::DownCast(node.GetChildAt(i)));
-  }
 
-  std::vector<std::string> blendShapeNames;
-  node.RetrieveBlendShapeNames(blendShapeNames);
-  for(const auto& iter : blendShapeNames)
+  GetImplementation(node).SetShadowMapTexture(shadowMapTexture);
+
+  uint32_t childrenCount = node.GetChildCount();
+  for(uint32_t i = 0; i < childrenCount; ++i)
   {
-    // Append or create new list.
-    resultMap[iter].push_back(node);
+    Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
+    if(childNode)
+    {
+      UpdateShadowMapTextureRecursively(childNode, shadowMapTexture);
+    }
   }
 }
 
@@ -239,6 +240,7 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr
   mModelUrl(modelUrl),
   mResourceDirectoryUrl(resourceDirectoryUrl),
   mModelRoot(),
+  mShaderManager(new Scene3D::Loader::ShaderManager()),
   mNaturalSize(Vector3::ZERO),
   mModelPivot(AnchorPoint::CENTER),
   mSceneIblScaleFactor(1.0f),
@@ -296,19 +298,17 @@ void Model::AddModelNode(Scene3D::ModelNode modelNode)
     mModelResourceReady = true;
   }
 
-  if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
+  UpdateShaderRecursively(modelNode, mShaderManager);
+
+  if(mShadowMapTexture)
   {
-    UpdateImageBasedLightTexture();
-    UpdateImageBasedLightScaleFactor();
+    UpdateShadowMapTextureRecursively(modelNode, mShadowMapTexture);
   }
 
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
+  if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
   {
-    if(mLights[i])
-    {
-      AddLightRecursively(modelNode, mLights[i], i);
-    }
+    UpdateImageBasedLightTexture();
+    UpdateImageBasedLightScaleFactor();
   }
 
   if(Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
@@ -321,14 +321,7 @@ void Model::RemoveModelNode(Scene3D::ModelNode modelNode)
 {
   if(mModelRoot)
   {
-    uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-    for(uint32_t i = 0; i < maxLightCount; ++i)
-    {
-      if(mLights[i])
-      {
-        RemoveLightRecursively(modelNode, i);
-      }
-    }
+    UpdateShaderRecursively(modelNode, nullptr);
     mModelRoot.Remove(modelNode);
   }
 }
@@ -769,11 +762,40 @@ void Model::OnInitialize()
 {
   // Make ParentOrigin as Center.
   Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-  mLights.resize(Scene3D::Internal::Light::GetMaximumEnabledLightCount());
 }
 
 void Model::OnSceneConnection(int depth)
 {
+  Actor parent = Self().GetParent();
+  while(parent)
+  {
+    // If this Model has parent SceneView and the its ShaderManager is same with privious ShaderManager,
+    // this Model don't need to update shader.
+    Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
+    if(sceneView)
+    {
+      mParentSceneView = sceneView;
+      GetImpl(sceneView).RegisterSceneItem(this);
+      Scene3D::Loader::ShaderManagerPtr shaderManager = GetImpl(sceneView).GetShaderManager();
+      if(mShaderManager != shaderManager)
+      {
+        mShaderManager = shaderManager;
+        UpdateShaderRecursively(mModelRoot, mShaderManager);
+      }
+      break;
+    }
+    parent = parent.GetParent();
+  }
+
+  // Model can be added on Dali::Scene directly without SceneView.
+  // So, Model's mShaderManager and shaders of child ModelNodes are needed to be reset when this Model has not parent SceneView.
+  Scene3D::SceneView parentSceneView = mParentSceneView.GetHandle();
+  if(!parentSceneView)
+  {
+    mShaderManager = new Dali::Scene3D::Loader::ShaderManager();
+    UpdateShaderRecursively(mModelRoot, mShaderManager);
+  }
+
   if(!mModelLoadTask && !mModelResourceReady && !mModelUrl.empty())
   {
     // Request model load only if we setup url.
@@ -791,19 +813,6 @@ void Model::OnSceneConnection(int depth)
     SetImageBasedLightSource(mDiffuseIblUrl, mSpecularIblUrl, mIblScaleFactor);
   }
 
-  Actor parent = Self().GetParent();
-  while(parent)
-  {
-    Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
-    if(sceneView)
-    {
-      GetImpl(sceneView).RegisterSceneItem(this);
-      mParentSceneView = sceneView;
-      break;
-    }
-    parent = parent.GetParent();
-  }
-
   NotifyResourceReady();
 
   mSizeNotification = Self().AddPropertyNotification(Actor::Property::SIZE, StepCondition(SIZE_STEP_CONDITION));
@@ -813,8 +822,11 @@ void Model::OnSceneConnection(int depth)
 
 void Model::OnSceneDisconnection()
 {
+  // If mParentSceneView is still onScene, that means this model
+  // is disconnected from mParentSceneView's sub tree.
+  // So, Unregister this Model from SceneView.
   Scene3D::SceneView sceneView = mParentSceneView.GetHandle();
-  if(sceneView)
+  if(sceneView && sceneView.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
   {
     GetImpl(sceneView).UnregisterSceneItem(this);
     mParentSceneView.Reset();
@@ -1020,6 +1032,15 @@ void Model::ApplyCameraTransform(Dali::CameraActor camera) const
   camera.SetProperty(Actor::Property::SCALE, resultScale);
 }
 
+void Model::NotifyShadowMapTexture(Dali::Texture shadowMapTexture)
+{
+  if(mShadowMapTexture != shadowMapTexture)
+  {
+    mShadowMapTexture = shadowMapTexture;
+    UpdateShadowMapTextureRecursively(mModelRoot, mShadowMapTexture);
+  }
+}
+
 void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels)
 {
   if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
@@ -1045,21 +1066,6 @@ void Model::NotifyImageBasedLightScaleFactor(float scaleFactor)
   }
 }
 
-void Model::NotifyLightAdded(uint32_t lightIndex, Scene3D::Light light)
-{
-  mLights[lightIndex] = light;
-  AddLightRecursively(mModelRoot, light, lightIndex);
-}
-
-void Model::NotifyLightRemoved(uint32_t lightIndex)
-{
-  if(mLights[lightIndex])
-  {
-    RemoveLightRecursively(mModelRoot, lightIndex);
-    mLights[lightIndex].Reset();
-  }
-}
-
 void Model::OnModelLoadComplete()
 {
   if(!mModelLoadTask->HasSucceeded())
@@ -1090,15 +1096,10 @@ void Model::OnModelLoadComplete()
     mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular;
   }
 
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
+  if(mShadowMapTexture)
   {
-    if(mLights[i])
-    {
-      AddLightRecursively(mModelRoot, mLights[i], i);
-    }
+    UpdateShadowMapTextureRecursively(mModelRoot, mShadowMapTexture);
   }
-
   UpdateImageBasedLightTexture();
   UpdateImageBasedLightScaleFactor();
   Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
@@ -1174,12 +1175,13 @@ void Model::NotifyResourceReady()
 
 void Model::CreateModel()
 {
-  BoundingVolume                                      AABB;
-  auto&                                               resources       = mModelLoadTask->GetResources();
-  auto&                                               scene           = mModelLoadTask->GetScene();
-  auto&                                               resourceChoices = mModelLoadTask->GetResourceChoices();
-  Dali::Scene3D::Loader::Transforms                   xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
-  Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}};
+  BoundingVolume                    AABB;
+  auto&                             resources       = mModelLoadTask->GetResources();
+  auto&                             scene           = mModelLoadTask->GetScene();
+  auto&                             resourceChoices = mModelLoadTask->GetResourceChoices();
+  Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
+
+  Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, mShaderManager, {}, {}, {}};
 
   // Generate Dali handles from resource bundle. Note that we generate all scene's resouce immediatly.
   resources.GenerateResources();