physical_bone_simulator_3d.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /**************************************************************************/
  2. /* physical_bone_simulator_3d.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  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. #include "physical_bone_simulator_3d.h"
  31. #include "scene/3d/physics/physical_bone_3d.h"
  32. void PhysicalBoneSimulator3D::_skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) {
  33. if (p_old) {
  34. if (p_old->is_connected(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed))) {
  35. p_old->disconnect(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed));
  36. }
  37. if (p_old->is_connected(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated))) {
  38. p_old->disconnect(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated));
  39. }
  40. }
  41. if (p_new) {
  42. if (!p_new->is_connected(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed))) {
  43. p_new->connect(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed));
  44. }
  45. if (!p_new->is_connected(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated))) {
  46. p_new->connect(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated));
  47. }
  48. }
  49. _bone_list_changed();
  50. }
  51. void PhysicalBoneSimulator3D::_bone_list_changed() {
  52. bones.clear();
  53. Skeleton3D *skeleton = get_skeleton();
  54. if (!skeleton) {
  55. return;
  56. }
  57. for (int i = 0; i < skeleton->get_bone_count(); i++) {
  58. SimulatedBone sb;
  59. sb.parent = skeleton->get_bone_parent(i);
  60. sb.child_bones = skeleton->get_bone_children(i);
  61. bones.push_back(sb);
  62. }
  63. _rebuild_physical_bones_cache();
  64. _pose_updated();
  65. }
  66. void PhysicalBoneSimulator3D::_pose_updated() {
  67. Skeleton3D *skeleton = get_skeleton();
  68. if (!skeleton || simulating) {
  69. return;
  70. }
  71. // If this triggers that means that we likely haven't rebuilt the bone list yet.
  72. if (skeleton->get_bone_count() != bones.size()) {
  73. // NOTE: this is re-entrant and will call _pose_updated again.
  74. _bone_list_changed();
  75. } else {
  76. for (int i = 0; i < skeleton->get_bone_count(); i++) {
  77. _bone_pose_updated(skeleton, i);
  78. }
  79. }
  80. }
  81. void PhysicalBoneSimulator3D::_bone_pose_updated(Skeleton3D *p_skeleton, int p_bone_id) {
  82. ERR_FAIL_INDEX(p_bone_id, bones.size());
  83. bones.write[p_bone_id].global_pose = p_skeleton->get_bone_global_pose(p_bone_id);
  84. }
  85. void PhysicalBoneSimulator3D::_set_active(bool p_active) {
  86. if (!Engine::get_singleton()->is_editor_hint()) {
  87. _reset_physical_bones_state();
  88. }
  89. }
  90. void PhysicalBoneSimulator3D::_reset_physical_bones_state() {
  91. for (int i = 0; i < bones.size(); i += 1) {
  92. if (bones[i].physical_bone) {
  93. bones[i].physical_bone->reset_physics_simulation_state();
  94. }
  95. }
  96. }
  97. bool PhysicalBoneSimulator3D::is_simulating_physics() const {
  98. return simulating;
  99. }
  100. int PhysicalBoneSimulator3D::find_bone(const String &p_name) const {
  101. Skeleton3D *skeleton = get_skeleton();
  102. if (!skeleton) {
  103. return -1;
  104. }
  105. return skeleton->find_bone(p_name);
  106. }
  107. String PhysicalBoneSimulator3D::get_bone_name(int p_bone) const {
  108. Skeleton3D *skeleton = get_skeleton();
  109. if (!skeleton) {
  110. return String();
  111. }
  112. return skeleton->get_bone_name(p_bone);
  113. }
  114. int PhysicalBoneSimulator3D::get_bone_count() const {
  115. return bones.size();
  116. }
  117. bool PhysicalBoneSimulator3D::is_bone_parent_of(int p_bone, int p_parent_bone_id) const {
  118. Skeleton3D *skeleton = get_skeleton();
  119. if (!skeleton) {
  120. return false;
  121. }
  122. return skeleton->is_bone_parent_of(p_bone, p_parent_bone_id);
  123. }
  124. void PhysicalBoneSimulator3D::bind_physical_bone_to_bone(int p_bone, PhysicalBone3D *p_physical_bone) {
  125. const int bone_size = bones.size();
  126. ERR_FAIL_INDEX(p_bone, bone_size);
  127. ERR_FAIL_COND(bones[p_bone].physical_bone);
  128. ERR_FAIL_NULL(p_physical_bone);
  129. bones.write[p_bone].physical_bone = p_physical_bone;
  130. _rebuild_physical_bones_cache();
  131. }
  132. void PhysicalBoneSimulator3D::unbind_physical_bone_from_bone(int p_bone) {
  133. const int bone_size = bones.size();
  134. ERR_FAIL_INDEX(p_bone, bone_size);
  135. bones.write[p_bone].physical_bone = nullptr;
  136. _rebuild_physical_bones_cache();
  137. }
  138. PhysicalBone3D *PhysicalBoneSimulator3D::get_physical_bone(int p_bone) {
  139. const int bone_size = bones.size();
  140. ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr);
  141. return bones[p_bone].physical_bone;
  142. }
  143. PhysicalBone3D *PhysicalBoneSimulator3D::get_physical_bone_parent(int p_bone) {
  144. const int bone_size = bones.size();
  145. ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr);
  146. if (bones[p_bone].cache_parent_physical_bone) {
  147. return bones[p_bone].cache_parent_physical_bone;
  148. }
  149. return _get_physical_bone_parent(p_bone);
  150. }
  151. PhysicalBone3D *PhysicalBoneSimulator3D::_get_physical_bone_parent(int p_bone) {
  152. const int bone_size = bones.size();
  153. ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr);
  154. const int parent_bone = bones[p_bone].parent;
  155. if (parent_bone < 0) {
  156. return nullptr;
  157. }
  158. PhysicalBone3D *pb = bones[parent_bone].physical_bone;
  159. if (pb) {
  160. return pb;
  161. } else {
  162. return get_physical_bone_parent(parent_bone);
  163. }
  164. }
  165. void PhysicalBoneSimulator3D::_rebuild_physical_bones_cache() {
  166. const int b_size = bones.size();
  167. for (int i = 0; i < b_size; ++i) {
  168. PhysicalBone3D *parent_pb = _get_physical_bone_parent(i);
  169. if (parent_pb != bones[i].cache_parent_physical_bone) {
  170. bones.write[i].cache_parent_physical_bone = parent_pb;
  171. if (bones[i].physical_bone) {
  172. bones[i].physical_bone->_on_bone_parent_changed();
  173. }
  174. }
  175. }
  176. }
  177. #ifndef DISABLE_DEPRECATED
  178. void _pb_stop_simulation_compat(Node *p_node) {
  179. PhysicalBoneSimulator3D *ps = Object::cast_to<PhysicalBoneSimulator3D>(p_node);
  180. if (ps) {
  181. return; // Prevent conflict.
  182. }
  183. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  184. _pb_stop_simulation_compat(p_node->get_child(i));
  185. }
  186. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
  187. if (pb) {
  188. pb->set_simulate_physics(false);
  189. }
  190. }
  191. #endif // _DISABLE_DEPRECATED
  192. void _pb_stop_simulation(Node *p_node) {
  193. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  194. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node->get_child(i));
  195. if (!pb) {
  196. continue;
  197. }
  198. _pb_stop_simulation(pb);
  199. }
  200. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
  201. if (pb) {
  202. pb->set_simulate_physics(false);
  203. }
  204. }
  205. void PhysicalBoneSimulator3D::physical_bones_stop_simulation() {
  206. simulating = false;
  207. _reset_physical_bones_state();
  208. #ifndef DISABLE_DEPRECATED
  209. if (is_compat) {
  210. Skeleton3D *sk = get_skeleton();
  211. if (sk) {
  212. _pb_stop_simulation_compat(sk);
  213. }
  214. } else {
  215. _pb_stop_simulation(this);
  216. }
  217. #else
  218. _pb_stop_simulation(this);
  219. #endif // _DISABLE_DEPRECATED
  220. }
  221. #ifndef DISABLE_DEPRECATED
  222. void _pb_start_simulation_compat(const PhysicalBoneSimulator3D *p_simulator, Node *p_node, const Vector<int> &p_sim_bones) {
  223. PhysicalBoneSimulator3D *ps = Object::cast_to<PhysicalBoneSimulator3D>(p_node);
  224. if (ps) {
  225. return; // Prevent conflict.
  226. }
  227. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  228. _pb_start_simulation_compat(p_simulator, p_node->get_child(i), p_sim_bones);
  229. }
  230. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
  231. if (pb) {
  232. if (p_sim_bones.is_empty()) { // If no bones are specified, activate ragdoll on full body.
  233. pb->set_simulate_physics(true);
  234. } else {
  235. for (int i = p_sim_bones.size() - 1; i >= 0; --i) {
  236. if (p_sim_bones[i] == pb->get_bone_id() || p_simulator->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
  237. pb->set_simulate_physics(true);
  238. break;
  239. }
  240. }
  241. }
  242. }
  243. }
  244. #endif // _DISABLE_DEPRECATED
  245. void _pb_start_simulation(const PhysicalBoneSimulator3D *p_simulator, Node *p_node, const Vector<int> &p_sim_bones) {
  246. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  247. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node->get_child(i));
  248. if (!pb) {
  249. continue;
  250. }
  251. _pb_start_simulation(p_simulator, pb, p_sim_bones);
  252. }
  253. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
  254. if (pb) {
  255. if (p_sim_bones.is_empty()) { // If no bones are specified, activate ragdoll on full body.
  256. pb->set_simulate_physics(true);
  257. } else {
  258. for (int i = p_sim_bones.size() - 1; i >= 0; --i) {
  259. if (p_sim_bones[i] == pb->get_bone_id() || p_simulator->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
  260. pb->set_simulate_physics(true);
  261. break;
  262. }
  263. }
  264. }
  265. }
  266. }
  267. void PhysicalBoneSimulator3D::physical_bones_start_simulation_on(const TypedArray<StringName> &p_bones) {
  268. _pose_updated();
  269. simulating = true;
  270. _reset_physical_bones_state();
  271. Vector<int> sim_bones;
  272. if (p_bones.size() > 0) {
  273. sim_bones.resize(p_bones.size());
  274. int c = 0;
  275. for (int i = sim_bones.size() - 1; i >= 0; --i) {
  276. int bone_id = find_bone(p_bones[i]);
  277. if (bone_id != -1) {
  278. sim_bones.write[c++] = bone_id;
  279. }
  280. }
  281. sim_bones.resize(c);
  282. }
  283. #ifndef DISABLE_DEPRECATED
  284. if (is_compat) {
  285. Skeleton3D *sk = get_skeleton();
  286. if (sk) {
  287. _pb_start_simulation_compat(this, sk, sim_bones);
  288. }
  289. } else {
  290. _pb_start_simulation(this, this, sim_bones);
  291. }
  292. #else
  293. _pb_start_simulation(this, this, sim_bones);
  294. #endif // _DISABLE_DEPRECATED
  295. }
  296. void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) {
  297. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  298. _physical_bones_add_remove_collision_exception(p_add, p_node->get_child(i), p_exception);
  299. }
  300. CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_node);
  301. if (co) {
  302. if (p_add) {
  303. PhysicsServer3D::get_singleton()->body_add_collision_exception(co->get_rid(), p_exception);
  304. } else {
  305. PhysicsServer3D::get_singleton()->body_remove_collision_exception(co->get_rid(), p_exception);
  306. }
  307. }
  308. }
  309. void PhysicalBoneSimulator3D::physical_bones_add_collision_exception(RID p_exception) {
  310. _physical_bones_add_remove_collision_exception(true, this, p_exception);
  311. }
  312. void PhysicalBoneSimulator3D::physical_bones_remove_collision_exception(RID p_exception) {
  313. _physical_bones_add_remove_collision_exception(false, this, p_exception);
  314. }
  315. Transform3D PhysicalBoneSimulator3D::get_bone_global_pose(int p_bone) const {
  316. const int bone_size = bones.size();
  317. ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D());
  318. return bones[p_bone].global_pose;
  319. }
  320. void PhysicalBoneSimulator3D::set_bone_global_pose(int p_bone, const Transform3D &p_pose) {
  321. const int bone_size = bones.size();
  322. ERR_FAIL_INDEX(p_bone, bone_size);
  323. bones.write[p_bone].global_pose = p_pose;
  324. }
  325. void PhysicalBoneSimulator3D::_process_modification(double p_delta) {
  326. Skeleton3D *skeleton = get_skeleton();
  327. if (!skeleton) {
  328. return;
  329. }
  330. ERR_FAIL_COND(skeleton->get_bone_count() != bones.size());
  331. for (int i = 0; i < skeleton->get_bone_count(); i++) {
  332. if (!bones[i].physical_bone) {
  333. continue;
  334. }
  335. if (bones[i].physical_bone->is_simulating_physics() == false) {
  336. _bone_pose_updated(skeleton, i);
  337. bones[i].physical_bone->reset_to_rest_position();
  338. } else if (simulating) {
  339. skeleton->set_bone_global_pose(i, bones[i].global_pose);
  340. }
  341. }
  342. }
  343. void PhysicalBoneSimulator3D::_bind_methods() {
  344. ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBoneSimulator3D::is_simulating_physics);
  345. ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &PhysicalBoneSimulator3D::physical_bones_stop_simulation);
  346. ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &PhysicalBoneSimulator3D::physical_bones_start_simulation_on, DEFVAL(Array()));
  347. ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &PhysicalBoneSimulator3D::physical_bones_add_collision_exception);
  348. ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &PhysicalBoneSimulator3D::physical_bones_remove_collision_exception);
  349. }
  350. PhysicalBoneSimulator3D::PhysicalBoneSimulator3D() {
  351. }