2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-scene3d/internal/controls/model/model-impl.h>
22 #include <dali-toolkit/dali-toolkit.h>
23 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
24 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/integration-api/adaptor-framework/adaptor.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/public-api/math/math-utils.h>
29 #include <dali/public-api/object/type-registry-helper.h>
30 #include <dali/public-api/object/type-registry.h>
34 #include <dali-scene3d/internal/common/model-cache-manager.h>
35 #include <dali-scene3d/internal/controls/scene-view/scene-view-impl.h>
36 #include <dali-scene3d/internal/model-components/model-node-impl.h>
37 #include <dali-scene3d/public-api/controls/model/model.h>
38 #include <dali-scene3d/public-api/loader/animation-definition.h>
39 #include <dali-scene3d/public-api/loader/camera-parameters.h>
40 #include <dali-scene3d/public-api/loader/light-parameters.h>
41 #include <dali-scene3d/public-api/loader/load-result.h>
42 #include <dali-scene3d/public-api/loader/node-definition.h>
43 #include <dali-scene3d/public-api/loader/scene-definition.h>
44 #include <dali-scene3d/public-api/loader/shader-definition-factory.h>
57 * Creates control through type registry
61 return Scene3D::Model::New(std::string());
64 // Setup properties, signals and actions using the type-registry.
65 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::Model, Toolkit::Control, Create);
66 DALI_TYPE_REGISTRATION_END()
68 static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f);
70 static constexpr bool DEFAULT_MODEL_CHILDREN_SENSITIVE = false;
71 static constexpr bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false;
77 pointMin = Vector3(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
78 pointMax = Vector3(std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min());
81 void ConsiderNewPointInVolume(const Vector3& position)
83 pointMin.x = std::min(position.x, pointMin.x);
84 pointMin.y = std::min(position.y, pointMin.y);
85 pointMin.z = std::min(position.z, pointMin.z);
87 pointMax.x = std::max(position.x, pointMax.x);
88 pointMax.y = std::max(position.y, pointMax.y);
89 pointMax.z = std::max(position.z, pointMax.z);
92 Vector3 CalculateSize()
94 return pointMax - pointMin;
97 Vector3 CalculatePivot()
99 Vector3 pivot = pointMin / (pointMin - pointMax);
100 for(uint32_t i = 0; i < 3; ++i)
102 // To avoid divid by zero
103 if(Dali::Equals(pointMin[i], pointMax[i]))
115 void ConfigureBlendShapeShaders(
116 Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector<Dali::Scene3D::Loader::BlendshapeShaderConfigurationRequest>&& requests)
118 std::vector<std::string> errors;
119 auto onError = [&errors](const std::string& msg)
120 { errors.push_back(msg); };
121 if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError))
123 Dali::Scene3D::Loader::ExceptionFlinger flinger(ASSERT_LOCATION);
124 for(auto& msg : errors)
126 flinger << msg << '\n';
131 void AddModelTreeToAABB(BoundingVolume& AABB, const Dali::Scene3D::Loader::SceneDefinition& scene, const Dali::Scene3D::Loader::Customization::Choices& choices, Dali::Scene3D::Loader::Index iNode, Dali::Scene3D::Loader::NodeDefinition::CreateParams& nodeParams, Matrix parentMatrix)
133 static constexpr uint32_t BOX_POINT_COUNT = 8;
134 static uint32_t BBIndex[BOX_POINT_COUNT][3] = {{0, 0, 0}, {0, 1, 0}, {1, 0, 0}, {1, 1, 0}, {0, 0, 1}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1}};
137 const Dali::Scene3D::Loader::NodeDefinition* node = scene.GetNode(iNode);
138 Matrix localMatrix = node->GetLocalSpace();
139 Matrix::Multiply(nodeMatrix, localMatrix, parentMatrix);
142 if(node->GetExtents(nodeParams.mResources, volume[0], volume[1]))
144 for(uint32_t i = 0; i < BOX_POINT_COUNT; ++i)
146 Vector4 position = Vector4(volume[BBIndex[i][0]].x, volume[BBIndex[i][1]].y, volume[BBIndex[i][2]].z, 1.0f);
147 Vector4 objectPosition = nodeMatrix * position;
148 objectPosition /= objectPosition.w;
150 AABB.ConsiderNewPointInVolume(Vector3(objectPosition));
154 if(node->mCustomization)
156 if(!node->mChildren.empty())
158 auto choice = choices.Get(node->mCustomization->mTag);
159 Dali::Scene3D::Loader::Index i = std::min(choice != Dali::Scene3D::Loader::Customization::NONE ? choice : 0, static_cast<Dali::Scene3D::Loader::Index>(node->mChildren.size() - 1));
161 AddModelTreeToAABB(AABB, scene, choices, node->mChildren[i], nodeParams, nodeMatrix);
166 for(auto i : node->mChildren)
168 AddModelTreeToAABB(AABB, scene, choices, i, nodeParams, nodeMatrix);
173 } // anonymous namespace
175 Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
176 : Control(ControlBehaviour(DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS)),
178 mResourceDirectoryUrl(resourceDirectoryUrl),
180 mNaturalSize(Vector3::ZERO),
181 mModelPivot(AnchorPoint::CENTER),
182 mSceneIblScaleFactor(1.0f),
183 mIblScaleFactor(1.0f),
184 mSceneSpecularMipmapLevels(1u),
185 mSpecularMipmapLevels(1u),
186 mModelChildrenSensitive(DEFAULT_MODEL_CHILDREN_SENSITIVE),
187 mModelChildrenFocusable(DEFAULT_MODEL_CHILDREN_FOCUSABLE),
188 mModelResourceReady(false),
189 mIblDiffuseResourceReady(true),
190 mIblSpecularResourceReady(true),
191 mIblDiffuseDirty(false),
192 mIblSpecularDirty(false)
198 if(ModelCacheManager::Get() && !mModelUrl.empty())
200 ModelCacheManager::Get().UnreferenceModelCache(mModelUrl);
203 ResetResourceTasks();
206 Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
208 Model* impl = new Model(modelUrl, resourceDirectoryUrl);
210 Dali::Scene3D::Model handle = Dali::Scene3D::Model(*impl);
212 // Second-phase init of the implementation
213 // This can only be done after the CustomActor connection has been made...
219 const Scene3D::ModelNode Model::GetModelRoot() const
224 void Model::AddModelNode(Scene3D::ModelNode modelNode)
231 mModelRoot.Add(modelNode);
232 if(mModelUrl.empty())
234 mModelResourceReady = true;
237 if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
239 UpdateImageBasedLightTexture();
240 UpdateImageBasedLightScaleFactor();
243 if(Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
245 NotifyResourceReady();
249 void Model::RemoveModelNode(Scene3D::ModelNode modelNode)
253 mModelRoot.Remove(modelNode);
257 void Model::SetChildrenSensitive(bool enable)
259 if(mModelChildrenSensitive != enable)
261 mModelChildrenSensitive = enable;
264 mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
269 bool Model::GetChildrenSensitive() const
271 return mModelChildrenSensitive;
274 void Model::SetChildrenFocusable(bool enable)
276 if(mModelChildrenFocusable != enable)
278 mModelChildrenFocusable = enable;
281 mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
282 mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
287 bool Model::GetChildrenFocusable() const
289 return mModelChildrenFocusable;
292 void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
294 bool needIblReset = false;
295 bool isOnScene = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
296 if(mDiffuseIblUrl != diffuseUrl)
298 mDiffuseIblUrl = diffuseUrl;
299 if(mDiffuseIblUrl.empty())
305 mIblDiffuseDirty = true;
306 mIblDiffuseResourceReady = false;
310 if(mSpecularIblUrl != specularUrl)
312 mSpecularIblUrl = specularUrl;
313 if(mSpecularIblUrl.empty())
319 mIblSpecularDirty = true;
320 mIblSpecularResourceReady = false;
324 // If one or both of diffuse url and specular url are empty,
325 // we don't need to request to load texture.
328 ResetResourceTask(mIblDiffuseLoadTask);
329 ResetResourceTask(mIblSpecularLoadTask);
331 mIblDiffuseDirty = false;
332 mIblSpecularDirty = false;
333 mIblDiffuseResourceReady = true;
334 mIblSpecularResourceReady = true;
336 mDiffuseTexture.Reset();
337 mSpecularTexture.Reset();
338 UpdateImageBasedLightTexture();
342 if(isOnScene && mIblDiffuseDirty)
344 ResetResourceTask(mIblDiffuseLoadTask);
345 mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblDiffuseLoadComplete));
346 Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
347 mIblDiffuseDirty = false;
350 if(isOnScene && mIblSpecularDirty)
352 ResetResourceTask(mIblSpecularLoadTask);
353 mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblSpecularLoadComplete));
354 Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
355 mIblSpecularDirty = false;
359 if(!Dali::Equals(mIblScaleFactor, scaleFactor))
361 mIblScaleFactor = scaleFactor;
362 UpdateImageBasedLightScaleFactor();
365 // If diffuse and specular textures are already loaded, emits resource ready signal here.
366 NotifyResourceReady();
369 void Model::SetImageBasedLightScaleFactor(float scaleFactor)
371 mIblScaleFactor = scaleFactor;
372 if(mDiffuseTexture && mSpecularTexture)
374 UpdateImageBasedLightScaleFactor();
378 float Model::GetImageBasedLightScaleFactor() const
380 return mIblScaleFactor;
383 uint32_t Model::GetAnimationCount() const
385 return mAnimations.size();
388 Dali::Animation Model::GetAnimation(uint32_t index) const
390 Dali::Animation animation;
391 if(mAnimations.size() > index)
393 animation = mAnimations[index].second;
398 Dali::Animation Model::GetAnimation(const std::string& name) const
400 Dali::Animation animation;
403 for(auto&& animationData : mAnimations)
405 if(animationData.first == name)
407 animation = animationData.second;
415 uint32_t Model::GetCameraCount() const
417 return mCameraParameters.size();
420 Dali::CameraActor Model::GenerateCamera(uint32_t index) const
422 Dali::CameraActor camera;
423 if(mCameraParameters.size() > index)
425 camera = Dali::CameraActor::New3DCamera();
426 if(!mCameraParameters[index].ConfigureCamera(camera, false))
428 DALI_LOG_ERROR("Fail to generate %u's camera actor : Some property was not defined. Please check model file.\n", index);
433 ApplyCameraTransform(camera);
438 bool Model::ApplyCamera(uint32_t index, Dali::CameraActor camera) const
440 if(camera && mCameraParameters.size() > index)
442 if(!mCameraParameters[index].ConfigureCamera(camera, false))
444 DALI_LOG_ERROR("Fail to apply %u's camera actor : Some property was not defined. Please check model file.\n", index);
448 ApplyCameraTransform(camera);
454 Scene3D::ModelNode Model::FindChildModelNodeByName(std::string_view nodeName)
456 Actor childActor = Self().FindChildByName(nodeName);
457 return Scene3D::ModelNode::DownCast(childActor);
460 ///////////////////////////////////////////////////////////
465 void Model::OnInitialize()
467 // Make ParentOrigin as Center.
468 Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
471 void Model::OnSceneConnection(int depth)
473 if(!mModelLoadTask && !mModelResourceReady && !mModelUrl.empty())
475 // Request model load only if we setup url.
476 if(ModelCacheManager::Get())
478 ModelCacheManager::Get().ReferenceModelCache(mModelUrl);
480 mModelLoadTask = new ModelLoadTask(mModelUrl, mResourceDirectoryUrl, MakeCallback(this, &Model::OnModelLoadComplete));
481 Dali::AsyncTaskManager::Get().AddTask(mModelLoadTask);
484 // If diffuse and specular url is not valid, IBL does not need to be loaded.
485 if(!mDiffuseIblUrl.empty() && !mSpecularIblUrl.empty())
487 SetImageBasedLightSource(mDiffuseIblUrl, mSpecularIblUrl, mIblScaleFactor);
490 Actor parent = Self().GetParent();
493 Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
496 GetImpl(sceneView).RegisterSceneItem(this);
497 mParentSceneView = sceneView;
500 parent = parent.GetParent();
503 NotifyResourceReady();
504 Control::OnSceneConnection(depth);
507 void Model::OnSceneDisconnection()
509 Scene3D::SceneView sceneView = mParentSceneView.GetHandle();
512 GetImpl(sceneView).UnregisterSceneItem(this);
513 mParentSceneView.Reset();
515 Control::OnSceneDisconnection();
518 Vector3 Model::GetNaturalSize()
522 DALI_LOG_ERROR("Model is still not loaded.\n");
523 return Vector3::ZERO;
529 float Model::GetHeightForWidth(float width)
532 padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
533 return Control::GetHeightForWidth(width) + padding.top + padding.bottom;
536 float Model::GetWidthForHeight(float height)
539 padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
540 return Control::GetWidthForHeight(height) + padding.start + padding.end;
543 void Model::OnRelayout(const Vector2& size, RelayoutContainer& container)
545 Control::OnRelayout(size, container);
549 bool Model::IsResourceReady() const
551 return mModelResourceReady && mIblDiffuseResourceReady && mIblSpecularResourceReady;
554 void Model::CreateModelRoot()
556 mModelRoot = Scene3D::ModelNode::New();
557 mModelRoot.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
558 mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION);
559 mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
560 mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
561 mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
562 Self().Add(mModelRoot);
565 void Model::ScaleModel()
573 Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
574 if(size.x > 0.0f && size.y > 0.0f)
577 scale = std::min(size.x / mNaturalSize.x, scale);
578 scale = std::min(size.y / mNaturalSize.y, scale);
580 // Models in glTF and dli are defined as right hand coordinate system.
581 // DALi uses left hand coordinate system. Scaling negative is for change winding order.
582 mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION * scale);
585 void Model::FitModelPosition()
591 // Loaded model pivot is not the model center.
592 mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
593 mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
596 void Model::UpdateImageBasedLightTextureRecursively(Scene3D::ModelNode node, Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
603 GetImplementation(node).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
604 uint32_t childrenCount = node.GetChildCount();
605 for(uint32_t i = 0; i < childrenCount; ++i)
607 Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
612 UpdateImageBasedLightTextureRecursively(childNode, diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
616 void Model::UpdateImageBasedLightScaleFactorRecursively(Scene3D::ModelNode node, float iblScaleFactor)
623 node.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), iblScaleFactor);
624 GetImplementation(node).SetImageBasedLightScaleFactor(iblScaleFactor);
626 uint32_t childrenCount = node.GetChildCount();
627 for(uint32_t i = 0; i < childrenCount; ++i)
629 Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
634 UpdateImageBasedLightScaleFactorRecursively(childNode, iblScaleFactor);
638 void Model::UpdateImageBasedLightTexture()
640 Dali::Texture currentDiffuseTexture = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
641 Dali::Texture currentSpecularTexture = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
642 float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
643 uint32_t currentIblSpecularMipmapLevels = (mDiffuseTexture && mSpecularTexture) ? mSpecularMipmapLevels : mSceneSpecularMipmapLevels;
645 if(!currentDiffuseTexture || !currentSpecularTexture)
647 currentDiffuseTexture = mDefaultDiffuseTexture;
648 currentSpecularTexture = mDefaultSpecularTexture;
649 currentIblScaleFactor = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
650 currentIblSpecularMipmapLevels = 1u;
653 UpdateImageBasedLightTextureRecursively(mModelRoot, currentDiffuseTexture, currentSpecularTexture, currentIblScaleFactor, currentIblSpecularMipmapLevels);
656 void Model::UpdateImageBasedLightScaleFactor()
658 if((!mDiffuseTexture || !mSpecularTexture) &&
659 (!mSceneDiffuseTexture || !mSceneSpecularTexture))
664 float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
665 UpdateImageBasedLightScaleFactorRecursively(mModelRoot, currentIblScaleFactor);
668 void Model::ApplyCameraTransform(Dali::CameraActor camera) const
670 Vector3 selfPosition = Self().GetProperty<Vector3>(Actor::Property::POSITION);
671 Quaternion selfOrientation = Self().GetProperty<Quaternion>(Actor::Property::ORIENTATION);
672 Vector3 selfScale = Self().GetProperty<Vector3>(Actor::Property::SCALE);
674 Vector3 cameraPosition = camera.GetProperty<Vector3>(Actor::Property::POSITION);
675 Quaternion cameraOrientation = camera.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
676 Vector3 cameraScale = camera.GetProperty<Vector3>(Actor::Property::SCALE);
678 // Models in glTF and dli are defined as right hand coordinate system.
679 // DALi uses left hand coordinate system. Scaling negative is for change winding order.
680 if(!Dali::Equals(Y_DIRECTION.Dot(Vector3::YAXIS), 1.0f))
682 // Reflect by XZ plane
683 cameraPosition.y = -cameraPosition.y;
684 Quaternion yDirectionQuaternion;
685 yDirectionQuaternion.mVector = Vector3::YAXIS;
686 // Reflect orientation
687 cameraOrientation = yDirectionQuaternion * cameraOrientation * yDirectionQuaternion;
690 Vector3 resultPosition;
691 Quaternion resultOrientation;
694 Matrix selfMatrix(false);
695 Matrix cameraMatrix(false);
696 Matrix resultMatrix(false);
697 selfMatrix.SetTransformComponents(selfScale, selfOrientation, selfPosition);
698 cameraMatrix.SetTransformComponents(cameraScale, cameraOrientation, cameraPosition);
699 Matrix::Multiply(resultMatrix, cameraMatrix, selfMatrix);
700 resultMatrix.GetTransformComponents(resultPosition, resultOrientation, resultScale);
702 camera.SetProperty(Actor::Property::POSITION, resultPosition);
703 camera.SetProperty(Actor::Property::ORIENTATION, resultOrientation);
704 camera.SetProperty(Actor::Property::SCALE, resultScale);
707 void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels)
709 if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
711 mSceneDiffuseTexture = diffuseTexture;
712 mSceneSpecularTexture = specularTexture;
713 mSceneIblScaleFactor = scaleFactor;
714 mSceneSpecularMipmapLevels = specularMipmapLevels;
715 // If Model IBL is not set, use SceneView's IBL.
716 if(!mDiffuseTexture || !mSpecularTexture)
718 UpdateImageBasedLightTexture();
723 void Model::NotifyImageBasedLightScaleFactor(float scaleFactor)
725 mSceneIblScaleFactor = scaleFactor;
726 if(mSceneDiffuseTexture && mSceneSpecularTexture)
728 UpdateImageBasedLightScaleFactor();
732 void Model::OnModelLoadComplete()
734 if(!mModelLoadTask->HasSucceeded())
736 ResetResourceTasks();
738 if(ModelCacheManager::Get() && !mModelUrl.empty())
740 ModelCacheManager::Get().UnreferenceModelCache(mModelUrl);
752 auto& resources = mModelLoadTask->GetResources();
753 auto& scene = mModelLoadTask->GetScene();
754 CreateAnimations(scene);
755 ResetCameraParameters();
756 if(!resources.mEnvironmentMaps.empty())
758 mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse;
759 mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular;
762 UpdateImageBasedLightTexture();
763 UpdateImageBasedLightScaleFactor();
764 Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
766 mModelResourceReady = true;
767 NotifyResourceReady();
768 ResetResourceTask(mModelLoadTask);
771 void Model::OnIblDiffuseLoadComplete()
773 mDiffuseTexture = mIblDiffuseLoadTask->GetLoadedTexture();
774 ResetResourceTask(mIblDiffuseLoadTask);
775 mIblDiffuseResourceReady = true;
776 if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
782 void Model::OnIblSpecularLoadComplete()
784 mSpecularTexture = mIblSpecularLoadTask->GetLoadedTexture();
785 mSpecularMipmapLevels = mIblSpecularLoadTask->GetMipmapLevels();
786 ResetResourceTask(mIblSpecularLoadTask);
787 mIblSpecularResourceReady = true;
788 if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
794 void Model::OnIblLoadComplete()
796 UpdateImageBasedLightTexture();
797 NotifyResourceReady();
800 void Model::ResetResourceTasks()
802 if(!Dali::Adaptor::IsAvailable())
806 ResetResourceTask(mModelLoadTask);
807 ResetResourceTask(mIblDiffuseLoadTask);
808 ResetResourceTask(mIblSpecularLoadTask);
811 void Model::ResetResourceTask(IntrusivePtr<AsyncTask> asyncTask)
817 Dali::AsyncTaskManager::Get().RemoveTask(asyncTask);
821 void Model::NotifyResourceReady()
823 if(!IsResourceReady())
827 Control::SetResourceReady(false);
830 void Model::CreateModel()
833 auto& resources = mModelLoadTask->GetResources();
834 auto& scene = mModelLoadTask->GetScene();
835 auto& resourceChoices = mModelLoadTask->GetResourceChoices();
836 Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
837 Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}};
839 // Generate Dali handles from resource bundle. Note that we generate all scene's resouce immediatly.
840 resources.GenerateResources();
841 for(auto iRoot : scene.GetRoots())
843 if(auto actor = scene.CreateNodes(iRoot, resourceChoices, nodeParams))
845 scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
846 ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
848 scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
850 mModelRoot.Add(actor);
853 AddModelTreeToAABB(AABB, scene, resourceChoices, iRoot, nodeParams, Matrix::IDENTITY);
856 mNaturalSize = AABB.CalculateSize();
857 mModelPivot = AABB.CalculatePivot();
858 mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
859 Vector3 controlSize = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
860 if(Dali::EqualsZero(controlSize.x) || Dali::EqualsZero(controlSize.y))
862 Self().SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
868 void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene)
871 if(!mModelLoadTask->GetAnimations().empty())
873 auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property)
875 if(property.mNodeIndex == Scene3D::Loader::INVALID_INDEX)
877 return mModelRoot.FindChildByName(property.mNodeName);
879 auto* node = scene.GetNode(property.mNodeIndex);
882 return Dali::Actor();
884 return mModelRoot.FindChildById(node->mNodeId);
887 for(auto&& animation : mModelLoadTask->GetAnimations())
889 Dali::Animation anim = animation.ReAnimate(getActor);
890 mAnimations.push_back({animation.GetName(), anim});
895 void Model::ResetCameraParameters()
897 mCameraParameters.clear();
898 if(!mModelLoadTask->GetCameras().empty())
900 // Copy camera parameters.
901 std::copy(mModelLoadTask->GetCameras().begin(), mModelLoadTask->GetCameras().end(), std::back_inserter(mCameraParameters));
905 } // namespace Internal
906 } // namespace Scene3D