/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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-toolkit/internal/controls/control/control-data-impl.h>
#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <dali/integration-api/debug.h>
#include <dali/public-api/math/math-utils.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <dali/public-api/object/type-registry.h>
-#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <filesystem>
// INTERNAL INCLUDES
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/loader/animation-definition.h>
#include <dali-scene3d/public-api/loader/camera-parameters.h>
-#include <dali-scene3d/public-api/loader/cube-map-loader.h>
#include <dali-scene3d/public-api/loader/dli-loader.h>
#include <dali-scene3d/public-api/loader/gltf2-loader.h>
#include <dali-scene3d/public-api/loader/light-parameters.h>
Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector<Dali::Scene3D::Loader::BlendshapeShaderConfigurationRequest>&& requests)
{
std::vector<std::string> errors;
- auto onError = [&errors](const std::string& msg) { errors.push_back(msg); };
+ auto onError = [&errors](const std::string& msg)
+ { errors.push_back(msg); };
if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError))
{
Dali::Scene3D::Loader::ExceptionFlinger flinger(ASSERT_LOCATION);
void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
{
bool needIblReset = false;
- bool isOnScene = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
+ bool isOnScene = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
if(mDiffuseIblUrl != diffuseUrl)
{
mDiffuseIblUrl = diffuseUrl;
if(mDiffuseIblUrl.empty())
{
- needIblReset = true;
+ needIblReset = true;
}
else
{
mSpecularIblUrl = specularUrl;
if(mSpecularIblUrl.empty())
{
- needIblReset = true;
+ needIblReset = true;
}
else
{
// we don't need to request to load texture.
if(needIblReset)
{
- if(mIblDiffuseLoadTask)
- {
- Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
- mIblDiffuseLoadTask.Reset();
- }
-
- if(mIblSpecularLoadTask)
- {
- Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
- mIblSpecularLoadTask.Reset();
- }
+ ResetResourceTask(mIblDiffuseLoadTask);
+ ResetResourceTask(mIblSpecularLoadTask);
mIblDiffuseDirty = false;
mIblSpecularDirty = false;
{
if(isOnScene && mIblDiffuseDirty)
{
- if(mIblDiffuseLoadTask)
- {
- Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
- mIblDiffuseLoadTask.Reset();
- }
- mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, MakeCallback(this, &Model::OnIblDiffuseLoadComplete));
+ ResetResourceTask(mIblDiffuseLoadTask);
+ mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblDiffuseLoadComplete));
Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
mIblDiffuseDirty = false;
}
if(isOnScene && mIblSpecularDirty)
{
- if(mIblSpecularLoadTask)
- {
- Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
- mIblSpecularLoadTask.Reset();
- }
- mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, MakeCallback(this, &Model::OnIblSpecularLoadComplete));
+ ResetResourceTask(mIblSpecularLoadTask);
+ mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblSpecularLoadComplete));
Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
mIblSpecularDirty = false;
}
}
// If diffuse and specular textures are already loaded, emits resource ready signal here.
- if(IsResourceReady())
- {
- Control::SetResourceReady(false);
- }
+ NotifyResourceReady();
}
void Model::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
void Model::ScaleModel()
{
- if(mModelRoot)
+ if(!mModelRoot)
{
- float scale = 1.0f;
- Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
- if(size.x > 0.0f && size.y > 0.0f)
- {
- scale = MAXFLOAT;
- scale = std::min(size.x / mNaturalSize.x, scale);
- scale = std::min(size.y / mNaturalSize.y, scale);
- }
- // Models in glTF and dli are defined as right hand coordinate system.
- // DALi uses left hand coordinate system. Scaling negative is for change winding order.
- mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION * scale);
+ return;
}
+
+ float scale = 1.0f;
+ Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+ if(size.x > 0.0f && size.y > 0.0f)
+ {
+ scale = MAXFLOAT;
+ scale = std::min(size.x / mNaturalSize.x, scale);
+ scale = std::min(size.y / mNaturalSize.y, scale);
+ }
+ // Models in glTF and dli are defined as right hand coordinate system.
+ // DALi uses left hand coordinate system. Scaling negative is for change winding order.
+ mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION * scale);
}
void Model::FitModelPosition()
{
- if(mModelRoot)
+ if(!mModelRoot)
{
- // Loaded model pivot is not the model center.
- mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
- mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
+ return;
}
+ // Loaded model pivot is not the model center.
+ mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
}
void Model::CollectRenderableActor(Actor actor)
for(auto&& actor : mRenderableActors)
{
Actor renderableActor = actor.GetHandle();
- if(renderableActor)
+ if(!renderableActor)
+ {
+ continue;
+ }
+
+ uint32_t rendererCount = renderableActor.GetRendererCount();
+ for(uint32_t i = 0; i < rendererCount; ++i)
{
- uint32_t rendererCount = renderableActor.GetRendererCount();
- for(uint32_t i = 0; i < rendererCount; ++i)
+ Dali::Renderer renderer = renderableActor.GetRendererAt(i);
+ if(!renderer)
{
- Dali::Renderer renderer = renderableActor.GetRendererAt(i);
- if(renderer)
- {
- Dali::TextureSet textures = renderer.GetTextures();
- if(textures)
- {
- uint32_t textureCount = textures.GetTextureCount();
- // EnvMap requires at least 2 texture, diffuse and specular
- if(textureCount > 2u)
- {
- textures.SetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE, currentDiffuseTexture);
- textures.SetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE, currentSpecularTexture);
- }
- }
- }
+ continue;
+ }
+ Dali::TextureSet textures = renderer.GetTextures();
+ if(!textures)
+ {
+ continue;
+ }
+ uint32_t textureCount = textures.GetTextureCount();
+ // EnvMap requires at least 2 texture, diffuse and specular
+ if(textureCount > 2u)
+ {
+ textures.SetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE, currentDiffuseTexture);
+ textures.SetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE, currentSpecularTexture);
}
- renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
}
+ renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
}
}
return;
}
- mModelRoot = Actor::New();
- mModelRoot.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
-
- BoundingVolume AABB;
- auto* resources = &(mModelLoadTask->mResources);
- auto* scene = &(mModelLoadTask->mScene);
- Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
- Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{*resources, xforms, {}, {}, {}};
- uint32_t rootCount = 0u;
- for(auto iRoot : scene->GetRoots())
- {
- resources->GenerateResources(mModelLoadTask->mResourceRefCounts[rootCount]);
-
- if(auto actor = scene->CreateNodes(iRoot, mModelLoadTask->mResourceChoices, nodeParams))
- {
- scene->ConfigureSkeletonJoints(iRoot, resources->mSkeletons, actor);
- scene->ConfigureSkinningShaders(*resources, actor, std::move(nodeParams.mSkinnables));
- ConfigureBlendShapeShaders(*resources, *scene, actor, std::move(nodeParams.mBlendshapeRequests));
-
- scene->ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
-
- mModelRoot.Add(actor);
- }
-
- AddModelTreeToAABB(AABB, *scene, mModelLoadTask->mResourceChoices, iRoot, nodeParams, Matrix::IDENTITY);
- rootCount++;
- }
+ CreateModel();
+ mRenderableActors.clear();
+ CollectRenderableActor(mModelRoot);
+ auto* resources = &(mModelLoadTask->mResources);
+ auto* scene = &(mModelLoadTask->mScene);
+ CreateAnimations(*scene);
if(!resources->mEnvironmentMaps.empty())
{
mDefaultDiffuseTexture = resources->mEnvironmentMaps.front().second.mDiffuse;
mDefaultSpecularTexture = resources->mEnvironmentMaps.front().second.mSpecular;
}
- if(!mModelLoadTask->mAnimations.empty())
- {
- auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property)
- {
- Dali::Actor actor;
- if(property.mNodeIndex != Scene3D::Loader::INVALID_INDEX)
- {
- auto* node = scene->GetNode(property.mNodeIndex);
- if(node != nullptr)
- {
- actor = mModelRoot.FindChildById(node->mNodeId);
- }
- }
- else
- {
- actor = mModelRoot.FindChildByName(property.mNodeName);
- }
- return actor;
- };
-
- mAnimations.clear();
- for(auto&& animation : mModelLoadTask->mAnimations)
- {
- Dali::Animation anim = animation.ReAnimate(getActor);
-
- mAnimations.push_back({animation.mName, anim});
- }
- }
-
- mRenderableActors.clear();
- CollectRenderableActor(mModelRoot);
-
UpdateImageBasedLightTexture();
UpdateImageBasedLightScaleFactor();
- mNaturalSize = AABB.CalculateSize();
- mModelPivot = AABB.CalculatePivot();
- mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
- Vector3 controlSize = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
- if(Dali::EqualsZero(controlSize.x) || Dali::EqualsZero(controlSize.y))
- {
- Self().SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
- }
-
- FitModelPosition();
- ScaleModel();
-
mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
Self().Add(mModelRoot);
-
Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
mModelResourceReady = true;
-
- if(IsResourceReady())
- {
- Control::SetResourceReady(false);
- }
- mModelLoadTask.Reset();
+ NotifyResourceReady();
+ ResetResourceTask(mModelLoadTask);
}
void Model::OnIblDiffuseLoadComplete()
{
- mDiffuseTexture = (mIblDiffuseLoadTask->HasSucceeded()) ? mIblDiffuseLoadTask->GetEnvironmentMap().CreateTexture() : Texture();
+ mDiffuseTexture = mIblDiffuseLoadTask->GetLoadedTexture();
+ ResetResourceTask(mIblDiffuseLoadTask);
mIblDiffuseResourceReady = true;
if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
{
OnIblLoadComplete();
}
- mIblDiffuseLoadTask.Reset();
}
void Model::OnIblSpecularLoadComplete()
{
- mSpecularTexture = (mIblSpecularLoadTask->HasSucceeded()) ? mIblSpecularLoadTask->GetEnvironmentMap().CreateTexture() : Texture();
+ mSpecularTexture = mIblSpecularLoadTask->GetLoadedTexture();
+ ResetResourceTask(mIblSpecularLoadTask);
mIblSpecularResourceReady = true;
if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
{
OnIblLoadComplete();
}
- mIblSpecularLoadTask.Reset();
}
void Model::OnIblLoadComplete()
{
UpdateImageBasedLightTexture();
+ NotifyResourceReady();
+}
- if(IsResourceReady())
+void Model::ResetResourceTasks()
+{
+ if(!Dali::Adaptor::IsAvailable())
{
- Control::SetResourceReady(false);
+ return;
}
+ ResetResourceTask(mModelLoadTask);
+ ResetResourceTask(mIblDiffuseLoadTask);
+ ResetResourceTask(mIblSpecularLoadTask);
}
-void Model::ResetResourceTasks()
+void Model::ResetResourceTask(IntrusivePtr<AsyncTask> asyncTask)
{
- if(Dali::Adaptor::IsAvailable())
+ if(!asyncTask)
{
- if(mModelLoadTask)
+ return;
+ }
+ Dali::AsyncTaskManager::Get().RemoveTask(asyncTask);
+ asyncTask.Reset();
+}
+
+void Model::NotifyResourceReady()
+{
+ if(!IsResourceReady())
+ {
+ return;
+ }
+ Control::SetResourceReady(false);
+}
+
+void Model::CreateModel()
+{
+ mModelRoot = Actor::New();
+ mModelRoot.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
+
+ BoundingVolume AABB;
+ auto* resources = &(mModelLoadTask->mResources);
+ auto* scene = &(mModelLoadTask->mScene);
+ Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
+ Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{*resources, xforms, {}, {}, {}};
+ uint32_t rootCount = 0u;
+ for(auto iRoot : scene->GetRoots())
+ {
+ resources->GenerateResources(mModelLoadTask->mResourceRefCounts[rootCount]);
+
+ if(auto actor = scene->CreateNodes(iRoot, mModelLoadTask->mResourceChoices, nodeParams))
{
- Dali::AsyncTaskManager::Get().RemoveTask(mModelLoadTask);
- mModelLoadTask.Reset();
+ scene->ConfigureSkeletonJoints(iRoot, resources->mSkeletons, actor);
+ scene->ConfigureSkinningShaders(*resources, actor, std::move(nodeParams.mSkinnables));
+ ConfigureBlendShapeShaders(*resources, *scene, actor, std::move(nodeParams.mBlendshapeRequests));
+
+ scene->ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
+
+ mModelRoot.Add(actor);
}
- if(mIblDiffuseLoadTask)
+
+ AddModelTreeToAABB(AABB, *scene, mModelLoadTask->mResourceChoices, iRoot, nodeParams, Matrix::IDENTITY);
+ rootCount++;
+ }
+
+ mNaturalSize = AABB.CalculateSize();
+ mModelPivot = AABB.CalculatePivot();
+ mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
+ Vector3 controlSize = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+ if(Dali::EqualsZero(controlSize.x) || Dali::EqualsZero(controlSize.y))
+ {
+ Self().SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
+ }
+ FitModelPosition();
+ ScaleModel();
+}
+
+void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene)
+{
+ if(!mModelLoadTask->mAnimations.empty())
+ {
+ auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property)
{
- Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
- mIblDiffuseLoadTask.Reset();
- }
- if(mIblSpecularLoadTask)
+ if(property.mNodeIndex == Scene3D::Loader::INVALID_INDEX)
+ {
+ return mModelRoot.FindChildByName(property.mNodeName);
+ }
+ auto* node = scene.GetNode(property.mNodeIndex);
+ if(node == nullptr)
+ {
+ return Dali::Actor();
+ }
+ return mModelRoot.FindChildById(node->mNodeId);
+ };
+
+ mAnimations.clear();
+ for(auto&& animation : mModelLoadTask->mAnimations)
{
- Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
- mIblSpecularLoadTask.Reset();
+ Dali::Animation anim = animation.ReAnimate(getActor);
+ mAnimations.push_back({animation.mName, anim});
}
}
}