/*
- * 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/common/image-resource-loader.h>
#include <dali-scene3d/internal/common/model-cache-manager.h>
#include <dali-scene3d/internal/controls/scene-view/scene-view-impl.h>
+#include <dali-scene3d/internal/event/collider-mesh-processor.h>
#include <dali-scene3d/internal/light/light-impl.h>
#include <dali-scene3d/internal/model-components/model-node-impl.h>
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/loader/scene-definition.h>
#include <dali-scene3d/public-api/loader/shader-manager.h>
#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
-
+#include <dali-toolkit/public-api/controls/control-impl.h>
using namespace Dali;
namespace Dali
}
}
+void ResetResourceTask(IntrusivePtr<AsyncTask>&& asyncTask)
+{
+ if(!asyncTask)
+ {
+ return;
+ }
+ Dali::AsyncTaskManager::Get().RemoveTask(asyncTask);
+ asyncTask.Reset();
+}
+
} // anonymous namespace
Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
mIblDiffuseResourceReady(true),
mIblSpecularResourceReady(true),
mIblDiffuseDirty(false),
- mIblSpecularDirty(false)
+ mIblSpecularDirty(false),
+ mIsShadowCasting(true),
+ mIsShadowReceiving(true)
{
}
UpdateImageBasedLightScaleFactor();
}
+ GetImplementation(modelNode).SetRootModel(this);
+
+ // If model has a collider mesh set, add it to the container
+ if(modelNode.HasColliderMesh())
+ {
+ RegisterColliderMesh(modelNode);
+ Scene3D::ColliderMeshProcessor::Get().ColliderMeshChanged(Scene3D::Model::DownCast(Self()));
+ }
+
if(Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
{
NotifyResourceReady();
}
}
+void Model::RegisterColliderMesh(Scene3D::ModelNode& modelNode)
+{
+ mColliderMeshes[modelNode.GetProperty<int>(Actor::Property::ID)] = modelNode;
+
+ // Add processor
+ Scene3D::ColliderMeshProcessor::Get().ColliderMeshChanged(Scene3D::Model::DownCast(Self()));
+}
+
+void Model::RemoveColliderMesh(Scene3D::ModelNode& node)
+{
+ auto id = node.GetProperty<int>(Actor::Property::ID);
+ auto iter = std::find_if(mColliderMeshes.begin(), mColliderMeshes.end(), [id](auto& item) {
+ return item.first == id;
+ });
+ if(iter != mColliderMeshes.end())
+ {
+ mColliderMeshes.erase(iter);
+ }
+}
+
void Model::RemoveModelNode(Scene3D::ModelNode modelNode)
{
+ // remove collider mesh from the list if node is being removed
+ if(modelNode.HasColliderMesh())
+ {
+ RemoveColliderMesh(modelNode);
+ GetImplementation(modelNode).SetRootModel(nullptr);
+ }
+
if(mModelRoot)
{
UpdateShaderRecursively(modelNode, nullptr);
mDiffuseTexture.Reset();
mSpecularTexture.Reset();
UpdateImageBasedLightTexture();
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
else
{
mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblDiffuseLoadComplete));
Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
mIblDiffuseDirty = false;
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
if(isOnScene && mIblSpecularDirty)
mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblSpecularLoadComplete));
Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
mIblSpecularDirty = false;
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
}
}
}
+void Model::CastShadow(bool castShadow)
+{
+ mIsShadowCasting = castShadow;
+ UpdateCastShadowRecursively(mModelRoot, mIsShadowCasting);
+}
+
+bool Model::IsShadowCasting() const
+{
+ return mIsShadowCasting;
+}
+
+void Model::ReceiveShadow(bool receiveShadow)
+{
+ mIsShadowReceiving = receiveShadow;
+ UpdateReceiveShadowRecursively(mModelRoot, mIsShadowReceiving);
+}
+
+bool Model::IsShadowReceiving() const
+{
+ return mIsShadowReceiving;
+}
+
+
///////////////////////////////////////////////////////////
//
// Private methods
mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
}
+void Model::UpdateCastShadowRecursively(Scene3D::ModelNode node, bool castShadow)
+{
+ if(!node)
+ {
+ return;
+ }
+
+ GetImplementation(node).CastShadow(castShadow);
+ uint32_t childrenCount = node.GetChildCount();
+ for(uint32_t i = 0; i < childrenCount; ++i)
+ {
+ Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
+ if(!childNode)
+ {
+ continue;
+ }
+ UpdateCastShadowRecursively(childNode, castShadow);
+ }
+}
+
+void Model::UpdateReceiveShadowRecursively(Scene3D::ModelNode node, bool receiveShadow)
+{
+ if(!node)
+ {
+ return;
+ }
+
+ GetImplementation(node).ReceiveShadow(receiveShadow);
+ uint32_t childrenCount = node.GetChildCount();
+ for(uint32_t i = 0; i < childrenCount; ++i)
+ {
+ Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
+ if(!childNode)
+ {
+ continue;
+ }
+ UpdateReceiveShadowRecursively(childNode, receiveShadow);
+ }
+}
+
void Model::UpdateImageBasedLightTextureRecursively(Scene3D::ModelNode node, Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
{
if(!node)
ResetResourceTask(mIblSpecularLoadTask);
}
-void Model::ResetResourceTask(IntrusivePtr<AsyncTask> asyncTask)
-{
- if(!asyncTask)
- {
- return;
- }
- Dali::AsyncTaskManager::Get().RemoveTask(asyncTask);
- asyncTask.Reset();
-}
-
void Model::NotifyResourceReady()
{
if(!IsResourceReady())