[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / controls / model / model-impl.h
1 #ifndef DALI_SCENE3D_INTERNAL_MODEL_H
2 #define DALI_SCENE3D_INTERNAL_MODEL_H
3
4 /*
5  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali/devel-api/common/map-wrapper.h>
24 #include <dali/public-api/actors/camera-actor.h>
25 #include <dali/public-api/actors/layer.h>
26 #include <dali/public-api/animation/animation.h>
27 #include <dali/public-api/object/property-notification.h>
28 #include <dali/public-api/object/weak-handle.h>
29 #include <dali/public-api/rendering/texture.h>
30 #include <unordered_map>
31
32 // INTERNAL INCLUDES
33 #include <dali-scene3d/internal/common/environment-map-load-task.h>
34 #include <dali-scene3d/internal/common/light-observer.h>
35 #include <dali-scene3d/internal/common/model-load-task.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/controls/scene-view/scene-view.h>
39 #include <dali-scene3d/public-api/light/light.h>
40 #include <dali-scene3d/public-api/loader/load-result.h>
41 #include <dali-scene3d/public-api/model-components/model-node.h>
42
43 namespace Dali
44 {
45 namespace Scene3D
46 {
47 class Model;
48
49 namespace Internal
50 {
51 /**
52  * @brief Impl class for Model.
53  */
54 class Model : public Dali::Toolkit::Internal::Control, public LightObserver
55 {
56 public:
57   using AnimationData          = std::pair<std::string, Dali::Animation>;
58   using CameraData             = Loader::CameraParameters;
59   using BlendShapeModelNodeMap = std::map<std::string, std::vector<Scene3D::ModelNode>>;
60
61   // ColliderMeshContainer doesn't hold actual collider meshes
62   // but pairs unique ModelNode id with ModelNode for lookup purposes.
63   // All model nodes in the container have collider mesh attached.
64   using ColliderMeshContainer = std::unordered_map<int, Scene3D::ModelNode>;
65
66   /**
67    * @copydoc Model::New()
68    */
69   static Dali::Scene3D::Model New(const std::string& modelUrl, const std::string& resourceDirectoryUrl);
70
71   /**
72    * @copydoc Model::GetModelRoot()
73    */
74   const Scene3D::ModelNode GetModelRoot() const;
75
76   /**
77    * @copydoc Model::AddModelNode()
78    */
79   void AddModelNode(Scene3D::ModelNode modelNode);
80
81   /**
82    * @copydoc Model::RemoveModelNode()
83    */
84   void RemoveModelNode(Scene3D::ModelNode modelNode);
85
86   /**
87    * @copydoc Model::SetChildrenSensitive()
88    */
89   void SetChildrenSensitive(bool enable);
90
91   /**
92    * @copydoc Model::GetChildrenSensitive()
93    */
94   bool GetChildrenSensitive() const;
95
96   /**
97    * @copydoc Model::SetChildrenFocusable()
98    */
99   void SetChildrenFocusable(bool enable);
100
101   /**
102    * @copydoc Model::GetChildrenFocusable()
103    */
104   bool GetChildrenFocusable() const;
105
106   /**
107    * @copydoc Model::SetImageBasedLightSource()
108    */
109   void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor);
110
111   /**
112    * @copydoc Model::SetImageBasedLightScaleFactor()
113    */
114   void SetImageBasedLightScaleFactor(float scaleFactor);
115
116   /**
117    * @copydoc Model::GetImageBasedLightScaleFactor()
118    */
119   float GetImageBasedLightScaleFactor() const;
120
121   /**
122    * @copydoc Model::GetAnimationCount()
123    */
124   uint32_t GetAnimationCount() const;
125
126   /**
127    * @copydoc Model::GetAnimation()
128    */
129   Dali::Animation GetAnimation(uint32_t index) const;
130
131   /**
132    * @copydoc Model::GetAnimation()
133    */
134   Dali::Animation GetAnimation(const std::string& name) const;
135
136   /**
137    * @copydoc Model::GetCameraCount()
138    */
139   uint32_t GetCameraCount() const;
140
141   /**
142    * @copydoc Model::GenerateCamera()
143    */
144   Dali::CameraActor GenerateCamera(uint32_t index) const;
145
146   /**
147    * @copydoc Model::ApplyCamera()
148    */
149   bool ApplyCamera(uint32_t index, Dali::CameraActor camera) const;
150
151   /**
152    * @copydoc Model::FindChildModelNodeByName()
153    */
154   Scene3D::ModelNode FindChildModelNodeByName(std::string_view nodeName);
155
156   /**
157    * @copydoc Model::RetrieveBlendShapeNames()
158    */
159   void RetrieveBlendShapeNames(std::vector<std::string>& blendShapeNames) const;
160
161   /**
162    * @copydoc Model::RetrieveModelNodesByBlendShapeName()
163    */
164   void RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector<Scene3D::ModelNode>& modelNodes) const;
165
166   /**
167    * @copydoc Model::GenerateMotionDataAnimation()
168    */
169   Dali::Animation GenerateMotionDataAnimation(Scene3D::MotionData motionData);
170
171   /**
172    * @copydoc Model::SetMotionData()
173    */
174   void SetMotionData(Scene3D::MotionData motionData);
175
176   /**
177    * @copydoc Model::CastShadow()
178    */
179   void CastShadow(bool castShadow);
180
181   /**
182    * @copydoc Model::IsShadowCasting()
183    */
184   bool IsShadowCasting() const;
185
186   /**
187    * @copydoc Model::ReceiveShadow()
188    */
189   void ReceiveShadow(bool receiveShadow);
190
191   /**
192    * @copydoc Model::IsShadowReceiving()
193    */
194   bool IsShadowReceiving() const;
195
196   /**
197    * @copydoc Scene3D::Model::MeshHitSignal()
198    */
199   Scene3D::Model::MeshHitSignalType& MeshHitSignal()
200   {
201     return mMeshHitSignal;
202   }
203
204   /**
205    * @brief Emits MeshHitSignal
206    * @param[in] modelNode ModelNode that has been hit
207    * @return Result of hit handling.
208    */
209   bool EmitMeshHitSignal(Scene3D::ModelNode modelNode)
210   {
211     bool retVal = false;
212     if(!mMeshHitSignal.Empty())
213     {
214       Scene3D::Model handle(GetOwner());
215       retVal = mMeshHitSignal.Emit(handle, modelNode);
216     }
217     return retVal;
218   }
219
220   /**
221    * @brief Returns collider mesh container
222    * @return Returns valid container
223    */
224   const ColliderMeshContainer& GetNodeColliderMeshContainer() const
225   {
226     return mColliderMeshes;
227   }
228
229   /**
230    * @brief Registers child node with collidier mesh
231    *
232    * @param[in] node ModelNode to register
233    */
234   void RegisterColliderMesh(Scene3D::ModelNode& node);
235
236   /**
237    * @brief Removes node/collider mesh from the register
238    * @param[in] node Child node to remove from the register
239    */
240   void RemoveColliderMesh(Scene3D::ModelNode& node);
241
242 protected:
243   /**
244    * @brief Constructs a new Model.
245    * @param[in] modelUrl model file path.(e.g., glTF, and DLI).
246    * @param[in] resourceDirectoryUrl resource file path that includes binary, image etc.
247    */
248   Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl);
249
250   /**
251    * A reference counted object may only be deleted by calling Unreference()
252    */
253   virtual ~Model();
254
255 private:
256   /**
257    * @copydoc Toolkit::Control::OnInitialize
258    */
259   void OnInitialize();
260
261   /**
262    * @copydoc CustomActorImpl::OnSceneConnection()
263    */
264   void OnSceneConnection(int depth) override;
265
266   /**
267    * @copydoc CustomActorImpl::OnSceneDisconnection()
268    */
269   void OnSceneDisconnection() override;
270
271   /**
272    * @copydoc CustomActorImpl::OnSizeSet( const Vector3& size )
273    */
274   void OnSizeSet(const Vector3& size) override;
275
276   /**
277    * @copydoc Toolkit::Control::GetNaturalSize
278    */
279   Vector3 GetNaturalSize() override;
280
281   /**
282    * @copydoc Toolkit::Control::GetHeightForWidth()
283    */
284   float GetHeightForWidth(float width) override;
285
286   /**
287    * @copydoc Toolkit::Control::GetWidthForHeight()
288    */
289   float GetWidthForHeight(float height) override;
290
291   /**
292    * @copydoc Toolkit::Control::OnRelayout()
293    */
294   void OnRelayout(const Vector2& size, RelayoutContainer& container) override;
295
296   /**
297    * @copydoc Toolkit::Control::IsResourceReady()
298    */
299   bool IsResourceReady() const override;
300
301 private:
302   /**
303    * @brief Create Model Root of this Model class.
304    */
305   void CreateModelRoot();
306
307   /**
308    * @brief Scales the model to fit the control or to return to original size.
309    */
310   void ScaleModel(bool useCurrentSize);
311
312   /**
313    * @brief Changes model anchor point to set the model at center or returns to the original model pivot.
314    */
315   void FitModelPosition();
316
317   /**
318    * @brief Makes the input node cast shadow or not.
319    */
320   void UpdateCastShadowRecursively(Scene3D::ModelNode node, bool castShadow);
321
322   /**
323    * @brief Makes the input node receive shadow or not.
324    */
325   void UpdateReceiveShadowRecursively(Scene3D::ModelNode node, bool receiveShadow);
326
327   /**
328    * @brief Changes IBL information of the input node.
329    */
330   void UpdateImageBasedLightTextureRecursively(Scene3D::ModelNode node, Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels);
331
332   /**
333    * @brief Changes IBL factor of the input node.
334    */
335   void UpdateImageBasedLightScaleFactorRecursively(Scene3D::ModelNode node, float iblScaleFactor);
336
337   /**
338    * @brief Changes IBL textures of the input node.
339    */
340   void UpdateImageBasedLightTexture();
341
342   /**
343    * @brief Changes IBL scale factor of the input node.
344    */
345   void UpdateImageBasedLightScaleFactor();
346
347   /**
348    * @brief Apply self transform into inputed camera.
349    * Inputed camera must be configured by CameraParameter. Mean, inputed camera coordinate depend on Model.
350    * After this API finished, CameraActor coordinate system converted as DALi coordinate system.
351    *
352    * @param[in,out] camera CameraActor who need to apply model itself's transform
353    */
354   void ApplyCameraTransform(Dali::CameraActor camera) const;
355
356 public: // Overrides LightObserver Methods.
357   /**
358    * @copydoc Dali::Scene3D::Internal::LightObserver::NotifyShadowMapTexture()
359    */
360   void NotifyShadowMapTexture(Dali::Texture shadowMapTexture) override;
361
362   /**
363    * @copydoc Dali::Scene3D::Internal::LightObserver::NotifyImageBasedLightTexture()
364    */
365   void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels) override;
366
367   /**
368    * @copydoc Dali::Scene3D::Internal::LightObserver::NotifyImageBasedLightScaleFactor()
369    */
370   void NotifyImageBasedLightScaleFactor(float scaleFactor) override;
371
372 private:
373   /**
374    * @brief Asynchronously model loading finished.
375    */
376   void OnModelLoadComplete();
377
378   /**
379    * @brief Asynchronously ibl diffusel image loading finished.
380    */
381   void OnIblDiffuseLoadComplete();
382
383   /**
384    * @brief Asynchronously ibl specular image loading finished.
385    */
386   void OnIblSpecularLoadComplete();
387
388   /**
389    * @brief Asynchronously ibl loading finished.
390    */
391   void OnIblLoadComplete();
392
393   /**
394    * @brief Update model root scale when Model size property is updated.
395    */
396   void OnSizeNotification(Dali::PropertyNotification& source);
397
398   /**
399    * @brief Reset Resource loading tasks.
400    */
401   void ResetResourceTasks();
402
403   /**
404    * @brief Notify Resource Ready signal.
405    */
406   void NotifyResourceReady();
407
408   /**
409    * @brief Create Model from loaded SceneDefinition.
410    */
411   void CreateModel();
412
413   /**
414    * @brief Create Dali::Animation from loaded AnimationDefinitions.
415    */
416   void CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene);
417
418   /**
419    * @brief Reset CameraData from loaded CameraParameters.
420    */
421   void ResetCameraParameters();
422
423   /**
424    * @brief Collect ModelNode list by blendshape name
425    */
426   void UpdateBlendShapeNodeMap();
427
428 private:
429   std::string                    mModelUrl;
430   std::string                    mResourceDirectoryUrl;
431   Scene3D::ModelNode             mModelRoot;
432   std::vector<AnimationData>     mAnimations;
433   std::vector<CameraData>        mCameraParameters;
434   WeakHandle<Scene3D::SceneView> mParentSceneView;
435   Dali::PropertyNotification     mSizeNotification;
436
437   // Signals
438   Scene3D::Model::MeshHitSignalType mMeshHitSignal;
439
440   Dali::Scene3D::Loader::ShaderManagerPtr mShaderManager;
441
442   ColliderMeshContainer mColliderMeshes;
443
444   // List of ModelNode for name of blend shape.
445   BlendShapeModelNodeMap mBlendShapeModelNodeMap;
446
447   // Asynchronous loading variable
448   ModelLoadTaskPtr          mModelLoadTask;
449   EnvironmentMapLoadTaskPtr mIblDiffuseLoadTask;
450   EnvironmentMapLoadTaskPtr mIblSpecularLoadTask;
451
452   // Shadow
453   Dali::Texture mShadowMapTexture;
454
455   std::string mDiffuseIblUrl;
456   std::string mSpecularIblUrl;
457
458   Dali::Texture mDefaultSpecularTexture;
459   Dali::Texture mDefaultDiffuseTexture;
460   Dali::Texture mSceneSpecularTexture;
461   Dali::Texture mSceneDiffuseTexture;
462   Dali::Texture mSpecularTexture;
463   Dali::Texture mDiffuseTexture;
464   Vector3       mNaturalSize;
465   Vector3       mModelPivot;
466   float         mSceneIblScaleFactor;
467   float         mIblScaleFactor;
468   uint32_t      mSceneSpecularMipmapLevels;
469   uint32_t      mSpecularMipmapLevels;
470   bool          mModelChildrenSensitive;
471   bool          mModelChildrenFocusable;
472   bool          mModelResourceReady;
473   bool          mIblDiffuseResourceReady;
474   bool          mIblSpecularResourceReady;
475   bool          mIblDiffuseDirty;
476   bool          mIblSpecularDirty;
477   bool          mIsShadowCasting;
478   bool          mIsShadowReceiving;
479 };
480
481 } // namespace Internal
482
483 // Helpers for public-api forwarding methods
484 inline Dali::Scene3D::Internal::Model& GetImpl(Dali::Scene3D::Model& obj)
485 {
486   DALI_ASSERT_ALWAYS(obj);
487   Dali::RefObject& handle = obj.GetImplementation();
488   return static_cast<Dali::Scene3D::Internal::Model&>(handle);
489 }
490
491 inline const Dali::Scene3D::Internal::Model& GetImpl(const Dali::Scene3D::Model& obj)
492 {
493   DALI_ASSERT_ALWAYS(obj);
494   const Dali::RefObject& handle = obj.GetImplementation();
495   return static_cast<const Dali::Scene3D::Internal::Model&>(handle);
496 }
497
498 } // namespace Scene3D
499
500 } // namespace Dali
501
502 #endif // DALI_SCENE3D_INTERNAL_MODEL_H