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/public-api/controls/model/model.h>
37 #include <dali-scene3d/public-api/loader/animation-definition.h>
38 #include <dali-scene3d/public-api/loader/camera-parameters.h>
39 #include <dali-scene3d/public-api/loader/light-parameters.h>
40 #include <dali-scene3d/public-api/loader/load-result.h>
41 #include <dali-scene3d/public-api/loader/node-definition.h>
42 #include <dali-scene3d/public-api/loader/scene-definition.h>
43 #include <dali-scene3d/public-api/loader/shader-definition-factory.h>
57 return Scene3D::Model::New(std::string());
60 // Setup properties, signals and actions using the type-registry.
61 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::Model, Toolkit::Control, Create);
62 DALI_TYPE_REGISTRATION_END()
64 static constexpr uint32_t OFFSET_FOR_DIFFUSE_CUBE_TEXTURE = 2u;
65 static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u;
67 static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f);
69 static constexpr bool DEFAULT_MODEL_CHILDREN_SENSITIVE = false;
70 static constexpr bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false;
76 pointMin = Vector3(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
77 pointMax = Vector3(std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min());
80 void ConsiderNewPointInVolume(const Vector3& position)
82 pointMin.x = std::min(position.x, pointMin.x);
83 pointMin.y = std::min(position.y, pointMin.y);
84 pointMin.z = std::min(position.z, pointMin.z);
86 pointMax.x = std::max(position.x, pointMax.x);
87 pointMax.y = std::max(position.y, pointMax.y);
88 pointMax.z = std::max(position.z, pointMax.z);
91 Vector3 CalculateSize()
93 return pointMax - pointMin;
96 Vector3 CalculatePivot()
98 Vector3 pivot = pointMin / (pointMin - pointMax);
99 for(uint32_t i = 0; i < 3; ++i)
101 // To avoid divid by zero
102 if(Dali::Equals(pointMin[i], pointMax[i]))
114 void ConfigureBlendShapeShaders(
115 Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector<Dali::Scene3D::Loader::BlendshapeShaderConfigurationRequest>&& requests)
117 std::vector<std::string> errors;
118 auto onError = [&errors](const std::string& msg)
119 { errors.push_back(msg); };
120 if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError))
122 Dali::Scene3D::Loader::ExceptionFlinger flinger(ASSERT_LOCATION);
123 for(auto& msg : errors)
125 flinger << msg << '\n';
130 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)
132 static constexpr uint32_t BOX_POINT_COUNT = 8;
133 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}};
136 const Dali::Scene3D::Loader::NodeDefinition* node = scene.GetNode(iNode);
137 Matrix localMatrix = node->GetLocalSpace();
138 Matrix::Multiply(nodeMatrix, localMatrix, parentMatrix);
141 if(node->GetExtents(nodeParams.mResources, volume[0], volume[1]))
143 for(uint32_t i = 0; i < BOX_POINT_COUNT; ++i)
145 Vector4 position = Vector4(volume[BBIndex[i][0]].x, volume[BBIndex[i][1]].y, volume[BBIndex[i][2]].z, 1.0f);
146 Vector4 objectPosition = nodeMatrix * position;
147 objectPosition /= objectPosition.w;
149 AABB.ConsiderNewPointInVolume(Vector3(objectPosition));
153 if(node->mCustomization)
155 if(!node->mChildren.empty())
157 auto choice = choices.Get(node->mCustomization->mTag);
158 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));
160 AddModelTreeToAABB(AABB, scene, choices, node->mChildren[i], nodeParams, nodeMatrix);
165 for(auto i : node->mChildren)
167 AddModelTreeToAABB(AABB, scene, choices, i, nodeParams, nodeMatrix);
172 } // anonymous namespace
174 Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
175 : Control(ControlBehaviour(DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS)),
177 mResourceDirectoryUrl(resourceDirectoryUrl),
179 mNaturalSize(Vector3::ZERO),
180 mModelPivot(AnchorPoint::CENTER),
181 mSceneIblScaleFactor(1.0f),
182 mIblScaleFactor(1.0f),
183 mModelChildrenSensitive(DEFAULT_MODEL_CHILDREN_SENSITIVE),
184 mModelChildrenFocusable(DEFAULT_MODEL_CHILDREN_FOCUSABLE),
185 mModelResourceReady(false),
186 mIblDiffuseResourceReady(true),
187 mIblSpecularResourceReady(true),
188 mIblDiffuseDirty(false),
189 mIblSpecularDirty(false)
195 if(ModelCacheManager::Get())
197 ModelCacheManager::Get().UnreferenceModelCache(mModelUrl);
200 ResetResourceTasks();
203 Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
205 Model* impl = new Model(modelUrl, resourceDirectoryUrl);
207 Dali::Scene3D::Model handle = Dali::Scene3D::Model(*impl);
209 // Second-phase init of the implementation
210 // This can only be done after the CustomActor connection has been made...
216 const Actor Model::GetModelRoot() const
221 void Model::SetChildrenSensitive(bool enable)
223 if(mModelChildrenSensitive != enable)
225 mModelChildrenSensitive = enable;
228 mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
233 bool Model::GetChildrenSensitive() const
235 return mModelChildrenSensitive;
238 void Model::SetChildrenFocusable(bool enable)
240 if(mModelChildrenFocusable != enable)
242 mModelChildrenFocusable = enable;
245 mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
246 mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
251 bool Model::GetChildrenFocusable() const
253 return mModelChildrenFocusable;
256 void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
258 bool needIblReset = false;
259 bool isOnScene = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
260 if(mDiffuseIblUrl != diffuseUrl)
262 mDiffuseIblUrl = diffuseUrl;
263 if(mDiffuseIblUrl.empty())
269 mIblDiffuseDirty = true;
270 mIblDiffuseResourceReady = false;
274 if(mSpecularIblUrl != specularUrl)
276 mSpecularIblUrl = specularUrl;
277 if(mSpecularIblUrl.empty())
283 mIblSpecularDirty = true;
284 mIblSpecularResourceReady = false;
288 // If one or both of diffuse url and specular url are empty,
289 // we don't need to request to load texture.
292 ResetResourceTask(mIblDiffuseLoadTask);
293 ResetResourceTask(mIblSpecularLoadTask);
295 mIblDiffuseDirty = false;
296 mIblSpecularDirty = false;
297 mIblDiffuseResourceReady = true;
298 mIblSpecularResourceReady = true;
300 mDiffuseTexture.Reset();
301 mSpecularTexture.Reset();
302 UpdateImageBasedLightTexture();
306 if(isOnScene && mIblDiffuseDirty)
308 ResetResourceTask(mIblDiffuseLoadTask);
309 mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblDiffuseLoadComplete));
310 Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
311 mIblDiffuseDirty = false;
314 if(isOnScene && mIblSpecularDirty)
316 ResetResourceTask(mIblSpecularLoadTask);
317 mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblSpecularLoadComplete));
318 Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
319 mIblSpecularDirty = false;
323 if(!Dali::Equals(mIblScaleFactor, scaleFactor))
325 mIblScaleFactor = scaleFactor;
326 UpdateImageBasedLightScaleFactor();
329 // If diffuse and specular textures are already loaded, emits resource ready signal here.
330 NotifyResourceReady();
333 void Model::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
335 // If input texture is wrong, Model is rendered with SceneView's IBL.
336 if(mDiffuseTexture != diffuseTexture || mSpecularTexture != specularTexture)
338 mDiffuseTexture = diffuseTexture;
339 mSpecularTexture = specularTexture;
340 mIblScaleFactor = scaleFactor;
341 UpdateImageBasedLightTexture();
345 void Model::SetImageBasedLightScaleFactor(float scaleFactor)
347 mIblScaleFactor = scaleFactor;
348 if(mDiffuseTexture && mSpecularTexture)
350 UpdateImageBasedLightScaleFactor();
354 float Model::GetImageBasedLightScaleFactor() const
356 return mIblScaleFactor;
359 uint32_t Model::GetAnimationCount() const
361 return mAnimations.size();
364 Dali::Animation Model::GetAnimation(uint32_t index) const
366 Dali::Animation animation;
367 if(mAnimations.size() > index)
369 animation = mAnimations[index].second;
374 Dali::Animation Model::GetAnimation(const std::string& name) const
376 Dali::Animation animation;
379 for(auto&& animationData : mAnimations)
381 if(animationData.first == name)
383 animation = animationData.second;
391 uint32_t Model::GetCameraCount() const
393 return mCameraParameters.size();
396 Dali::CameraActor Model::GenerateCamera(uint32_t index) const
398 Dali::CameraActor camera;
399 if(mCameraParameters.size() > index)
401 camera = Dali::CameraActor::New3DCamera();
402 if(!mCameraParameters[index].ConfigureCamera(camera, false))
404 DALI_LOG_ERROR("Fail to generate %u's camera actor : Some property was not defined. Please check model file.\n", index);
409 ApplyCameraTransform(camera);
414 bool Model::ApplyCamera(uint32_t index, Dali::CameraActor camera) const
416 if(camera && mCameraParameters.size() > index)
418 if(!mCameraParameters[index].ConfigureCamera(camera, false))
420 DALI_LOG_ERROR("Fail to apply %u's camera actor : Some property was not defined. Please check model file.\n", index);
424 ApplyCameraTransform(camera);
430 ///////////////////////////////////////////////////////////
435 void Model::OnInitialize()
437 // Make ParentOrigin as Center.
438 Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
441 void Model::OnSceneConnection(int depth)
443 if(!mModelLoadTask && !mModelRoot)
445 if(ModelCacheManager::Get())
447 ModelCacheManager::Get().ReferenceModelCache(mModelUrl);
449 mModelLoadTask = new ModelLoadTask(mModelUrl, mResourceDirectoryUrl, MakeCallback(this, &Model::OnModelLoadComplete));
450 Dali::AsyncTaskManager::Get().AddTask(mModelLoadTask);
452 // If diffuse and specular url is not valid, IBL does not need to be loaded.
453 if(!mDiffuseIblUrl.empty() && !mSpecularIblUrl.empty())
455 SetImageBasedLightSource(mDiffuseIblUrl, mSpecularIblUrl, mIblScaleFactor);
458 Actor parent = Self().GetParent();
461 Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
464 GetImpl(sceneView).RegisterSceneItem(this);
465 mParentSceneView = sceneView;
468 parent = parent.GetParent();
471 Control::OnSceneConnection(depth);
474 void Model::OnSceneDisconnection()
476 Scene3D::SceneView sceneView = mParentSceneView.GetHandle();
479 GetImpl(sceneView).UnregisterSceneItem(this);
480 mParentSceneView.Reset();
482 Control::OnSceneDisconnection();
485 Vector3 Model::GetNaturalSize()
489 DALI_LOG_ERROR("Model is still not loaded.\n");
490 return Vector3::ZERO;
496 float Model::GetHeightForWidth(float width)
499 padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
500 return Control::GetHeightForWidth(width) + padding.top + padding.bottom;
503 float Model::GetWidthForHeight(float height)
506 padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
507 return Control::GetWidthForHeight(height) + padding.start + padding.end;
510 void Model::OnRelayout(const Vector2& size, RelayoutContainer& container)
512 Control::OnRelayout(size, container);
516 bool Model::IsResourceReady() const
518 return mModelResourceReady && mIblDiffuseResourceReady && mIblSpecularResourceReady;
521 void Model::ScaleModel()
529 Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
530 if(size.x > 0.0f && size.y > 0.0f)
533 scale = std::min(size.x / mNaturalSize.x, scale);
534 scale = std::min(size.y / mNaturalSize.y, scale);
536 // Models in glTF and dli are defined as right hand coordinate system.
537 // DALi uses left hand coordinate system. Scaling negative is for change winding order.
538 mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION * scale);
541 void Model::FitModelPosition()
547 // Loaded model pivot is not the model center.
548 mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
549 mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
552 void Model::CollectRenderableActor(Actor actor)
554 uint32_t rendererCount = actor.GetRendererCount();
557 mRenderableActors.push_back(actor);
560 uint32_t childrenCount = actor.GetChildCount();
561 for(uint32_t i = 0; i < childrenCount; ++i)
563 CollectRenderableActor(actor.GetChildAt(i));
567 void Model::UpdateImageBasedLightTexture()
569 Dali::Texture currentDiffuseTexture = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
570 Dali::Texture currentSpecularTexture = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
571 float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
573 if(!currentDiffuseTexture || !currentSpecularTexture)
575 currentDiffuseTexture = mDefaultDiffuseTexture;
576 currentSpecularTexture = mDefaultSpecularTexture;
577 currentIblScaleFactor = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
580 for(auto&& actor : mRenderableActors)
582 Actor renderableActor = actor.GetHandle();
588 uint32_t rendererCount = renderableActor.GetRendererCount();
589 for(uint32_t i = 0; i < rendererCount; ++i)
591 Dali::Renderer renderer = renderableActor.GetRendererAt(i);
596 Dali::TextureSet textures = renderer.GetTextures();
601 uint32_t textureCount = textures.GetTextureCount();
602 // EnvMap requires at least 2 texture, diffuse and specular
603 if(textureCount > 2u &&
604 (textures.GetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE) != currentDiffuseTexture ||
605 textures.GetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE) != currentSpecularTexture))
607 Dali::TextureSet newTextures = Dali::TextureSet::New();
609 for(uint32_t index = 0u; index < textureCount; ++index)
611 Dali::Texture texture = textures.GetTexture(index);
612 if(index == textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE)
614 texture = currentDiffuseTexture;
616 else if(index == textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE)
618 texture = currentSpecularTexture;
621 newTextures.SetTexture(index, texture);
622 newTextures.SetSampler(index, textures.GetSampler(index));
625 renderer.SetTextures(newTextures);
628 renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
632 void Model::UpdateImageBasedLightScaleFactor()
634 if((!mDiffuseTexture || !mSpecularTexture) &&
635 (!mSceneDiffuseTexture || !mSceneSpecularTexture))
640 float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
641 for(auto&& actor : mRenderableActors)
643 Actor renderableActor = actor.GetHandle();
646 renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
651 void Model::ApplyCameraTransform(Dali::CameraActor camera) const
653 Vector3 selfPosition = Self().GetProperty<Vector3>(Actor::Property::POSITION);
654 Quaternion selfOrientation = Self().GetProperty<Quaternion>(Actor::Property::ORIENTATION);
655 Vector3 selfScale = Self().GetProperty<Vector3>(Actor::Property::SCALE);
657 Vector3 cameraPosition = camera.GetProperty<Vector3>(Actor::Property::POSITION);
658 Quaternion cameraOrientation = camera.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
659 Vector3 cameraScale = camera.GetProperty<Vector3>(Actor::Property::SCALE);
661 // Models in glTF and dli are defined as right hand coordinate system.
662 // DALi uses left hand coordinate system. Scaling negative is for change winding order.
663 if(!Dali::Equals(Y_DIRECTION.Dot(Vector3::YAXIS), 1.0f))
665 // Reflect by XZ plane
666 cameraPosition.y = -cameraPosition.y;
667 Quaternion yDirectionQuaternion;
668 yDirectionQuaternion.mVector = Vector3::YAXIS;
669 // Reflect orientation
670 cameraOrientation = yDirectionQuaternion * cameraOrientation * yDirectionQuaternion;
673 Vector3 resultPosition;
674 Quaternion resultOrientation;
677 Matrix selfMatrix(false);
678 Matrix cameraMatrix(false);
679 Matrix resultMatrix(false);
680 selfMatrix.SetTransformComponents(selfScale, selfOrientation, selfPosition);
681 cameraMatrix.SetTransformComponents(cameraScale, cameraOrientation, cameraPosition);
682 Matrix::Multiply(resultMatrix, cameraMatrix, selfMatrix);
683 resultMatrix.GetTransformComponents(resultPosition, resultOrientation, resultScale);
685 camera.SetProperty(Actor::Property::POSITION, resultPosition);
686 camera.SetProperty(Actor::Property::ORIENTATION, resultOrientation);
687 camera.SetProperty(Actor::Property::SCALE, resultScale);
690 void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
692 if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
694 mSceneDiffuseTexture = diffuseTexture;
695 mSceneSpecularTexture = specularTexture;
696 mSceneIblScaleFactor = scaleFactor;
697 // If Model IBL is not set, use SceneView's IBL.
698 if(!mDiffuseTexture || !mSpecularTexture)
700 UpdateImageBasedLightTexture();
705 void Model::NotifyImageBasedLightScaleFactor(float scaleFactor)
707 mSceneIblScaleFactor = scaleFactor;
708 if(mSceneDiffuseTexture && mSceneSpecularTexture)
710 UpdateImageBasedLightScaleFactor();
714 void Model::OnModelLoadComplete()
716 if(!mModelLoadTask->HasSucceeded())
718 ResetResourceTasks();
720 if(ModelCacheManager::Get())
722 ModelCacheManager::Get().UnreferenceModelCache(mModelUrl);
729 mRenderableActors.clear();
730 CollectRenderableActor(mModelRoot);
732 auto& resources = mModelLoadTask->GetResources();
733 auto& scene = mModelLoadTask->GetScene();
734 CreateAnimations(scene);
735 ResetCameraParameters();
736 if(!resources.mEnvironmentMaps.empty())
738 mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse;
739 mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular;
742 UpdateImageBasedLightTexture();
743 UpdateImageBasedLightScaleFactor();
745 mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
746 mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
747 mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
749 Self().Add(mModelRoot);
750 Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
752 mModelResourceReady = true;
753 NotifyResourceReady();
754 ResetResourceTask(mModelLoadTask);
757 void Model::OnIblDiffuseLoadComplete()
759 mDiffuseTexture = mIblDiffuseLoadTask->GetLoadedTexture();
760 ResetResourceTask(mIblDiffuseLoadTask);
761 mIblDiffuseResourceReady = true;
762 if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
768 void Model::OnIblSpecularLoadComplete()
770 mSpecularTexture = mIblSpecularLoadTask->GetLoadedTexture();
771 ResetResourceTask(mIblSpecularLoadTask);
772 mIblSpecularResourceReady = true;
773 if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
779 void Model::OnIblLoadComplete()
781 UpdateImageBasedLightTexture();
782 NotifyResourceReady();
785 void Model::ResetResourceTasks()
787 if(!Dali::Adaptor::IsAvailable())
791 ResetResourceTask(mModelLoadTask);
792 ResetResourceTask(mIblDiffuseLoadTask);
793 ResetResourceTask(mIblSpecularLoadTask);
796 void Model::ResetResourceTask(IntrusivePtr<AsyncTask> asyncTask)
802 Dali::AsyncTaskManager::Get().RemoveTask(asyncTask);
806 void Model::NotifyResourceReady()
808 if(!IsResourceReady())
812 Control::SetResourceReady(false);
815 void Model::CreateModel()
817 mModelRoot = Actor::New();
818 mModelRoot.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
821 auto& resources = mModelLoadTask->GetResources();
822 auto& scene = mModelLoadTask->GetScene();
823 auto& resourceChoices = mModelLoadTask->GetResourceChoices();
824 Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
825 Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}};
827 // Generate Dali handles from resource bundle. Note that we generate all scene's resouce immediatly.
828 resources.GenerateResources();
829 for(auto iRoot : scene.GetRoots())
831 if(auto actor = scene.CreateNodes(iRoot, resourceChoices, nodeParams))
833 scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
834 scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
835 ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
837 scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
839 mModelRoot.Add(actor);
842 AddModelTreeToAABB(AABB, scene, resourceChoices, iRoot, nodeParams, Matrix::IDENTITY);
845 mNaturalSize = AABB.CalculateSize();
846 mModelPivot = AABB.CalculatePivot();
847 mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
848 Vector3 controlSize = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
849 if(Dali::EqualsZero(controlSize.x) || Dali::EqualsZero(controlSize.y))
851 Self().SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
857 void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene)
860 if(!mModelLoadTask->GetAnimations().empty())
862 auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property)
864 if(property.mNodeIndex == Scene3D::Loader::INVALID_INDEX)
866 return mModelRoot.FindChildByName(property.mNodeName);
868 auto* node = scene.GetNode(property.mNodeIndex);
871 return Dali::Actor();
873 return mModelRoot.FindChildById(node->mNodeId);
876 for(auto&& animation : mModelLoadTask->GetAnimations())
878 Dali::Animation anim = animation.ReAnimate(getActor);
879 mAnimations.push_back({animation.mName, anim});
884 void Model::ResetCameraParameters()
886 mCameraParameters.clear();
887 if(!mModelLoadTask->GetCameras().empty())
889 // Copy camera parameters.
890 std::copy(mModelLoadTask->GetCameras().begin(), mModelLoadTask->GetCameras().end(), std::back_inserter(mCameraParameters));
894 } // namespace Internal
895 } // namespace Scene3D