1 #ifndef IK_SOLVER_H
2 #define IK_SOLVER_H
3 
4 #include "ik/config.h"
5 #include "ik/chain_tree.h"
6 #include "ik/ordered_vector.h"
7 #include "ik/quat.h"
8 #include "ik/vec3.h"
9 
10 C_HEADER_BEGIN
11 
12 typedef void (*ik_solver_destruct_func)(ik_solver_t*);
13 typedef int (*ik_solver_post_chain_build_func)(ik_solver_t*);
14 typedef int (*ik_solver_solve_func)(ik_solver_t*);
15 
16 typedef void (*ik_solver_iterate_node_cb_func)(ik_node_t*);
17 
18 typedef enum solver_algorithm_e
19 {
20     SOLVER_ONE_BONE,
21     SOLVER_TWO_BONE,
22     SOLVER_FABRIK,
23     SOLVER_MSD
24     /* TODO Not implemented
25     SOLVER_JACOBIAN_INVERSE,
26     SOLVER_JACOBIAN_TRANSPOSE */
27 } solver_algorithm_e;
28 
29 typedef enum solver_flags_e
30 {
31     /*!
32      * @brief Causes the root node in the tree to be excluded from the list of
33      * nodes to solve for. It won't be affected by the solver, but it may still
34      * be passed through to the result callback function.
35      */
36     SOLVER_EXCLUDE_ROOT                   = 0x01,
37 
38     SOLVER_ENABLE_CONSTRAINTS             = 0x02,
39 
40     SOLVER_CALCULATE_TARGET_ROTATIONS     = 0x04
41 } solver_flags_e;
42 
43 /*!
44  * @brief This is a base for all solvers.
45  */
46 #define SOLVER_DATA_HEAD                                              \
47     int32_t                             max_iterations;               \
48     float                               tolerance;                    \
49     uint8_t                             flags;                        \
50                                                                       \
51     /* Derived structure callbacks */                                 \
52     ik_solver_destruct_func             destruct;                     \
53     ik_solver_post_chain_build_func     post_chain_build;             \
54     ik_solver_solve_func                solve;                        \
55                                                                       \
56     ordered_vector_t                    effector_nodes_list;          \
57     ik_node_t*                          tree;                         \
58     /* list of ik_chain_tree_t objects (allocated in-place) */        \
59     chain_tree_t                        chain_tree;
60 
61 struct ik_solver_t
62 {
63     SOLVER_DATA_HEAD
64 };
65 
66 /*!
67  * @brief Allocates a new solver object according to the specified algorithm.
68  *
69  * Once the solver is created, you can configure the solver to enable/disable
70  * various features depending on your needs.
71  *
72  * The following attributes can be changed at any point.
73  *  + solver->apply_result
74  *       This is the main mechanism with which to obtain the solved data.
75  *       Assign a callback function here and it will be called for every node
76  *       in the tree when a new target position/rotation has been calculated.
77  *       You can use the node->user_data attribute to store external node
78  *       specific data, which can be accessed again the in callback function.
79  *  + solver->max_iterations
80  *       Specifies the maximum number of iterations. The more iterations, the
81  *       more exact the result will be. The default value for the FABRIK solver
82  *       is 20, but you can get away with values as low as 5.
83  *  + solver->tolerance
84  *       This value can be changed at any point. Specifies the acceptable
85  *       distance each effector needs to be to its target position. The solver
86  *       will stop iterating if the effectors are within this distance. The
87  *       default value is 1e-3. Recommended values are 100th of your world
88  *       unit.
89  *  + solver->flags
90  *       Changes the behaviour of the solver. See the enum solver_flags_e for
91  *       more information.
92  *
93  * The following attributes can be accessed (read from) but should not be
94  * modified.
95  *  + solver->tree
96  *       The tree to be solved. You may modify the nodes in the tree.
97  *       @note If you add/remove nodes or if you add/remove effectors, you
98  *       must call ik_solver_rebuild_data() so the internal solver structures
99  *       are updated. Failing to do so may cause segfaults. If you're just
100  *       updating positions/rotations or any of the other public data then
101  *       there is no need to rebuild data.
102  *  + solver->effector_nodes_list
103  *       A vector containing pointers to nodes in the tree which have an
104  *       effector attached to them. You may not modify this list, but you may
105  *       iterate it.
106  * @param[in] algorithm The algorithm to use. Currently, only FABRIK is
107  * supported.
108  */
109 IK_PUBLIC_API ik_solver_t*
110 ik_solver_create(solver_algorithm_e algorithm);
111 
112 /*!
113  * @brief Destroys the solver and all nodes/effectors that are part of the
114  * solver. Any pointers to tree nodes are invalid after this function returns.
115  */
116 IK_PUBLIC_API void
117 ik_solver_destroy(ik_solver_t* solver);
118 
119 /*!
120  * @brief Sets the tree to solve. The solver takes ownership of the tree, so
121  * destroying the solver will destroy all nodes in the tree. Note that you will
122  * have to call ik_solver_rebuild_data() before being able to solve it. If the
123  * solver already has a tree, then said tree will be destroyed.
124  */
125 IK_PUBLIC_API void
126 ik_solver_set_tree(ik_solver_t* solver, ik_node_t* root);
127 
128 /*!
129  * @brief The solver releases any references to a previously set tree and
130  * returns the root node of said tree. Any proceeding calls that involve the
131  * tree (e.g. solve or rebuild) will have no effect until a new tree is set.
132  * @return If the solver has no tree then NULL is returned.
133  */
134 IK_PUBLIC_API ik_node_t*
135 ik_solver_unlink_tree(ik_solver_t* solver);
136 
137 /*!
138  * @brief The solver releases any references to a previously set tree and
139  * destroys it.
140  */
141 IK_PUBLIC_API void
142 ik_solver_destroy_tree(ik_solver_t* solver);
143 
144 /*!
145  * @brief Causes the set tree to be processed into more optimal data structures
146  * for solving. Must be called before ik_solver_solve().
147  * @note Needs to be called whenever the tree changes in any way. I.e. if you
148  * remove nodes or add nodes, or if you remove effectors or add effectors,
149  * you must call this again before calling the solver.
150  * @return Returns non-zero if any of the chain trees are invalid for any
151  * reason. If this happens, check the log for error messages.
152  * @warning If this functions fails, the internal structures are in an
153  * undefined state. You cannot solve the tree in this state.
154  */
155 IK_PUBLIC_API int
156 ik_solver_rebuild_chain_trees(ik_solver_t* solver);
157 
158 /*!
159  * @brief Unusual, but if you have a tree with translational motions such that
160  * the distances between nodes changes (perhaps a slider?), you can call this
161  * to re-calculate the segment lengths after assigning new positions to the
162  * nodes.
163  * @note This function gets called by ik_solver_rebuild_data().
164  */
165 IK_PUBLIC_API void
166 ik_solver_recalculate_segment_lengths(ik_solver_t* solver);
167 
168 /*!
169  * @brief Solves the IK problem. The node solutions will be provided via a
170  * callback function, which can be registered to the solver by assigning it to
171  * solver->apply_result.
172  */
173 IK_PUBLIC_API int
174 ik_solver_solve(ik_solver_t* solver);
175 
176 IK_PUBLIC_API void
177 ik_solver_calculate_joint_rotations(ik_solver_t* solver);
178 
179 /*!
180  * @brief Iterates all nodes in the internal tree, breadth first, and passes
181  * each node to the specified callback function.
182  */
183 IK_PUBLIC_API void
184 ik_solver_iterate_tree(ik_solver_t* solver,
185                        ik_solver_iterate_node_cb_func callback);
186 
187 /*!
188  * @brief Iterates just the nodes that are being affected by the solver. Useful
189  * for a more optimized write-back of the solution data.
190  */
191 IK_PUBLIC_API void
192 ik_solver_iterate_chain_tree(ik_solver_t* solver,
193                              ik_solver_iterate_node_cb_func callback);
194 
195 /*!
196  * @brief Sets the solved positions and rotations equal to the original
197  * positions and rotations for every node in the tree.
198  */
199 IK_PUBLIC_API void
200 ik_solver_reset_to_original_pose(ik_solver_t* solver);
201 
202 C_HEADER_END
203 
204 #endif /* IK_SOLVER_H */
205