1 #ifndef DALI_SCENE3D_MODEL_H
2 #define DALI_SCENE3D_MODEL_H
5 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <dali-toolkit/public-api/controls/control.h>
25 #include <dali/public-api/actors/camera-actor.h>
26 #include <dali/public-api/common/dali-common.h>
27 #include <dali/public-api/rendering/texture.h>
30 #include <dali-scene3d/public-api/algorithm/navigation-mesh.h>
31 #include <dali-scene3d/public-api/api.h>
32 #include <dali-scene3d/public-api/model-components/model-node.h>
33 #include <dali-scene3d/public-api/model-motion/motion-data.h>
39 namespace Internal DALI_INTERNAL
45 * @addtogroup dali_toolkit_controls_model
50 * @brief Model is a control to show 3D model objects.
51 * Model supports to load glTF 2.0 and DLI models for the input format
52 * and also supports Physically Based Rendering with Image Based Lighting.
54 * The Animations defined in the glTF or DLI models are also loaded and can be retrieved by using GetAnimation() method.
55 * The number of animation is also retrieved by GetAnimationCount() method.
57 * By default, The loaded model has its own position and size which are defined in vertex buffer regardless of the Control size.
59 * @note We support to render model well only if glsl version is higher than 300.
64 * Model model = Model::New(modelUrl);
65 * model.SetProperty(Dali::Actor::Property::SIZE, Vector2(width, height));
66 * model.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
67 * model.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
68 * model.SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor);
70 * uint32_t animationCount = model.GetAnimationCount();
71 * Dali::Animation animation = model.GetAnimation(0);
76 class DALI_SCENE3D_API Model : public Dali::Toolkit::Control
80 using MeshHitSignalType = Signal<bool(Model, Scene3D::ModelNode)>; ///< Mesh hit signal type @SINCE_2_2.53
81 using ColliderMeshPtr = std::unique_ptr<Algorithm::NavigationMesh>;
84 * @brief Create an initialized Model.
87 * @param[in] modelUrl model file path.(e.g., glTF, and DLI).
88 * @param[in] resourceDirectoryUrl resource file path that includes binary, image etc.
89 * @note If modelUrl is empty, it will not load resouces. Only ModelRoot will be created.
90 * @note If resourceDirectoryUrl is empty, the parent directory path of modelUrl is used for resource path.
91 * @return A handle to a newly allocated Dali resource
93 static Model New(const std::string& modelUrl = std::string(), const std::string& resourceDirectoryUrl = std::string());
96 * @brief Creates an uninitialized Model.
98 * Only derived versions can be instantiated. Calling member
99 * functions with an uninitialized Dali::Object is not allowed.
108 * This is non-virtual since derived Handle types must not contain data or virtual methods.
115 * @brief Copy constructor.
118 * @param[in] model Handle to an object
120 Model(const Model& model);
123 * @brief Move constructor
126 * @param[in] rhs A reference to the moved handle
128 Model(Model&& rhs) noexcept;
131 * @brief Assignment operator.
134 * @param[in] model Handle to an object
135 * @return reference to this
137 Model& operator=(const Model& model);
140 * @brief Move assignment
143 * @param[in] rhs A reference to the moved handle
144 * @return A reference to this
146 Model& operator=(Model&& rhs) noexcept;
149 * @brief Downcasts an Object handle to Model.
151 * If handle points to a Model, the downcast produces valid handle.
152 * If not, the returned handle is left uninitialized.
155 * @param[in] handle Handle to an object
156 * @return Handle to a Model or an uninitialized handle
158 static Model DownCast(BaseHandle handle);
161 * @brief Retrieves model root Node.
164 * @return Root Node of the model.
166 const ModelNode GetModelRoot() const;
169 * @brief Add new ModelNode to this Model.
170 * This modelNode will become child of ModelRoot.
173 * @param[in] modelNode the root of ModelNode tree to be added.
175 void AddModelNode(ModelNode modelNode);
178 * @brief Remove ModelNode from this Model.
181 * @param[in] modelNode the root of ModelNode tree to be removed.
183 void RemoveModelNode(ModelNode modelNode);
186 * @brief Whether allow this model's children actor to use events.
188 * Usually, 3D Model might have a lot of actors. And most of them don't need to check events.
189 * To optimize traversal, we need to setup some flag that this model don't allow (or allow) to traversal
190 * children so that child can use events.
193 * @note Even if we set children sensitive as false, model itself's sensitive
194 * is depend on it's property.
195 * @note If we don't call this API, default is false. (Don't allow to traversal model's children during hit-test)
197 * @param[in] enable True to enable model's children can use events.
199 void SetChildrenSensitive(bool enable);
202 * @brief Gets whether this Model allow model's children actor to use events or not.
205 * @return bool True if this Model allow model children sensitive.
207 bool GetChildrenSensitive() const;
210 * @brief Whether allow this model's children actor to be keyboard focusable.
212 * Usually, 3D Model might have a lot of actors. And most of them don't need to check focusable.
213 * To optimize traversal, we need to setup some flag that this model don't allow (or allow) to traversal
214 * children so that child can be keyboard focusable.
217 * @note Even if we set children focusable as false, model itself's focusable
218 * is depend on it's property.
219 * @note If we don't call this API, default is false. (Don't allow to traversal model's children during focusable test)
221 * @param[in] enable True to enable model's children can be focusable.
223 void SetChildrenFocusable(bool enable);
226 * @brief Gets whether this Model allow model's children actor to be keyboard focusable or not.
229 * @return bool True if this Model allow model children are focusable.
231 bool GetChildrenFocusable() const;
234 * @brief Changes Image Based Light as the input textures.
237 * @param[in] diffuseUrl cube map that can be used as a diffuse IBL source.
238 * @param[in] specularUrl cube map that can be used as a specular IBL source.
239 * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.
241 void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor = 1.0f);
244 * @brief Sets Scale Factor of Image Based Light Source.
247 * @note If SetImageBasedLightSource() method is called after this method, scaleFactor is overrided.
249 * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f].
251 void SetImageBasedLightScaleFactor(float scaleFactor);
254 * @brief Gets Scale Factor of Image Based Light Source.
255 * Default value is 1.0f.
258 * @return scale factor that controls light source intensity.
260 float GetImageBasedLightScaleFactor() const;
263 * @brief Gets number of animations those loaded from model file.
266 * @return The number of loaded animations.
267 * @note This method should be called after Model load finished.
269 uint32_t GetAnimationCount() const;
272 * @brief Gets animation at the index.
275 * @param[in] index Index of animation to be retrieved.
276 * @return Animation at the index.
277 * @note This method should be called after Model load finished.
279 Dali::Animation GetAnimation(uint32_t index) const;
282 * @brief Retrieves animation with the given name.
285 * @param[in] name string name of animation to be retrieved.
286 * @return Animation that has the given name.
287 * @note This method should be called after Model load finished.
289 Dali::Animation GetAnimation(const std::string& name) const;
292 * @brief Gets number of camera parameters those loaded from model file.
295 * @return The number of loaded camera parameters.
296 * @note This method should be called after Model load finished.
298 uint32_t GetCameraCount() const;
301 * @brief Generate camera actor using camera parameters at the index.
302 * If camera parameter is valid, create new CameraActor.
303 * Camera parameter decide at initialized time and
304 * didn't apply model node's current position (like Animation).
307 * @param[in] index Index of camera to be used for generation camera.
308 * @return Generated CameraActor by the index, or empty Handle if generation failed.
309 * @note This method should be called after Model load finished.
311 Dali::CameraActor GenerateCamera(uint32_t index) const;
314 * @brief Apply camera parameters at the index to inputed camera actor.
315 * If camera parameter is valid and camera actor is not empty, apply parameters.
316 * It will change camera's transform and near / far / fov or orthographic size / aspect ratio (if defined)
317 * Camera parameter decide at initialized time and
318 * didn't apply model node's current position (like Animation).
321 * @param[in] index Index of camera to be used for generation camera.
322 * @param[in,out] camera Index of camera to be used for generation camera.
323 * @return True if apply successed. False otherwise.
324 * @note This method should be called after Model load finished.
326 bool ApplyCamera(uint32_t index, Dali::CameraActor camera) const;
329 * @brief Returns a child ModelNode object with a name that matches nodeName.
332 * @param[in] nodeName The name of the child ModelNode object you want to find.
333 * @return Returns a child ModelNode object with a name that matches nodeName. If there is no corresponding child ModelNode object, it returns an empty ModelNode object.
335 ModelNode FindChildModelNodeByName(std::string_view nodeName);
338 * @brief Retrieves the list of blendshape name that current Model hold.
339 * The name will be appended end of input list.
342 * @param[in, out] blendShapeNames The name of blendShape list collected.
343 * @note This method should be called after Model load finished.
345 void RetrieveBlendShapeNames(std::vector<std::string>& blendShapeNames) const;
348 * @brief Retrieves the list of ModelNode that contains given blend shape name.
349 * The ModelNode will be appended end of input list.
352 * @param[in] blendShapeName The name of blendShape that want to collect.
353 * @param[in, out] modelNodes The ModelNode list collected.
354 * @note This method should be called after Model load finished.
356 void RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector<ModelNode>& modelNodes) const;
359 * @brief Generates specific animation of this Model by inputed MotionData.
362 * @param[in] motionData the data of motion animation.
363 * @return Animation that be generated by MotionData. Or empty handle if there is no valid animation generated.
364 * @note This method should be called after Model load finished.
366 Dali::Animation GenerateMotionDataAnimation(MotionData motionData);
369 * @brief Sets specific values of this Model by inputed MotionData.
370 * @note If MotionValue's ValueType is ValueType::KEY_FRAMES, the last value will be set.
373 * @param[in] motionData the data of motion to be set.
374 * @note This method should be called after Model load finished.
376 void SetMotionData(Scene3D::MotionData motionData);
379 * @brief Sets whether this Model casts shadow or not.
380 * If it is true, this model is drawn on Shadow Map.
383 * @param[in] castShadow Whether this Model casts shadow or not.
384 * @note This method affects all of the child ModelNode.
385 * However, same property of each child ModelNode can be changed respectively and it not changes parent's property.
387 void CastShadow(bool castShadow);
390 * @brief Retrieves whether the Model casts shadow or not for Light.
393 * @return True if this model casts shadow.
394 * @note IBL does not cast any shadow.
396 bool IsShadowCasting() const;
399 * @brief Sets whether this Model receives shadow or not.
400 * If it is true, shadows are drawn on this model.
403 * @param[in] receiveShadow Whether this Model receives shadow or not.
404 * @note This method affects all of the child ModelNode.
405 * However, same property of each child ModelNode can be changed respectively and it not changes parent's property.
407 void ReceiveShadow(bool receiveShadow);
410 * @brief Retrieves whether the Model receives shadow or not for Light.
413 * @return True if this model receives shadow.
415 bool IsShadowReceiving() const;
418 * @brief This signal is emitted when the collider mesh is touched/hit.
420 * A callback of the following type may be connected:
422 * bool YourCallbackName(Model model, ModelNode modelNode);
424 * Here the model is the model that is hit and the ModelNode containing the collider mesh
426 * The return value of True, indicates that the hover event should be consumed.
427 * Otherwise the signal will be emitted on the next sensitive parent of the actor.
430 * @return The signal to connect to
432 MeshHitSignalType& MeshHitSignal();
434 public: // Not intended for application developers
437 * @brief Creates a handle using the Toolkit::Internal implementation.
439 * @param[in] implementation The Control implementation
441 DALI_INTERNAL Model(Internal::Model& implementation);
444 * @brief Allows the creation of this Control from an Internal::CustomActor pointer.
446 * @param[in] internal A pointer to the internal CustomActor
448 DALI_INTERNAL Model(Dali::Internal::CustomActor* internal);
455 } // namespace Scene3D
459 #endif // DALI_SCENE3D_MODEL_H