1 #ifndef DALI_SCENE3D_LOADER_SCENE_DEFINITION_H_
2 #define DALI_SCENE3D_LOADER_SCENE_DEFINITION_H_
4 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include <dali/public-api/actors/actor.h>
22 #include <dali/public-api/math/matrix.h>
23 #include <dali/public-api/math/quaternion.h>
24 #include <dali/public-api/math/vector4.h>
29 #include <dali-scene3d/public-api/loader/customization.h>
30 #include <dali-scene3d/public-api/loader/node-definition.h>
31 #include <dali-scene3d/public-api/loader/string-callback.h>
32 #include <dali-scene3d/public-api/loader/utils.h>
34 namespace Dali::Scene3D::Loader
39 * @brief Intermediate representation of a scene with functionality required to
40 * create DALi objects (Actors, Renderers) from it.
42 class DALI_SCENE3D_API SceneDefinition
45 using NodePredicate = std::function<bool(const NodeDefinition&)>;
46 using NodeConsumer = std::function<void(NodeDefinition&)>;
47 using ConstNodeConsumer = std::function<void(const NodeDefinition&)>;
51 SceneDefinition(SceneDefinition&& other);
55 * @brief Registers a scene root node.
56 * @return The index of the scene root node *registration*.
58 Index AddRootNode(Index iNode);
61 * @return the list of scene root node IDs in the order of their loading.
63 const std::vector<Index>& GetRoots() const;
66 * @brief Removes scene root registration at the given index @a iRoot.
67 * @note @a iRoot is the index of the registration (i.e. into the vector returned by GetRoots()),
70 void RemoveRootNode(Index iRoot);
73 * @return The number of node( definition)s in the scene.
75 uint32_t GetNodeCount() const;
78 * @return Const pointer to the node (definition) at the given index.
80 const NodeDefinition* GetNode(Index iNode) const;
83 * @return Pointer to the node (definition) at the given index.
85 NodeDefinition* GetNode(Index iNode);
88 * @brief Traverses the scene starting from the node at the given index into
89 * nodes, using the given customization @a choices and the visitor @a v.
91 void Visit(Index iNode, const Customization::Choices& choices, NodeDefinition::IVisitor& v);
94 * @brief Traverses the scene starting from the node at the given index into
95 * nodes, using the given customization @a choices and the visitor @a v.
97 void Visit(Index iNode, const Customization::Choices& choices, NodeDefinition::IConstVisitor& v) const;
100 * @brief Counts the references to meshes, shaders, materials that nodes in
101 * the scene are holding, writing the results into @a refCounts.
102 * @note @a refCounts' entries must have the correct size. Use ResourceBundle::GetRefCounter().
104 void CountResourceRefs(Index iNode, const Customization::Choices& choices, ResourceRefCounts& refCounts) const;
107 * @brief Given a bundle of @a resources that are loaded, and customization
108 * @a choices, this method traverses the scene, creating the ModelNodes and renderers
109 * from node definitions.
110 * @return Handle to the root node.
112 ModelNode CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params);
115 * @brief Creates / update a registry of mappings from customization tags to
116 * a lists of names of customizable nodes under each tag, and the number of
117 * options. If @a outMissingChoices was specified, each tag that it encounters
118 * in the scene but not in @a choices, will be registered on it with the default
121 void GetCustomizationOptions(const Customization::Choices& choices,
122 Customization::Map& outCustomizationOptions,
123 Customization::Choices* outMissingChoices) const;
126 * @brief Attempts to add @a nodeDef to the end of nodes, and its index to the end of
127 * its parent's list of children (if iParent != NodeDefinition::INVALID_PARENT).
128 * @return If the operation was successful - which requires nodeDef->name to be unique -
129 * a pointer to the stored node definition; nullptr otherwise.
131 NodeDefinition* AddNode(std::unique_ptr<NodeDefinition>&& nodeDef);
134 * @brief Moves the node to some other parent and / or to a different index.
135 * @return Whether the operation was successful.
136 * @note This is currently breaking an assumption of never having a child of a node at a lower
137 * index as that of the node itself, due to the fact that we're only changing parent ids (and
138 * entries into the vector of children of node definitions), to save the complication of having
139 * to move about, and offset indices to, everything past the reparented node. This should be
140 * sufficient AT LEAST AS LONG AS we recreate the SceneDefinition when loading the scene; if
141 * we ever needed to serialize it, we should ensure correct ordering of nodes.
143 bool ReparentNode(const std::string& name, const std::string& newParentName, Index siblingOrder);
146 * @brief Removes a node with the given name, including all of its children, and updating
147 * the indices on all remaining node definitions.
148 * @return Whether the operation was successful.
150 bool RemoveNode(const std::string& name);
153 * @brief Builds the model matrix stack for the node at the given @a index.
154 * @note It only pushes new matrices; does not require the stack to be empty (or cares if it was not).
156 void GetNodeModelStack(Index index, MatrixStack& model) const;
159 * @brief Attempts to find the definition of a node with the given @a name. Only upon
160 * success, and if @a outIndex is non-null, the index of the node is written to it.
161 * @return Pointer to the node definition; nullptr if not found.
162 * @note No ownership transfer.
164 NodeDefinition* FindNode(const std::string& name, Index* outIndex = nullptr);
167 * @brief Attempts to find the definition of a node with the given @a name. Only upon
168 * success, and if @a outIndex is non-null, the index of the node is written to it.
169 * @return Pointer to the node definition; nullptr if not found.
170 * @note No ownership transfer.
172 const NodeDefinition* FindNode(const std::string& name, Index* outIndex = nullptr) const;
175 * @return The index of the given NodeDefinition@ a node, or -1 if the node definition
178 Index FindNodeIndex(const NodeDefinition& node) const;
181 * @brief Calls @a consumer with up to @a limit NodeDefinitions that evaluate to true
183 * @note A @a limit value of 0 means no limit.
185 void FindNodes(NodePredicate predicate, NodeConsumer consumer, unsigned int limit = 0);
188 * @brief Calls @a consumer with up to @a limit NodeDefinitions that evaluate to true
190 * @note A @a limit value of 0 means no limit.
192 void FindNodes(NodePredicate predicate, ConstNodeConsumer consumer, unsigned int limit = 0) const;
195 * @brief Applies constraints from the given requests.
197 void ApplyConstraints(Actor& root,
198 std::vector<ConstraintRequest>&& constrainables,
199 StringCallback onError = DefaultErrorCallback) const;
202 * @brief Sets up joint matrix properties and constraints on actors that are involved in skeletal
203 * animation (i.e. those that are between (inclusive) the lower and upper bounds of any skeleton),
204 * to ensure the correct update of meshes skinned to these skeletons.
205 * @param iRoot The index of the scene root node. Skeletons that aren't descendants of this node
207 * @param skeletons The list of skeletons that require setting up.
208 * @param rootActor The Actor corresponding to the root node, which will be used to locate
211 void ConfigureSkeletonJoints(uint32_t iRoot, const SkeletonDefinition::Vector& skeletons, Actor rootActor) const;
214 * @brief Ensures that there is no overlap between shaders used by nodes that have
215 * meshes skinned to different skeletons.
217 void EnsureUniqueSkinningShaderInstances(ResourceBundle& resources) const;
220 * @brief Performs the configuration of the given skinning shaders with the given skeleton
221 * This means that the absolute transforms of the joints are calculated and set as one of
222 * the uniforms in the mat4 @b uBone array (in depth first traversal). Further, the following
224 * - a @b jointMatrix property on each joint Actor;<br />
225 * - constraint from the Actor's local position and rotation (and if it has a @e joint
226 * parent, the jointMatrix of the parent) to its @b jointMatrix property;<br />
227 * - a constraint from the the Actor's @b jointMatrix property to the related entry in
228 * the shader's @b uBone property;<br />
229 * This ensures the automatic update of the skeletal animation, should any of the joints'
230 * transform changes, by whatever means.
231 * @return The success of the operations. Error messages will be posted to the optional
232 * @a onError callback.
233 * @note A maximum of SkinningDetails::MAX_JOINTS joints per skeleton are supported at the moment.
234 * @note Even if multiple skinned meshes use the same skinning shader, the correct number
235 * of separate instances need to be declared in the .dli to avoid clashing uniform
236 * definitions and constraints.
238 void ConfigureSkinningShaders(const ResourceBundle& resources,
240 std::vector<SkinningShaderConfigurationRequest>&& requests) const;
243 * @brief Ensures there is no two meshes with blend shapes sharing the same shader.
245 void EnsureUniqueBlendShapeShaderInstances(ResourceBundle& resources) const;
248 * @brief Performs the configuration of the given blend shapes.
250 * For each node with blend shapes it registers into the actor the weights properties for each morph target
251 * and some needed uniforms into the shader.
253 * @param[in] root The root actor.
254 * @param[in] requests The requests to configure blend shapes.
255 * @param[in] resources The resources bundle. Meshes need to be accessed to configure the blend shapes.
256 * @param[in] onError The error callback.
258 bool ConfigureBlendshapeShaders(const ResourceBundle& resources,
260 std::vector<BlendshapeShaderConfigurationRequest>&& requests,
261 StringCallback onError = DefaultErrorCallback) const;
263 SceneDefinition& operator=(SceneDefinition&& other);
266 bool FindNode(const std::string& name, std::unique_ptr<NodeDefinition>** result);
269 std::vector<std::unique_ptr<NodeDefinition>> mNodes; // size unknown up front (may discard nodes).
270 std::vector<Index> mRootNodeIds;
273 } // namespace Dali::Scene3D::Loader
275 #endif //DALI_SCENE3D_LOADER_SCENE_DEFINITION_H_