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