1 #ifndef IK_NODE_H
2 #define IK_NODE_H
3 
4 #include "ik/config.h"
5 #include "ik/bst_vector.h"
6 #include "ik/vec3.h"
7 #include "ik/quat.h"
8 
9 C_HEADER_BEGIN
10 
11 /*!
12  * @brief Represents one node in the tree to be solved.
13  */
14 struct ik_node_t
15 {
16     /*!
17      * @brief Allows the user of this library to store custom data per node
18      * @note Can be set and retrieved directly without issue.
19      *
20      * This is especially useful in c++ applications which need to store the
21      * "this" pointer to their own scene graph nodes. The user data can be
22      * accessed in callback functions to make object calls again.
23      *
24      * For instance:
25      * ```cpp
26      * // A node in your scene graph
27      * MyNode* node = GetMyNode();
28      *
29      * ik_solver_t* solver = ik_solver_create(SOLVER_FABRIK);
30      * ik_node_t* ikNode = ik_node_create(node->GetID());
31      * ikNode->user_data = node; // Store pointer to your own node object
32      *
33      * // ---- elsewhere ------
34      * static void ApplyResultsCallback(ik_node_t* ikNode)
35      * {
36      *     Node* node = (Node*)ikNode->user_data; // Extract your own node object again
37      *     node->SetPosition(ikNode->solved_position);
38      * }
39      * ```
40      */
41     void* user_data;
42 
43     /*!
44      * @brief The initial global position (in world space).
45      * @note Must be set by the user to get correct results. This value can
46      * be set and retrieved at any time.
47      * @note The default value is (0, 0, 0).
48      */
49     vec3_t original_position;
50 
51     /*!
52      * @brief The initial global rotation (in world space).
53      * @note Must be set by the user to get correct results if the solver has
54      * angle computations enabled (SOLVER_CALCULATE_FINAL_ANGLES).
55      * @note The default value is the identity quaternion.
56      */
57     quat_t original_rotation;
58 
59     /*!
60      * @brief After the solver is executed, the solved global (world) position
61      * is stored here and can be retrieved.
62      */
63     vec3_t position;
64 
65     /*!
66      * @brief After the solver is executed, the solved global (world) rotation
67      * is stored here and can be retrieved.
68      */
69     quat_t rotation;
70 
71     /*!
72      * @brief Global identifier for this node. The identifier must be unique
73      * within the tree, but separate trees may re-use the same IDs again. The
74      * ID can later be used to retrieve nodes from the tree again.
75      * @note Don't change this if this node has a parent. If you need to change
76      * the guid then unlink the node, change it, and re-add it as a child.
77      */
78     uint32_t guid;
79 
80     /*!
81      * @brief The end effector object.
82      * @note This pointer should not be changed directly. You can however set
83      * the target position/rotation of the effector by writing to
84      * node->effector->target_position or node->effector->target_rotation.
85      * @note May be NULL.
86      */
87     ik_effector_t* effector;
88 
89     ik_constraint_t* constraint;
90 
91     ik_real stiffness;
92     ik_real rotation_weight;
93 
94     /* Private data */
95     ik_real segment_length;
96     ik_node_t* parent;
97     bstv_t children;    /* ik_node_t objects */
98 };
99 
100 /*!
101  * @brief Creates a new node and returns it. Each node requires a tree-unique
102  * ID, which can be used later to search for nodes in the tree.
103  */
104 IK_PUBLIC_API ik_node_t*
105 ik_node_create(uint32_t guid);
106 
107 /*!
108  * @brief Constructs an already allocated node.
109  */
110 IK_PUBLIC_API void
111 ik_node_construct(ik_node_t* node, uint32_t guid);
112 
113 /*!
114  * @brief Destructs a node, destroying all children in the process, but does
115  * not deallocate the node object itself.
116  */
117 IK_PUBLIC_API void
118 ik_node_destruct(ik_node_t* node);
119 
120 /*!
121  * @brief Destructs and frees the node, destroying all children in the process.
122  * If the node was part of a tree, then it will be removed from its parents.
123  * @note You will need to rebuild the solver's tree before solving.
124  */
125 IK_PUBLIC_API void
126 ik_node_destroy(ik_node_t* node);
127 
128 /*!
129  * @brief Attaches a node as a child to another node. The parent node gains
130  * ownership of the child node and is responsible for deallocating it.
131  * @note You will need to rebuild the solver's tree before solving.
132  */
133 IK_PUBLIC_API void
134 ik_node_add_child(ik_node_t* node, ik_node_t* child);
135 
136 /*!
137  * @brief Unlinks a node from the tree, without destroying anything. All
138  * children of the unlinked node remain in tact and will no longer be
139  * affiliated with the original tree.
140  * @note You will need to rebuild the solver's tree before solving.
141  */
142 IK_PUBLIC_API void
143 ik_node_unlink(ik_node_t* node);
144 
145 /*!
146  * @brief Searches recursively for a node in a tree with the specified global
147  * identifier.
148  * @return Returns NULL if the node was not found, otherwise the node is
149  * returned.
150  */
151 IK_PUBLIC_API ik_node_t*
152 ik_node_find_child(ik_node_t* node, uint32_t guid);
153 
154 /*!
155  * @brief Attaches an effector object to the node. The node gains ownership
156  * of the effector and is responsible for its deallocation. If the node
157  * already owns an effector, then it is first destroyed.
158  * @note You will need to rebuild the solver's tree before solving.
159  */
160 IK_PUBLIC_API void
161 ik_node_attach_effector(ik_node_t* node, ik_effector_t* effector);
162 
163 /*!
164  * @brief Removes and destroys the node's effector, if it exists. The field
165  * node->effector is set to NULL.
166  * @note You will need to rebuild the solver's tree before solving.
167  */
168 IK_PUBLIC_API void
169 ik_node_destroy_effector(ik_node_t* node);
170 
171 /*!
172  * @brief The constraint is attached to the specified node, but applies to the
173  * parent of this node. In other words, if you wish to constraint the rotation
174  * of node A then you must attach said constraint to the **child** of node A.
175  *
176  * Constraints are a bit strange in how they are stored. They don't apply to
177  * single nodes, rather, they apply to entire segments (edges connecting nodes).
178  * This is not apparent in a single chain of nodes, but becomes apparent if you
179  * consider a tree structure.
180  *
181  *    A   C
182  *     \ /
183  *      B
184  *      |
185  *      D
186  *
187  * If you wanted to constraint the rotation of D, then you would add a
188  * constraint to node B. If you wanted to constraint the rotation of the
189  * segment B-A then you would add a constraint to node A.
190  *
191  * @param[in] node The child of the node you wish to constrain.
192  * @param[in] constraint The constraint object. The node gains ownership of
193  * the constraint and is responsible for its deallocation. If the node already
194  * owns a constraint, then it is first destroyed.
195  */
196 IK_PUBLIC_API void
197 ik_node_attach_constraint(ik_node_t* node, ik_constraint_t* constraint);
198 
199 /*!
200  * @brief Removes and destroys the node's constraint, if it exists. The field
201  * node->constraint is set to NULL.
202  */
203 IK_PUBLIC_API void
204 ik_node_destroy_constraint(ik_node_t* node);
205 
206 /*!
207  * @brief Dumps all nodes recursively to DOT format. You can use graphviz (
208  * or other compatible tools) to generate a graphic of the tree.
209  */
210 IK_PUBLIC_API void
211 ik_node_dump_to_dot(ik_node_t* node, const char* file_name);
212 
213 IK_PUBLIC_API void
214 ik_node_global_to_local(ik_node_t* node);
215 
216 IK_PUBLIC_API void
217 ik_node_local_to_global(ik_node_t* node);
218 
219 C_HEADER_END
220 
221 #endif /* IK_NODE_H */
222