X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-scene3d%2Finternal%2Fcontrols%2Fmodel%2Fmodel-impl.cpp;h=f012aa6ac9ce8668513f6801add26c9a90637705;hb=7892a19ca3a420eb54bcafa007d82bb5fe44c55c;hp=b0f8294d2e2d8f03a8e0d37e0fdf85ce90d1cf9a;hpb=9bbca96c9151fb1a96b47e17f09c720b7c05adc2;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-scene3d/internal/controls/model/model-impl.cpp b/dali-scene3d/internal/controls/model/model-impl.cpp index b0f8294..f012aa6 100644 --- a/dali-scene3d/internal/controls/model/model-impl.cpp +++ b/dali-scene3d/internal/controls/model/model-impl.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -31,8 +31,11 @@ #include // INTERNAL INCLUDES +#include #include #include +#include +#include #include #include #include @@ -41,8 +44,9 @@ #include #include #include -#include - +#include +#include +#include using namespace Dali; namespace Dali @@ -117,8 +121,7 @@ void ConfigureBlendShapeShaders( Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector&& requests) { std::vector 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); @@ -171,6 +174,77 @@ void AddModelTreeToAABB(BoundingVolume& AABB, const Dali::Scene3D::Loader::Scene } } +void UpdateBlendShapeNodeMapRecursively(Model::BlendShapeModelNodeMap& resultMap, const Scene3D::ModelNode& node) +{ + 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 blendShapeNames; + node.RetrieveBlendShapeNames(blendShapeNames); + for(const auto& iter : blendShapeNames) + { + // Append or create new list. + resultMap[iter].push_back(node); + } +} + +void UpdateShaderRecursively(Scene3D::ModelNode node, Scene3D::Loader::ShaderManagerPtr shaderManager) +{ + if(!node) + { + return; + } + + GetImplementation(node).UpdateShader(shaderManager); + + uint32_t childrenCount = node.GetChildCount(); + for(uint32_t i = 0; i < childrenCount; ++i) + { + Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i)); + if(childNode) + { + UpdateShaderRecursively(childNode, shaderManager); + } + } +} + +void UpdateShadowMapTextureRecursively(Scene3D::ModelNode node, Dali::Texture shadowMapTexture) +{ + if(!node) + { + return; + } + + GetImplementation(node).SetShadowMapTexture(shadowMapTexture); + + uint32_t childrenCount = node.GetChildCount(); + for(uint32_t i = 0; i < childrenCount; ++i) + { + Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i)); + if(childNode) + { + UpdateShadowMapTextureRecursively(childNode, shadowMapTexture); + } + } +} + +void ResetResourceTask(IntrusivePtr&& asyncTask) +{ + if(!asyncTask) + { + return; + } + Dali::AsyncTaskManager::Get().RemoveTask(asyncTask); + asyncTask.Reset(); +} + } // anonymous namespace Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl) @@ -178,6 +252,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), @@ -190,18 +265,20 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr mIblDiffuseResourceReady(true), mIblSpecularResourceReady(true), mIblDiffuseDirty(false), - mIblSpecularDirty(false) + mIblSpecularDirty(false), + mIsShadowCasting(true), + mIsShadowReceiving(true) { } Model::~Model() { + ResetResourceTasks(); + if(ModelCacheManager::Get() && !mModelUrl.empty()) { ModelCacheManager::Get().UnreferenceModelCache(mModelUrl); } - - ResetResourceTasks(); } Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl) @@ -235,22 +312,66 @@ void Model::AddModelNode(Scene3D::ModelNode modelNode) mModelResourceReady = true; } + UpdateShaderRecursively(modelNode, mShaderManager); + + if(mShadowMapTexture) + { + UpdateShadowMapTextureRecursively(modelNode, mShadowMapTexture); + } + if(mIblDiffuseResourceReady && mIblSpecularResourceReady) { UpdateImageBasedLightTexture(); 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(Dali::Actor::Property::CONNECTED_TO_SCENE)) { NotifyResourceReady(); } } +void Model::RegisterColliderMesh(Scene3D::ModelNode& modelNode) +{ + mColliderMeshes[modelNode.GetProperty(Actor::Property::ID)] = modelNode; + + // Add processor + Scene3D::ColliderMeshProcessor::Get().ColliderMeshChanged(Scene3D::Model::DownCast(Self())); +} + +void Model::RemoveColliderMesh(Scene3D::ModelNode& node) +{ + auto id = node.GetProperty(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); mModelRoot.Remove(modelNode); } } @@ -337,6 +458,9 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s mDiffuseTexture.Reset(); mSpecularTexture.Reset(); UpdateImageBasedLightTexture(); + + // Request image resource GC + Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect(); } else { @@ -346,6 +470,9 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s 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) @@ -354,6 +481,9 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s 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(); } } @@ -458,6 +588,253 @@ Scene3D::ModelNode Model::FindChildModelNodeByName(std::string_view nodeName) return Scene3D::ModelNode::DownCast(childActor); } +void Model::RetrieveBlendShapeNames(std::vector& blendShapeNames) const +{ + blendShapeNames.reserve(blendShapeNames.size() + mBlendShapeModelNodeMap.size()); + for(const auto& iter : mBlendShapeModelNodeMap) + { + blendShapeNames.push_back(iter.first); + } +} + +void Model::RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector& modelNodes) const +{ + auto iter = mBlendShapeModelNodeMap.find(std::string(blendShapeName)); + if(iter != mBlendShapeModelNodeMap.end()) + { + const auto& modelNodeList = iter->second; + modelNodes.reserve(modelNodes.size() + modelNodeList.size()); + for(const auto& nodeIter : modelNodeList) + { + modelNodes.push_back(nodeIter); + } + } +} + +Dali::Animation Model::GenerateMotionDataAnimation(Scene3D::MotionData motionData) +{ + Dali::Animation animation; + + // TODO : Need to collect duplicated codes with SetMotionData() + + if(motionData) + { + const uint32_t motionCount = motionData.GetMotionCount(); + for(uint32_t i = 0u; i < motionCount; ++i) + { + auto motionIndex = motionData.GetIndex(i); + auto motionValue = motionData.GetValue(i); + if(motionIndex && motionValue) + { + if(motionIndex.GetModelNodeId() != Property::INVALID_KEY) + { + Scene3D::ModelNode modelNode; + if(motionIndex.GetModelNodeId().type == Property::Key::Type::STRING) + { + modelNode = FindChildModelNodeByName(motionIndex.GetModelNodeId().stringKey); + } + else if(motionIndex.GetModelNodeId().type == Property::Key::Type::INDEX) + { + // TODO : Not implement yet. + } + + if(modelNode) + { + KeyFrames keyFrames = motionValue.GetKeyFrames(); + + if(keyFrames) + { + // Try to use index first. If failed, try to use name + Property::Index animatedPropertyIndex = motionIndex.GetPropertyIndex(modelNode); + if(animatedPropertyIndex != Property::INVALID_INDEX) + { + if(DALI_UNLIKELY(!animation)) + { + animation = Animation::New(motionData.GetDuration()); + } + animation.AnimateBetween(Dali::Property(modelNode, animatedPropertyIndex), keyFrames); + } + else + { + std::string animatedPropertyName = motionIndex.GetPropertyName(modelNode); + Dali::Property property(modelNode, animatedPropertyName); + if(property.propertyIndex != Property::INVALID_INDEX) + { + if(DALI_UNLIKELY(!animation)) + { + animation = Animation::New(motionData.GetDuration()); + } + animation.AnimateBetween(property, keyFrames); + } + } + } + } + } + else + { + Scene3D::BlendShapeIndex blendShapeIndex = Scene3D::BlendShapeIndex::DownCast(motionIndex); + if(blendShapeIndex && blendShapeIndex.GetBlendShapeId().type == Property::Key::Type::STRING) + { + // Special case : For BlendShapeIndex that doesn't have ModelNodeId and has string BlendShapeId, + // we need to animate all kind of blendshapes + + KeyFrames keyFrames = motionValue.GetKeyFrames(); + + if(keyFrames) + { + std::vector modelNodes; + RetrieveModelNodesByBlendShapeName(blendShapeIndex.GetBlendShapeId().stringKey, modelNodes); + + for(auto& modelNode : modelNodes) + { + // Try to use index first. If failed, try to use name + Property::Index animatedPropertyIndex = motionIndex.GetPropertyIndex(modelNode); + if(animatedPropertyIndex != Property::INVALID_INDEX) + { + if(DALI_UNLIKELY(!animation)) + { + animation = Animation::New(motionData.GetDuration()); + } + animation.AnimateBetween(Dali::Property(modelNode, animatedPropertyIndex), keyFrames); + } + else + { + std::string animatedPropertyName = motionIndex.GetPropertyName(modelNode); + Dali::Property property(modelNode, animatedPropertyName); + + if(property.propertyIndex != Property::INVALID_INDEX) + { + if(DALI_UNLIKELY(!animation)) + { + animation = Animation::New(motionData.GetDuration()); + } + animation.AnimateBetween(property, keyFrames); + } + } + } + } + } + } + } + } + } + + return animation; +} + +void Model::SetMotionData(Scene3D::MotionData motionData) +{ + // TODO : Need to collect duplicated codes with GenerateMotionDataAnimation() + + if(motionData) + { + const uint32_t motionCount = motionData.GetMotionCount(); + for(uint32_t i = 0u; i < motionCount; ++i) + { + auto motionIndex = motionData.GetIndex(i); + auto motionValue = motionData.GetValue(i); + if(motionIndex && motionValue) + { + if(motionIndex.GetModelNodeId() != Property::INVALID_KEY) + { + Scene3D::ModelNode modelNode; + if(motionIndex.GetModelNodeId().type == Property::Key::Type::STRING) + { + modelNode = FindChildModelNodeByName(motionIndex.GetModelNodeId().stringKey); + } + else if(motionIndex.GetModelNodeId().type == Property::Key::Type::INDEX) + { + // TODO : Not implement yet. + } + + if(modelNode) + { + Property::Value value = motionValue.GetPropertyValue(); + + if(value.GetType() != Property::Type::NONE) + { + // Try to use index first. If failed, try to use name + Property::Index propertyIndex = motionIndex.GetPropertyIndex(modelNode); + if(propertyIndex != Property::INVALID_INDEX) + { + modelNode.SetProperty(propertyIndex, value); + } + else + { + std::string propertyName = motionIndex.GetPropertyName(modelNode); + Dali::Property property(modelNode, propertyName); + if(property.propertyIndex != Property::INVALID_INDEX) + { + modelNode.SetProperty(property.propertyIndex, value); + } + } + } + } + } + else + { + Scene3D::BlendShapeIndex blendShapeIndex = Scene3D::BlendShapeIndex::DownCast(motionIndex); + if(blendShapeIndex && blendShapeIndex.GetBlendShapeId().type == Property::Key::Type::STRING) + { + // Special case : For BlendShapeIndex that doesn't have ModelNodeId and has string BlendShapeId, + // we need to animate all kind of blendshapes + + Property::Value value = motionValue.GetPropertyValue(); + + if(value.GetType() != Property::Type::NONE) + { + std::vector modelNodes; + RetrieveModelNodesByBlendShapeName(blendShapeIndex.GetBlendShapeId().stringKey, modelNodes); + + for(auto& modelNode : modelNodes) + { + // Try to use index first. If failed, try to use name + Property::Index propertyIndex = motionIndex.GetPropertyIndex(modelNode); + if(propertyIndex != Property::INVALID_INDEX) + { + modelNode.SetProperty(propertyIndex, value); + } + else + { + std::string propertyName = motionIndex.GetPropertyName(modelNode); + Dali::Property property(modelNode, propertyName); + if(property.propertyIndex != Property::INVALID_INDEX) + { + modelNode.SetProperty(property.propertyIndex, value); + } + } + } + } + } + } + } + } + } +} + +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 @@ -467,10 +844,43 @@ void Model::OnInitialize() { // Make ParentOrigin as Center. Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + mDefaultDiffuseTexture = ImageResourceLoader::GetEmptyTextureWhiteRGB(); + mDefaultSpecularTexture = ImageResourceLoader::GetEmptyTextureWhiteRGB(); } 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. @@ -488,19 +898,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)); @@ -510,8 +907,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(Dali::Actor::Property::CONNECTED_TO_SCENE)) { GetImpl(sceneView).UnregisterSceneItem(this); mParentSceneView.Reset(); @@ -607,6 +1007,46 @@ void Model::FitModelPosition() 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) @@ -634,7 +1074,6 @@ void Model::UpdateImageBasedLightScaleFactorRecursively(Scene3D::ModelNode node, return; } - node.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), iblScaleFactor); GetImplementation(node).SetImageBasedLightScaleFactor(iblScaleFactor); uint32_t childrenCount = node.GetChildCount(); @@ -718,6 +1157,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) @@ -745,6 +1193,8 @@ void Model::NotifyImageBasedLightScaleFactor(float scaleFactor) void Model::OnModelLoadComplete() { + IntrusivePtr self = this; // Keep reference until this API finished + if(!mModelLoadTask->HasSucceeded()) { ResetResourceTasks(); @@ -769,17 +1219,27 @@ void Model::OnModelLoadComplete() ResetCameraParameters(); if(!resources.mEnvironmentMaps.empty()) { - mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse; - mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular; + if(resources.mEnvironmentMaps.front().second.mDiffuse) + { + mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse; + } + if(resources.mEnvironmentMaps.front().second.mSpecular) + { + mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular; + } } + if(mShadowMapTexture) + { + UpdateShadowMapTextureRecursively(mModelRoot, mShadowMapTexture); + } UpdateImageBasedLightTexture(); UpdateImageBasedLightScaleFactor(); Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z)); mModelResourceReady = true; - NotifyResourceReady(); ResetResourceTask(mModelLoadTask); + NotifyResourceReady(); } void Model::OnIblDiffuseLoadComplete() @@ -827,51 +1287,44 @@ void Model::ResetResourceTasks() ResetResourceTask(mIblSpecularLoadTask); } -void Model::ResetResourceTask(IntrusivePtr asyncTask) -{ - if(!asyncTask) - { - return; - } - Dali::AsyncTaskManager::Get().RemoveTask(asyncTask); - asyncTask.Reset(); -} - void Model::NotifyResourceReady() { if(!IsResourceReady()) { return; } - Control::SetResourceReady(false); + Control::SetResourceReady(); } 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(); for(auto iRoot : scene.GetRoots()) { - if(auto actor = scene.CreateNodes(iRoot, resourceChoices, nodeParams)) + if(auto modelNode = scene.CreateNodes(iRoot, resourceChoices, nodeParams)) { - scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); - ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); + scene.ConfigureSkinningShaders(resources, modelNode, std::move(nodeParams.mSkinnables)); + ConfigureBlendShapeShaders(resources, scene, modelNode, std::move(nodeParams.mBlendshapeRequests)); - scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); + scene.ApplyConstraints(modelNode, std::move(nodeParams.mConstrainables)); - mModelRoot.Add(actor); + mModelRoot.Add(modelNode); } AddModelTreeToAABB(AABB, scene, resourceChoices, iRoot, nodeParams, Matrix::IDENTITY); } + UpdateBlendShapeNodeMap(); + mNaturalSize = AABB.CalculateSize(); mModelPivot = AABB.CalculatePivot(); mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize); @@ -889,8 +1342,7 @@ void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene) mAnimations.clear(); if(!mModelLoadTask->GetAnimations().empty()) { - auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) - { + auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) { if(property.mNodeIndex == Scene3D::Loader::INVALID_INDEX) { return mModelRoot.FindChildByName(property.mNodeName); @@ -921,6 +1373,14 @@ void Model::ResetCameraParameters() } } +void Model::UpdateBlendShapeNodeMap() +{ + // Remove privous node map + mBlendShapeModelNodeMap.clear(); + + UpdateBlendShapeNodeMapRecursively(mBlendShapeModelNodeMap, mModelRoot); +} + } // namespace Internal } // namespace Scene3D } // namespace Dali