X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-scene3d%2Finternal%2Fcontrols%2Fmodel%2Fmodel-impl.cpp;h=b0f8294d2e2d8f03a8e0d37e0fdf85ce90d1cf9a;hb=c1236a21a2ddc2da56cb8d54b4ab7e7b1b6c2b50;hp=3345bfc3ffee09fc464db991eec5ed1733534df4;hpb=56897b0a8957791cb016bd3310b76c60e1baf8a6;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 3345bfc..b0f8294 100644 --- a/dali-scene3d/internal/controls/model/model-impl.cpp +++ b/dali-scene3d/internal/controls/model/model-impl.cpp @@ -23,20 +23,20 @@ #include #include #include +#include #include #include #include #include -#include #include // INTERNAL INCLUDES +#include #include +#include #include #include #include -#include -#include #include #include #include @@ -53,6 +53,9 @@ namespace Internal { namespace { +/** + * Creates control through type registry + */ BaseHandle Create() { return Scene3D::Model::New(std::string()); @@ -62,10 +65,8 @@ BaseHandle Create() DALI_TYPE_REGISTRATION_BEGIN(Scene3D::Model, Toolkit::Control, Create); DALI_TYPE_REGISTRATION_END() -static constexpr uint32_t OFFSET_FOR_DIFFUSE_CUBE_TEXTURE = 2u; -static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u; - static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f); +static constexpr float SIZE_STEP_CONDITION = 0.1f; static constexpr bool DEFAULT_MODEL_CHILDREN_SENSITIVE = false; static constexpr bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false; @@ -116,7 +117,8 @@ 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); @@ -180,6 +182,8 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr mModelPivot(AnchorPoint::CENTER), mSceneIblScaleFactor(1.0f), mIblScaleFactor(1.0f), + mSceneSpecularMipmapLevels(1u), + mSpecularMipmapLevels(1u), mModelChildrenSensitive(DEFAULT_MODEL_CHILDREN_SENSITIVE), mModelChildrenFocusable(DEFAULT_MODEL_CHILDREN_FOCUSABLE), mModelResourceReady(false), @@ -192,6 +196,11 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr Model::~Model() { + if(ModelCacheManager::Get() && !mModelUrl.empty()) + { + ModelCacheManager::Get().UnreferenceModelCache(mModelUrl); + } + ResetResourceTasks(); } @@ -208,11 +217,44 @@ Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& return handle; } -const Actor Model::GetModelRoot() const +const Scene3D::ModelNode Model::GetModelRoot() const { return mModelRoot; } +void Model::AddModelNode(Scene3D::ModelNode modelNode) +{ + if(!mModelRoot) + { + CreateModelRoot(); + } + + mModelRoot.Add(modelNode); + if(mModelUrl.empty()) + { + mModelResourceReady = true; + } + + if(mIblDiffuseResourceReady && mIblSpecularResourceReady) + { + UpdateImageBasedLightTexture(); + UpdateImageBasedLightScaleFactor(); + } + + if(Self().GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE)) + { + NotifyResourceReady(); + } +} + +void Model::RemoveModelNode(Scene3D::ModelNode modelNode) +{ + if(mModelRoot) + { + mModelRoot.Remove(modelNode); + } +} + void Model::SetChildrenSensitive(bool enable) { if(mModelChildrenSensitive != enable) @@ -251,13 +293,13 @@ bool Model::GetChildrenFocusable() const void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor) { bool needIblReset = false; - bool isOnScene = Self().GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE); + bool isOnScene = Self().GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE); if(mDiffuseIblUrl != diffuseUrl) { mDiffuseIblUrl = diffuseUrl; if(mDiffuseIblUrl.empty()) { - needIblReset = true; + needIblReset = true; } else { @@ -271,7 +313,7 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s mSpecularIblUrl = specularUrl; if(mSpecularIblUrl.empty()) { - needIblReset = true; + needIblReset = true; } else { @@ -284,17 +326,8 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s // 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; @@ -309,11 +342,7 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s { if(isOnScene && mIblDiffuseDirty) { - if(mIblDiffuseLoadTask) - { - Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask); - mIblDiffuseLoadTask.Reset(); - } + ResetResourceTask(mIblDiffuseLoadTask); mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblDiffuseLoadComplete)); Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask); mIblDiffuseDirty = false; @@ -321,11 +350,7 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s if(isOnScene && mIblSpecularDirty) { - if(mIblSpecularLoadTask) - { - Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask); - mIblSpecularLoadTask.Reset(); - } + ResetResourceTask(mIblSpecularLoadTask); mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblSpecularLoadComplete)); Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask); mIblSpecularDirty = false; @@ -339,22 +364,7 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s } // If diffuse and specular textures are already loaded, emits resource ready signal here. - if(IsResourceReady()) - { - Control::SetResourceReady(false); - } -} - -void Model::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor) -{ - // If input texture is wrong, Model is rendered with SceneView's IBL. - if(mDiffuseTexture != diffuseTexture || mSpecularTexture != specularTexture) - { - mDiffuseTexture = diffuseTexture; - mSpecularTexture = specularTexture; - mIblScaleFactor = scaleFactor; - UpdateImageBasedLightTexture(); - } + NotifyResourceReady(); } void Model::SetImageBasedLightScaleFactor(float scaleFactor) @@ -403,6 +413,51 @@ Dali::Animation Model::GetAnimation(const std::string& name) const return animation; } +uint32_t Model::GetCameraCount() const +{ + return mCameraParameters.size(); +} + +Dali::CameraActor Model::GenerateCamera(uint32_t index) const +{ + Dali::CameraActor camera; + if(mCameraParameters.size() > index) + { + camera = Dali::CameraActor::New3DCamera(); + if(!mCameraParameters[index].ConfigureCamera(camera, false)) + { + DALI_LOG_ERROR("Fail to generate %u's camera actor : Some property was not defined. Please check model file.\n", index); + camera.Reset(); + return camera; + } + + ApplyCameraTransform(camera); + } + return camera; +} + +bool Model::ApplyCamera(uint32_t index, Dali::CameraActor camera) const +{ + if(camera && mCameraParameters.size() > index) + { + if(!mCameraParameters[index].ConfigureCamera(camera, false)) + { + DALI_LOG_ERROR("Fail to apply %u's camera actor : Some property was not defined. Please check model file.\n", index); + return false; + } + + ApplyCameraTransform(camera); + return true; + } + return false; +} + +Scene3D::ModelNode Model::FindChildModelNodeByName(std::string_view nodeName) +{ + Actor childActor = Self().FindChildByName(nodeName); + return Scene3D::ModelNode::DownCast(childActor); +} + /////////////////////////////////////////////////////////// // // Private methods @@ -416,12 +471,17 @@ void Model::OnInitialize() void Model::OnSceneConnection(int depth) { - if(!mModelLoadTask && !mModelRoot) + if(!mModelLoadTask && !mModelResourceReady && !mModelUrl.empty()) { - Scene3D::Loader::InitializeGltfLoader(); + // Request model load only if we setup url. + if(ModelCacheManager::Get()) + { + ModelCacheManager::Get().ReferenceModelCache(mModelUrl); + } mModelLoadTask = new ModelLoadTask(mModelUrl, mResourceDirectoryUrl, MakeCallback(this, &Model::OnModelLoadComplete)); Dali::AsyncTaskManager::Get().AddTask(mModelLoadTask); } + // If diffuse and specular url is not valid, IBL does not need to be loaded. if(!mDiffuseIblUrl.empty() && !mSpecularIblUrl.empty()) { @@ -441,6 +501,10 @@ void Model::OnSceneConnection(int depth) parent = parent.GetParent(); } + NotifyResourceReady(); + + mSizeNotification = Self().AddPropertyNotification(Actor::Property::SIZE, StepCondition(SIZE_STEP_CONDITION)); + mSizeNotification.NotifySignal().Connect(this, &Model::OnSizeNotification); Control::OnSceneConnection(depth); } @@ -452,9 +516,19 @@ void Model::OnSceneDisconnection() GetImpl(sceneView).UnregisterSceneItem(this); mParentSceneView.Reset(); } + + mSizeNotification.NotifySignal().Disconnect(this, &Model::OnSizeNotification); + Self().RemovePropertyNotification(mSizeNotification); + mSizeNotification.Reset(); + Control::OnSceneDisconnection(); } +void Model::OnSizeSet(const Vector3& size) +{ + ScaleModel(false); +} + Vector3 Model::GetNaturalSize() { if(!mModelRoot) @@ -483,7 +557,7 @@ float Model::GetWidthForHeight(float height) void Model::OnRelayout(const Vector2& size, RelayoutContainer& container) { Control::OnRelayout(size, container); - ScaleModel(); + ScaleModel(false); } bool Model::IsResourceReady() const @@ -491,91 +565,108 @@ bool Model::IsResourceReady() const return mModelResourceReady && mIblDiffuseResourceReady && mIblSpecularResourceReady; } -void Model::ScaleModel() +void Model::CreateModelRoot() { - if(mModelRoot) + mModelRoot = Scene3D::ModelNode::New(); + mModelRoot.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR); + mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION); + 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); +} + +void Model::ScaleModel(bool useCurrentSize) +{ + if(!mModelRoot) { - float scale = 1.0f; - Vector3 size = Self().GetProperty(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 = (useCurrentSize) ? Self().GetCurrentProperty(Dali::Actor::Property::SIZE) : Self().GetProperty(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) +void Model::UpdateImageBasedLightTextureRecursively(Scene3D::ModelNode node, Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels) { - uint32_t rendererCount = actor.GetRendererCount(); - if(rendererCount) + if(!node) { - mRenderableActors.push_back(actor); + return; } - uint32_t childrenCount = actor.GetChildCount(); + GetImplementation(node).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels); + uint32_t childrenCount = node.GetChildCount(); for(uint32_t i = 0; i < childrenCount; ++i) { - CollectRenderableActor(actor.GetChildAt(i)); + Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i)); + if(!childNode) + { + continue; + } + UpdateImageBasedLightTextureRecursively(childNode, diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels); } } -void Model::UpdateImageBasedLightTexture() +void Model::UpdateImageBasedLightScaleFactorRecursively(Scene3D::ModelNode node, float iblScaleFactor) { - Dali::Texture currentDiffuseTexture = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture; - Dali::Texture currentSpecularTexture = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture; - float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor; - - if(!currentDiffuseTexture || !currentSpecularTexture) + if(!node) { - currentDiffuseTexture = mDefaultDiffuseTexture; - currentSpecularTexture = mDefaultSpecularTexture; - currentIblScaleFactor = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity(); + return; } - for(auto&& actor : mRenderableActors) + node.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), iblScaleFactor); + GetImplementation(node).SetImageBasedLightScaleFactor(iblScaleFactor); + + uint32_t childrenCount = node.GetChildCount(); + for(uint32_t i = 0; i < childrenCount; ++i) { - Actor renderableActor = actor.GetHandle(); - if(renderableActor) + Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i)); + if(!childNode) { - uint32_t rendererCount = renderableActor.GetRendererCount(); - for(uint32_t i = 0; i < rendererCount; ++i) - { - 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); - } - } - } - } - renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor); + continue; } + UpdateImageBasedLightScaleFactorRecursively(childNode, iblScaleFactor); } } +void Model::UpdateImageBasedLightTexture() +{ + Dali::Texture currentDiffuseTexture = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture; + Dali::Texture currentSpecularTexture = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture; + float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor; + uint32_t currentIblSpecularMipmapLevels = (mDiffuseTexture && mSpecularTexture) ? mSpecularMipmapLevels : mSceneSpecularMipmapLevels; + + if(!currentDiffuseTexture || !currentSpecularTexture) + { + currentDiffuseTexture = mDefaultDiffuseTexture; + currentSpecularTexture = mDefaultSpecularTexture; + currentIblScaleFactor = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity(); + currentIblSpecularMipmapLevels = 1u; + } + + UpdateImageBasedLightTextureRecursively(mModelRoot, currentDiffuseTexture, currentSpecularTexture, currentIblScaleFactor, currentIblSpecularMipmapLevels); +} + void Model::UpdateImageBasedLightScaleFactor() { if((!mDiffuseTexture || !mSpecularTexture) && @@ -585,23 +676,56 @@ void Model::UpdateImageBasedLightScaleFactor() } float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor; - for(auto&& actor : mRenderableActors) + UpdateImageBasedLightScaleFactorRecursively(mModelRoot, currentIblScaleFactor); +} + +void Model::ApplyCameraTransform(Dali::CameraActor camera) const +{ + Vector3 selfPosition = Self().GetProperty(Actor::Property::POSITION); + Quaternion selfOrientation = Self().GetProperty(Actor::Property::ORIENTATION); + Vector3 selfScale = Self().GetProperty(Actor::Property::SCALE); + + Vector3 cameraPosition = camera.GetProperty(Actor::Property::POSITION); + Quaternion cameraOrientation = camera.GetProperty(Actor::Property::ORIENTATION); + Vector3 cameraScale = camera.GetProperty(Actor::Property::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. + if(!Dali::Equals(Y_DIRECTION.Dot(Vector3::YAXIS), 1.0f)) { - Actor renderableActor = actor.GetHandle(); - if(renderableActor) - { - renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor); - } + // Reflect by XZ plane + cameraPosition.y = -cameraPosition.y; + Quaternion yDirectionQuaternion; + yDirectionQuaternion.mVector = Vector3::YAXIS; + // Reflect orientation + cameraOrientation = yDirectionQuaternion * cameraOrientation * yDirectionQuaternion; } + + Vector3 resultPosition; + Quaternion resultOrientation; + Vector3 resultScale; + + Matrix selfMatrix(false); + Matrix cameraMatrix(false); + Matrix resultMatrix(false); + selfMatrix.SetTransformComponents(selfScale, selfOrientation, selfPosition); + cameraMatrix.SetTransformComponents(cameraScale, cameraOrientation, cameraPosition); + Matrix::Multiply(resultMatrix, cameraMatrix, selfMatrix); + resultMatrix.GetTransformComponents(resultPosition, resultOrientation, resultScale); + + camera.SetProperty(Actor::Property::POSITION, resultPosition); + camera.SetProperty(Actor::Property::ORIENTATION, resultOrientation); + camera.SetProperty(Actor::Property::SCALE, resultScale); } -void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor) +void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels) { if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture) { - mSceneDiffuseTexture = diffuseTexture; - mSceneSpecularTexture = specularTexture; - mSceneIblScaleFactor = scaleFactor; + mSceneDiffuseTexture = diffuseTexture; + mSceneSpecularTexture = specularTexture; + mSceneIblScaleFactor = scaleFactor; + mSceneSpecularMipmapLevels = specularMipmapLevels; // If Model IBL is not set, use SceneView's IBL. if(!mDiffuseTexture || !mSpecularTexture) { @@ -624,161 +748,179 @@ void Model::OnModelLoadComplete() if(!mModelLoadTask->HasSucceeded()) { ResetResourceTasks(); - 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)) + if(ModelCacheManager::Get() && !mModelUrl.empty()) { - 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); + ModelCacheManager::Get().UnreferenceModelCache(mModelUrl); } - AddModelTreeToAABB(AABB, *scene, mModelLoadTask->mResourceChoices, iRoot, nodeParams, Matrix::IDENTITY); - rootCount++; + return; } - if(!resources->mEnvironmentMaps.empty()) + if(!mModelRoot) { - mDefaultDiffuseTexture = resources->mEnvironmentMaps.front().second.mDiffuse; - mDefaultSpecularTexture = resources->mEnvironmentMaps.front().second.mSpecular; + CreateModelRoot(); } + CreateModel(); - if(!mModelLoadTask->mAnimations.empty()) + auto& resources = mModelLoadTask->GetResources(); + auto& scene = mModelLoadTask->GetScene(); + CreateAnimations(scene); + ResetCameraParameters(); + if(!resources.mEnvironmentMaps.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}); - } + mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse; + mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular; } - mRenderableActors.clear(); - CollectRenderableActor(mModelRoot); - UpdateImageBasedLightTexture(); UpdateImageBasedLightScaleFactor(); - - mNaturalSize = AABB.CalculateSize(); - mModelPivot = AABB.CalculatePivot(); - mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize); - Vector3 controlSize = Self().GetProperty(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().GetTexture() : Texture(); + mDiffuseTexture = mIblDiffuseLoadTask->GetLoadedTexture(); + ResetResourceTask(mIblDiffuseLoadTask); mIblDiffuseResourceReady = true; if(mIblDiffuseResourceReady && mIblSpecularResourceReady) { OnIblLoadComplete(); } - mIblDiffuseLoadTask.Reset(); } void Model::OnIblSpecularLoadComplete() { - mSpecularTexture = (mIblSpecularLoadTask->HasSucceeded()) ? mIblSpecularLoadTask->GetEnvironmentMap().GetTexture() : Texture(); + mSpecularTexture = mIblSpecularLoadTask->GetLoadedTexture(); + mSpecularMipmapLevels = mIblSpecularLoadTask->GetMipmapLevels(); + ResetResourceTask(mIblSpecularLoadTask); mIblSpecularResourceReady = true; if(mIblDiffuseResourceReady && mIblSpecularResourceReady) { OnIblLoadComplete(); } - mIblSpecularLoadTask.Reset(); } void Model::OnIblLoadComplete() { UpdateImageBasedLightTexture(); + NotifyResourceReady(); +} + +void Model::OnSizeNotification(Dali::PropertyNotification& source) +{ + ScaleModel(true); +} - 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) +{ + if(!asyncTask) + { + return; + } + Dali::AsyncTaskManager::Get().RemoveTask(asyncTask); + asyncTask.Reset(); +} + +void Model::NotifyResourceReady() { - if(Dali::Adaptor::IsAvailable()) + if(!IsResourceReady()) { - if(mModelLoadTask) + return; + } + Control::SetResourceReady(false); +} + +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, {}, {}, {}}; + + // 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)) { - Dali::AsyncTaskManager::Get().RemoveTask(mModelLoadTask); - mModelLoadTask.Reset(); + 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, resourceChoices, iRoot, nodeParams, Matrix::IDENTITY); + } + + mNaturalSize = AABB.CalculateSize(); + mModelPivot = AABB.CalculatePivot(); + mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize); + Vector3 controlSize = Self().GetProperty(Dali::Actor::Property::SIZE); + if(Dali::EqualsZero(controlSize.x) || Dali::EqualsZero(controlSize.y)) + { + Self().SetProperty(Dali::Actor::Property::SIZE, mNaturalSize); + } + FitModelPosition(); + ScaleModel(false); +} + +void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene) +{ + mAnimations.clear(); + if(!mModelLoadTask->GetAnimations().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); + }; + + for(auto&& animation : mModelLoadTask->GetAnimations()) { - Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask); - mIblSpecularLoadTask.Reset(); + Dali::Animation anim = animation.ReAnimate(getActor); + mAnimations.push_back({animation.GetName(), anim}); } } } +void Model::ResetCameraParameters() +{ + mCameraParameters.clear(); + if(!mModelLoadTask->GetCameras().empty()) + { + // Copy camera parameters. + std::copy(mModelLoadTask->GetCameras().begin(), mModelLoadTask->GetCameras().end(), std::back_inserter(mCameraParameters)); + } +} + } // namespace Internal } // namespace Scene3D } // namespace Dali