ik.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*************************************************************************/
  2. /* ik.cpp */
  3. /* Copyright (c) 2016 Sergey Lapin <slapinid@gmail.com> */
  4. /*************************************************************************/
  5. /* This file is part of: */
  6. /* GODOT ENGINE */
  7. /* https://godotengine.org */
  8. /*************************************************************************/
  9. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  10. /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
  11. /* */
  12. /* Permission is hereby granted, free of charge, to any person obtaining */
  13. /* a copy of this software and associated documentation files (the */
  14. /* "Software"), to deal in the Software without restriction, including */
  15. /* without limitation the rights to use, copy, modify, merge, publish, */
  16. /* distribute, sublicense, and/or sell copies of the Software, and to */
  17. /* permit persons to whom the Software is furnished to do so, subject to */
  18. /* the following conditions: */
  19. /* */
  20. /* The above copyright notice and this permission notice shall be */
  21. /* included in all copies or substantial portions of the Software. */
  22. /* */
  23. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  24. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  25. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  26. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  27. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  28. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  29. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  30. /*************************************************************************/
  31. #include "ik.h"
  32. bool InverseKinematics::_get(const StringName &p_name, Variant &r_ret) const {
  33. if (String(p_name) == "ik_bone") {
  34. r_ret = get_bone_name();
  35. return true;
  36. }
  37. return false;
  38. }
  39. bool InverseKinematics::_set(const StringName &p_name, const Variant &p_value) {
  40. if (String(p_name) == "ik_bone") {
  41. set_bone_name(p_value);
  42. changed = true;
  43. return true;
  44. }
  45. return false;
  46. }
  47. void InverseKinematics::_get_property_list(List<PropertyInfo> *p_list) const {
  48. Skeleton *parent = NULL;
  49. if (get_parent())
  50. parent = get_parent()->cast_to<Skeleton>();
  51. if (parent) {
  52. String names;
  53. for (int i = 0; i < parent->get_bone_count(); i++) {
  54. if (i > 0)
  55. names += ",";
  56. names += parent->get_bone_name(i);
  57. }
  58. p_list->push_back(PropertyInfo(Variant::STRING, "ik_bone", PROPERTY_HINT_ENUM, names));
  59. } else {
  60. p_list->push_back(PropertyInfo(Variant::STRING, "ik_bone"));
  61. }
  62. }
  63. void InverseKinematics::_check_bind() {
  64. if (get_parent() && get_parent()->cast_to<Skeleton>()) {
  65. Skeleton *sk = get_parent()->cast_to<Skeleton>();
  66. int idx = sk->find_bone(ik_bone);
  67. if (idx != -1) {
  68. ik_bone_no = idx;
  69. bound = true;
  70. }
  71. skel = sk;
  72. }
  73. }
  74. void InverseKinematics::_check_unbind() {
  75. if (bound) {
  76. if (get_parent() && get_parent()->cast_to<Skeleton>()) {
  77. Skeleton *sk = get_parent()->cast_to<Skeleton>();
  78. int idx = sk->find_bone(ik_bone);
  79. if (idx != -1)
  80. ik_bone_no = idx;
  81. else
  82. ik_bone_no = 0;
  83. skel = sk;
  84. }
  85. bound = false;
  86. }
  87. }
  88. void InverseKinematics::set_bone_name(const String &p_name) {
  89. if (is_inside_tree())
  90. _check_unbind();
  91. ik_bone = p_name;
  92. if (is_inside_tree())
  93. _check_bind();
  94. changed = true;
  95. }
  96. String InverseKinematics::get_bone_name() const {
  97. return ik_bone;
  98. }
  99. void InverseKinematics::set_iterations(int itn) {
  100. if (is_inside_tree())
  101. _check_unbind();
  102. iterations = itn;
  103. if (is_inside_tree())
  104. _check_bind();
  105. changed = true;
  106. }
  107. int InverseKinematics::get_iterations() const {
  108. return iterations;
  109. }
  110. void InverseKinematics::set_chain_size(int cs) {
  111. if (is_inside_tree())
  112. _check_unbind();
  113. chain_size = cs;
  114. chain.clear();
  115. if (bound)
  116. update_parameters();
  117. if (is_inside_tree())
  118. _check_bind();
  119. changed = true;
  120. }
  121. int InverseKinematics::get_chain_size() const {
  122. return chain_size;
  123. }
  124. void InverseKinematics::set_precision(float p) {
  125. if (is_inside_tree())
  126. _check_unbind();
  127. precision = p;
  128. if (is_inside_tree())
  129. _check_bind();
  130. changed = true;
  131. }
  132. float InverseKinematics::get_precision() const {
  133. return precision;
  134. }
  135. void InverseKinematics::set_speed(float p) {
  136. if (is_inside_tree())
  137. _check_unbind();
  138. speed = p;
  139. if (is_inside_tree())
  140. _check_bind();
  141. changed = true;
  142. }
  143. float InverseKinematics::get_speed() const {
  144. return speed;
  145. }
  146. void InverseKinematics::update_parameters() {
  147. tail_bone = -1;
  148. for (int i = 0; i < skel->get_bone_count(); i++)
  149. if (skel->get_bone_parent(i) == ik_bone_no)
  150. tail_bone = i;
  151. int cur_bone = ik_bone_no;
  152. int its = chain_size;
  153. while (its > 0 && cur_bone >= 0) {
  154. chain.push_back(cur_bone);
  155. cur_bone = skel->get_bone_parent(cur_bone);
  156. its--;
  157. }
  158. }
  159. void InverseKinematics::_notification(int p_what) {
  160. switch (p_what) {
  161. case NOTIFICATION_ENTER_TREE: {
  162. _check_bind();
  163. if (bound) {
  164. update_parameters();
  165. changed = false;
  166. set_process(true);
  167. }
  168. } break;
  169. case NOTIFICATION_PROCESS: {
  170. Spatial *sksp = skel->cast_to<Spatial>();
  171. if (!bound)
  172. break;
  173. if (!sksp)
  174. break;
  175. if (changed) {
  176. update_parameters();
  177. changed = false;
  178. }
  179. Vector3 to = get_translation();
  180. for (int hump = 0; hump < iterations; hump++) {
  181. int depth = 0;
  182. float olderr = 1000.0;
  183. float psign = 1.0;
  184. bool reached = false;
  185. for (List<int>::Element *b = chain.front(); b; b = b->next()) {
  186. int cur_bone = b->get();
  187. Vector3 d = skel->get_bone_global_pose(tail_bone).origin;
  188. Vector3 rg = to;
  189. float err = d.distance_squared_to(rg);
  190. if (err < precision) {
  191. if (!reached && err < precision)
  192. reached = true;
  193. break;
  194. } else if (reached)
  195. reached = false;
  196. if (err > olderr)
  197. psign = -psign;
  198. Transform mod = skel->get_bone_global_pose(cur_bone);
  199. Quat q1 = Quat(mod.basis).normalized();
  200. Transform mod2 = mod.looking_at(to, Vector3(0.0, 1.0, 0.0));
  201. Quat q2 = Quat(mod2.basis).normalized();
  202. if (psign < 0.0)
  203. q2 = q2.inverse();
  204. Quat q = q1.slerp(q2, speed / (1.0 + 500.0 * depth)).normalized();
  205. Transform fin = Transform(q);
  206. fin.origin = mod.origin;
  207. skel->set_bone_global_pose(cur_bone, fin);
  208. depth++;
  209. }
  210. if (reached)
  211. break;
  212. }
  213. } break;
  214. case NOTIFICATION_EXIT_TREE: {
  215. set_process(false);
  216. _check_unbind();
  217. } break;
  218. }
  219. }
  220. void InverseKinematics::_bind_methods() {
  221. ObjectTypeDB::bind_method(_MD("set_bone_name", "ik_bone"), &InverseKinematics::set_bone_name);
  222. ObjectTypeDB::bind_method(_MD("get_bone_name"), &InverseKinematics::get_bone_name);
  223. ObjectTypeDB::bind_method(_MD("set_iterations", "iterations"), &InverseKinematics::set_iterations);
  224. ObjectTypeDB::bind_method(_MD("get_iterations"), &InverseKinematics::get_iterations);
  225. ObjectTypeDB::bind_method(_MD("set_chain_size", "chain_size"), &InverseKinematics::set_chain_size);
  226. ObjectTypeDB::bind_method(_MD("get_chain_size"), &InverseKinematics::get_chain_size);
  227. ObjectTypeDB::bind_method(_MD("set_precision", "precision"), &InverseKinematics::set_precision);
  228. ObjectTypeDB::bind_method(_MD("get_precision"), &InverseKinematics::get_precision);
  229. ObjectTypeDB::bind_method(_MD("set_speed", "speed"), &InverseKinematics::set_speed);
  230. ObjectTypeDB::bind_method(_MD("get_speed"), &InverseKinematics::get_speed);
  231. ADD_PROPERTY(PropertyInfo(Variant::INT, "iterations"), _SCS("set_iterations"), _SCS("get_iterations"));
  232. ADD_PROPERTY(PropertyInfo(Variant::INT, "chain_size"), _SCS("set_chain_size"), _SCS("get_chain_size"));
  233. ADD_PROPERTY(PropertyInfo(Variant::REAL, "precision"), _SCS("set_precision"), _SCS("get_precision"));
  234. ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed"), _SCS("set_speed"), _SCS("get_speed"));
  235. }
  236. InverseKinematics::InverseKinematics() {
  237. bound = false;
  238. chain_size = 2;
  239. iterations = 100;
  240. precision = 0.001;
  241. speed = 0.2;
  242. }