1 /*************************************************************************/ 2 /* skeleton_ik.h */ 3 /*************************************************************************/ 4 /* This file is part of: */ 5 /* GODOT ENGINE */ 6 /* https://godotengine.org */ 7 /*************************************************************************/ 8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ 9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ 10 /* */ 11 /* Permission is hereby granted, free of charge, to any person obtaining */ 12 /* a copy of this software and associated documentation files (the */ 13 /* "Software"), to deal in the Software without restriction, including */ 14 /* without limitation the rights to use, copy, modify, merge, publish, */ 15 /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 /* permit persons to whom the Software is furnished to do so, subject to */ 17 /* the following conditions: */ 18 /* */ 19 /* The above copyright notice and this permission notice shall be */ 20 /* included in all copies or substantial portions of the Software. */ 21 /* */ 22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 /*************************************************************************/ 30 31 #ifndef SKELETON_IK_H 32 #define SKELETON_IK_H 33 34 #ifndef _3D_DISABLED 35 36 /** 37 * @author AndreaCatania 38 */ 39 40 #include "core/math/transform.h" 41 #include "scene/3d/skeleton.h" 42 43 class FabrikInverseKinematic { 44 45 struct EndEffector { 46 BoneId tip_bone; 47 Transform goal_transform; 48 }; 49 50 struct ChainItem { 51 52 Vector<ChainItem> children; 53 ChainItem *parent_item; 54 55 // Bone info 56 BoneId bone; 57 PhysicalBone *pb; 58 59 real_t length; 60 /// Positions relative to root bone 61 Transform initial_transform; 62 Vector3 current_pos; 63 // Direction from this bone to child 64 Vector3 current_ori; 65 ChainItemChainItem66 ChainItem() : 67 parent_item(NULL), 68 bone(-1), 69 pb(NULL), 70 length(0) {} 71 72 ChainItem *find_child(const BoneId p_bone_id); 73 ChainItem *add_child(const BoneId p_bone_id); 74 }; 75 76 struct ChainTip { 77 ChainItem *chain_item; 78 const EndEffector *end_effector; 79 ChainTipChainTip80 ChainTip() : 81 chain_item(NULL), 82 end_effector(NULL) {} 83 ChainTipChainTip84 ChainTip(ChainItem *p_chain_item, const EndEffector *p_end_effector) : 85 chain_item(p_chain_item), 86 end_effector(p_end_effector) {} 87 ChainTipChainTip88 ChainTip(const ChainTip &p_other_ct) : 89 chain_item(p_other_ct.chain_item), 90 end_effector(p_other_ct.end_effector) {} 91 }; 92 93 struct Chain { 94 ChainItem chain_root; 95 ChainItem *middle_chain_item; 96 Vector<ChainTip> tips; 97 Vector3 magnet_position; 98 }; 99 100 public: 101 struct Task : public RID_Data { 102 RID self; 103 Skeleton *skeleton; 104 105 Chain chain; 106 107 // Settings 108 real_t min_distance; 109 int max_iterations; 110 111 // Bone data 112 BoneId root_bone; 113 Vector<EndEffector> end_effectors; 114 115 Transform goal_global_transform; 116 TaskTask117 Task() : 118 skeleton(NULL), 119 min_distance(0.01), 120 max_iterations(10), 121 root_bone(-1) {} 122 }; 123 124 private: 125 /// Init a chain that starts from the root to tip 126 static bool build_chain(Task *p_task, bool p_force_simple_chain = true); 127 128 static void update_chain(const Skeleton *p_sk, ChainItem *p_chain_item); 129 130 static void solve_simple(Task *p_task, bool p_solve_magnet); 131 /// Special solvers that solve only chains with one end effector 132 static void solve_simple_backwards(Chain &r_chain, bool p_solve_magnet); 133 static void solve_simple_forwards(Chain &r_chain, bool p_solve_magnet); 134 135 public: 136 static Task *create_simple_task(Skeleton *p_sk, BoneId root_bone, BoneId tip_bone, const Transform &goal_transform); 137 static void free_task(Task *p_task); 138 // The goal of chain should be always in local space 139 static void set_goal(Task *p_task, const Transform &p_goal); 140 static void make_goal(Task *p_task, const Transform &p_inverse_transf, real_t blending_delta); 141 static void solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position); 142 }; 143 144 class SkeletonIK : public Node { 145 GDCLASS(SkeletonIK, Node); 146 147 StringName root_bone; 148 StringName tip_bone; 149 real_t interpolation; 150 Transform target; 151 NodePath target_node_path_override; 152 bool override_tip_basis; 153 bool use_magnet; 154 Vector3 magnet_position; 155 156 real_t min_distance; 157 int max_iterations; 158 159 Skeleton *skeleton; 160 Spatial *target_node_override; 161 FabrikInverseKinematic::Task *task; 162 163 protected: 164 virtual void 165 _validate_property(PropertyInfo &property) const; 166 167 static void _bind_methods(); 168 virtual void _notification(int p_what); 169 170 public: 171 SkeletonIK(); 172 virtual ~SkeletonIK(); 173 174 void set_root_bone(const StringName &p_root_bone); 175 StringName get_root_bone() const; 176 177 void set_tip_bone(const StringName &p_tip_bone); 178 StringName get_tip_bone() const; 179 180 void set_interpolation(real_t p_interpolation); 181 real_t get_interpolation() const; 182 183 void set_target_transform(const Transform &p_target); 184 const Transform &get_target_transform() const; 185 186 void set_target_node(const NodePath &p_node); 187 NodePath get_target_node(); 188 189 void set_override_tip_basis(bool p_override); 190 bool is_override_tip_basis() const; 191 192 void set_use_magnet(bool p_use); 193 bool is_using_magnet() const; 194 195 void set_magnet_position(const Vector3 &p_local_position); 196 const Vector3 &get_magnet_position() const; 197 198 void set_min_distance(real_t p_min_distance); get_min_distance()199 real_t get_min_distance() const { return min_distance; } 200 201 void set_max_iterations(int p_iterations); get_max_iterations()202 int get_max_iterations() const { return max_iterations; } 203 get_parent_skeleton()204 Skeleton *get_parent_skeleton() const { return skeleton; } 205 206 bool is_running(); 207 208 void start(bool p_one_time = false); 209 void stop(); 210 211 private: 212 Transform _get_target_transform(); 213 void reload_chain(); 214 void reload_goal(); 215 void _solve_chain(); 216 }; 217 218 #endif // _3D_DISABLED 219 220 #endif // SKELETON_IK_H 221