soft_body_bullet.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /*************************************************************************/
  2. /* soft_body_bullet.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2021 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. #include "soft_body_bullet.h"
  31. #include "bullet_types_converter.h"
  32. #include "bullet_utilities.h"
  33. #include "scene/3d/soft_body_3d.h"
  34. #include "space_bullet.h"
  35. SoftBodyBullet::SoftBodyBullet() :
  36. CollisionObjectBullet(CollisionObjectBullet::TYPE_SOFT_BODY) {}
  37. SoftBodyBullet::~SoftBodyBullet() {
  38. }
  39. void SoftBodyBullet::reload_body() {
  40. if (space) {
  41. space->remove_soft_body(this);
  42. space->add_soft_body(this);
  43. }
  44. }
  45. void SoftBodyBullet::set_space(SpaceBullet *p_space) {
  46. if (space) {
  47. isScratched = false;
  48. space->remove_soft_body(this);
  49. }
  50. space = p_space;
  51. if (space) {
  52. space->add_soft_body(this);
  53. }
  54. }
  55. void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {}
  56. void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {}
  57. void SoftBodyBullet::update_rendering_server(SoftBodyRenderingServerHandler *p_rendering_server_handler) {
  58. if (!bt_soft_body) {
  59. return;
  60. }
  61. /// Update visual server vertices
  62. const btSoftBody::tNodeArray &nodes(bt_soft_body->m_nodes);
  63. const int nodes_count = nodes.size();
  64. const Vector<int> *vs_indices;
  65. const void *vertex_position;
  66. const void *vertex_normal;
  67. for (int vertex_index = 0; vertex_index < nodes_count; ++vertex_index) {
  68. vertex_position = reinterpret_cast<const void *>(&nodes[vertex_index].m_x);
  69. vertex_normal = reinterpret_cast<const void *>(&nodes[vertex_index].m_n);
  70. vs_indices = &indices_table[vertex_index];
  71. const int vs_indices_size(vs_indices->size());
  72. for (int x = 0; x < vs_indices_size; ++x) {
  73. p_rendering_server_handler->set_vertex((*vs_indices)[x], vertex_position);
  74. p_rendering_server_handler->set_normal((*vs_indices)[x], vertex_normal);
  75. }
  76. }
  77. /// Generate AABB
  78. btVector3 aabb_min;
  79. btVector3 aabb_max;
  80. bt_soft_body->getAabb(aabb_min, aabb_max);
  81. btVector3 size(aabb_max - aabb_min);
  82. AABB aabb;
  83. B_TO_G(aabb_min, aabb.position);
  84. B_TO_G(size, aabb.size);
  85. p_rendering_server_handler->set_aabb(aabb);
  86. }
  87. void SoftBodyBullet::set_soft_mesh(const Ref<Mesh> &p_mesh) {
  88. if (p_mesh.is_null()) {
  89. soft_mesh.unref();
  90. } else {
  91. soft_mesh = p_mesh;
  92. }
  93. if (soft_mesh.is_null()) {
  94. destroy_soft_body();
  95. return;
  96. }
  97. Array arrays = soft_mesh->surface_get_arrays(0);
  98. ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & RS::ARRAY_FORMAT_INDEX));
  99. set_trimesh_body_shape(arrays[RS::ARRAY_INDEX], arrays[RS::ARRAY_VERTEX]);
  100. }
  101. void SoftBodyBullet::destroy_soft_body() {
  102. if (!bt_soft_body) {
  103. return;
  104. }
  105. if (space) {
  106. /// Remove from world before deletion
  107. space->remove_soft_body(this);
  108. }
  109. destroyBulletCollisionObject();
  110. bt_soft_body = nullptr;
  111. }
  112. void SoftBodyBullet::set_soft_transform(const Transform &p_transform) {
  113. reset_all_node_positions();
  114. move_all_nodes(p_transform);
  115. }
  116. void SoftBodyBullet::move_all_nodes(const Transform &p_transform) {
  117. if (!bt_soft_body) {
  118. return;
  119. }
  120. btTransform bt_transf;
  121. G_TO_B(p_transform, bt_transf);
  122. bt_soft_body->transform(bt_transf);
  123. }
  124. void SoftBodyBullet::set_node_position(int p_node_index, const Vector3 &p_global_position) {
  125. btVector3 bt_pos;
  126. G_TO_B(p_global_position, bt_pos);
  127. set_node_position(p_node_index, bt_pos);
  128. }
  129. void SoftBodyBullet::set_node_position(int p_node_index, const btVector3 &p_global_position) {
  130. if (bt_soft_body) {
  131. bt_soft_body->m_nodes[p_node_index].m_q = bt_soft_body->m_nodes[p_node_index].m_x;
  132. bt_soft_body->m_nodes[p_node_index].m_x = p_global_position;
  133. }
  134. }
  135. void SoftBodyBullet::get_node_position(int p_node_index, Vector3 &r_position) const {
  136. if (bt_soft_body) {
  137. B_TO_G(bt_soft_body->m_nodes[p_node_index].m_x, r_position);
  138. }
  139. }
  140. void SoftBodyBullet::get_node_offset(int p_node_index, Vector3 &r_offset) const {
  141. if (soft_mesh.is_null()) {
  142. return;
  143. }
  144. Array arrays = soft_mesh->surface_get_arrays(0);
  145. Vector<Vector3> vertices(arrays[RS::ARRAY_VERTEX]);
  146. if (0 <= p_node_index && vertices.size() > p_node_index) {
  147. r_offset = vertices[p_node_index];
  148. }
  149. }
  150. void SoftBodyBullet::get_node_offset(int p_node_index, btVector3 &r_offset) const {
  151. Vector3 off;
  152. get_node_offset(p_node_index, off);
  153. G_TO_B(off, r_offset);
  154. }
  155. void SoftBodyBullet::set_node_mass(int node_index, btScalar p_mass) {
  156. if (0 >= p_mass) {
  157. pin_node(node_index);
  158. } else {
  159. unpin_node(node_index);
  160. }
  161. if (bt_soft_body) {
  162. bt_soft_body->setMass(node_index, p_mass);
  163. }
  164. }
  165. btScalar SoftBodyBullet::get_node_mass(int node_index) const {
  166. if (bt_soft_body) {
  167. return bt_soft_body->getMass(node_index);
  168. } else {
  169. return -1 == search_node_pinned(node_index) ? 1 : 0;
  170. }
  171. }
  172. void SoftBodyBullet::reset_all_node_mass() {
  173. if (bt_soft_body) {
  174. for (int i = pinned_nodes.size() - 1; 0 <= i; --i) {
  175. bt_soft_body->setMass(pinned_nodes[i], 1);
  176. }
  177. }
  178. pinned_nodes.resize(0);
  179. }
  180. void SoftBodyBullet::reset_all_node_positions() {
  181. if (soft_mesh.is_null()) {
  182. return;
  183. }
  184. Array arrays = soft_mesh->surface_get_arrays(0);
  185. Vector<Vector3> vs_vertices(arrays[RS::ARRAY_VERTEX]);
  186. const Vector3 *vs_vertices_read = vs_vertices.ptr();
  187. for (int vertex_index = bt_soft_body->m_nodes.size() - 1; 0 <= vertex_index; --vertex_index) {
  188. G_TO_B(vs_vertices_read[indices_table[vertex_index][0]], bt_soft_body->m_nodes[vertex_index].m_x);
  189. bt_soft_body->m_nodes[vertex_index].m_q = bt_soft_body->m_nodes[vertex_index].m_x;
  190. bt_soft_body->m_nodes[vertex_index].m_v = btVector3(0, 0, 0);
  191. bt_soft_body->m_nodes[vertex_index].m_f = btVector3(0, 0, 0);
  192. }
  193. }
  194. void SoftBodyBullet::set_activation_state(bool p_active) {
  195. if (p_active) {
  196. bt_soft_body->setActivationState(ACTIVE_TAG);
  197. } else {
  198. bt_soft_body->setActivationState(WANTS_DEACTIVATION);
  199. }
  200. }
  201. void SoftBodyBullet::set_total_mass(real_t p_val) {
  202. if (0 >= p_val) {
  203. p_val = 1;
  204. }
  205. total_mass = p_val;
  206. if (bt_soft_body) {
  207. bt_soft_body->setTotalMass(total_mass);
  208. }
  209. }
  210. void SoftBodyBullet::set_linear_stiffness(real_t p_val) {
  211. linear_stiffness = p_val;
  212. if (bt_soft_body) {
  213. mat0->m_kLST = linear_stiffness;
  214. }
  215. }
  216. void SoftBodyBullet::set_angular_stiffness(real_t p_val) {
  217. angular_stiffness = p_val;
  218. if (bt_soft_body) {
  219. mat0->m_kAST = angular_stiffness;
  220. }
  221. }
  222. void SoftBodyBullet::set_volume_stiffness(real_t p_val) {
  223. volume_stiffness = p_val;
  224. if (bt_soft_body) {
  225. mat0->m_kVST = volume_stiffness;
  226. }
  227. }
  228. void SoftBodyBullet::set_simulation_precision(int p_val) {
  229. simulation_precision = p_val;
  230. if (bt_soft_body) {
  231. bt_soft_body->m_cfg.piterations = simulation_precision;
  232. bt_soft_body->m_cfg.viterations = simulation_precision;
  233. bt_soft_body->m_cfg.diterations = simulation_precision;
  234. bt_soft_body->m_cfg.citerations = simulation_precision;
  235. }
  236. }
  237. void SoftBodyBullet::set_pressure_coefficient(real_t p_val) {
  238. pressure_coefficient = p_val;
  239. if (bt_soft_body) {
  240. bt_soft_body->m_cfg.kPR = pressure_coefficient;
  241. }
  242. }
  243. void SoftBodyBullet::set_pose_matching_coefficient(real_t p_val) {
  244. pose_matching_coefficient = p_val;
  245. if (bt_soft_body) {
  246. bt_soft_body->m_cfg.kMT = pose_matching_coefficient;
  247. }
  248. }
  249. void SoftBodyBullet::set_damping_coefficient(real_t p_val) {
  250. damping_coefficient = p_val;
  251. if (bt_soft_body) {
  252. bt_soft_body->m_cfg.kDP = damping_coefficient;
  253. }
  254. }
  255. void SoftBodyBullet::set_drag_coefficient(real_t p_val) {
  256. drag_coefficient = p_val;
  257. if (bt_soft_body) {
  258. bt_soft_body->m_cfg.kDG = drag_coefficient;
  259. }
  260. }
  261. void SoftBodyBullet::set_trimesh_body_shape(Vector<int> p_indices, Vector<Vector3> p_vertices) {
  262. /// Assert the current soft body is destroyed
  263. destroy_soft_body();
  264. /// Parse visual server indices to physical indices.
  265. /// Merge all overlapping vertices and create a map of physical vertices to visual server
  266. {
  267. /// This is the map of visual server indices to physics indices (So it's the inverse of idices_map), Thanks to it I don't need make a heavy search in the indices_map
  268. Vector<int> vs_indices_to_physics_table;
  269. { // Map vertices
  270. indices_table.resize(0);
  271. int index = 0;
  272. Map<Vector3, int> unique_vertices;
  273. const int vs_vertices_size(p_vertices.size());
  274. const Vector3 *p_vertices_read = p_vertices.ptr();
  275. for (int vs_vertex_index = 0; vs_vertex_index < vs_vertices_size; ++vs_vertex_index) {
  276. Map<Vector3, int>::Element *e = unique_vertices.find(p_vertices_read[vs_vertex_index]);
  277. int vertex_id;
  278. if (e) {
  279. // Already rxisting
  280. vertex_id = e->value();
  281. } else {
  282. // Create new one
  283. unique_vertices[p_vertices_read[vs_vertex_index]] = vertex_id = index++;
  284. indices_table.push_back(Vector<int>());
  285. }
  286. indices_table.write[vertex_id].push_back(vs_vertex_index);
  287. vs_indices_to_physics_table.push_back(vertex_id);
  288. }
  289. }
  290. const int indices_map_size(indices_table.size());
  291. Vector<btScalar> bt_vertices;
  292. { // Parse vertices to bullet
  293. bt_vertices.resize(indices_map_size * 3);
  294. const Vector3 *p_vertices_read = p_vertices.ptr();
  295. for (int i = 0; i < indices_map_size; ++i) {
  296. bt_vertices.write[3 * i + 0] = p_vertices_read[indices_table[i][0]].x;
  297. bt_vertices.write[3 * i + 1] = p_vertices_read[indices_table[i][0]].y;
  298. bt_vertices.write[3 * i + 2] = p_vertices_read[indices_table[i][0]].z;
  299. }
  300. }
  301. Vector<int> bt_triangles;
  302. const int triangles_size(p_indices.size() / 3);
  303. { // Parse indices
  304. bt_triangles.resize(triangles_size * 3);
  305. const int *p_indices_read = p_indices.ptr();
  306. for (int i = 0; i < triangles_size; ++i) {
  307. bt_triangles.write[3 * i + 0] = vs_indices_to_physics_table[p_indices_read[3 * i + 2]];
  308. bt_triangles.write[3 * i + 1] = vs_indices_to_physics_table[p_indices_read[3 * i + 1]];
  309. bt_triangles.write[3 * i + 2] = vs_indices_to_physics_table[p_indices_read[3 * i + 0]];
  310. }
  311. }
  312. btSoftBodyWorldInfo fake_world_info;
  313. bt_soft_body = btSoftBodyHelpers::CreateFromTriMesh(fake_world_info, &bt_vertices[0], &bt_triangles[0], triangles_size, false);
  314. setup_soft_body();
  315. }
  316. }
  317. void SoftBodyBullet::setup_soft_body() {
  318. if (!bt_soft_body) {
  319. return;
  320. }
  321. // Soft body setup
  322. setupBulletCollisionObject(bt_soft_body);
  323. bt_soft_body->m_worldInfo = nullptr; // Remove fake world info
  324. bt_soft_body->getCollisionShape()->setMargin(0.01);
  325. bt_soft_body->setCollisionFlags(bt_soft_body->getCollisionFlags() & (~(btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT)));
  326. // Space setup
  327. if (space) {
  328. space->add_soft_body(this);
  329. }
  330. mat0 = bt_soft_body->appendMaterial();
  331. // Assign soft body data
  332. bt_soft_body->generateBendingConstraints(2, mat0);
  333. mat0->m_kLST = linear_stiffness;
  334. mat0->m_kAST = angular_stiffness;
  335. mat0->m_kVST = volume_stiffness;
  336. // Clusters allow to have Soft vs Soft collision but doesn't work well right now
  337. //bt_soft_body->m_cfg.kSRHR_CL = 1;// Soft vs rigid hardness [0,1] (cluster only)
  338. //bt_soft_body->m_cfg.kSKHR_CL = 1;// Soft vs kinematic hardness [0,1] (cluster only)
  339. //bt_soft_body->m_cfg.kSSHR_CL = 1;// Soft vs soft hardness [0,1] (cluster only)
  340. //bt_soft_body->m_cfg.kSR_SPLT_CL = 1; // Soft vs rigid impulse split [0,1] (cluster only)
  341. //bt_soft_body->m_cfg.kSK_SPLT_CL = 1; // Soft vs kinematic impulse split [0,1] (cluster only)
  342. //bt_soft_body->m_cfg.kSS_SPLT_CL = 1; // Soft vs Soft impulse split [0,1] (cluster only)
  343. //bt_soft_body->m_cfg.collisions = btSoftBody::fCollision::CL_SS + btSoftBody::fCollision::CL_RS + btSoftBody::fCollision::VF_SS;
  344. //bt_soft_body->generateClusters(64);
  345. bt_soft_body->m_cfg.piterations = simulation_precision;
  346. bt_soft_body->m_cfg.viterations = simulation_precision;
  347. bt_soft_body->m_cfg.diterations = simulation_precision;
  348. bt_soft_body->m_cfg.citerations = simulation_precision;
  349. bt_soft_body->m_cfg.kDP = damping_coefficient;
  350. bt_soft_body->m_cfg.kDG = drag_coefficient;
  351. bt_soft_body->m_cfg.kPR = pressure_coefficient;
  352. bt_soft_body->m_cfg.kMT = pose_matching_coefficient;
  353. bt_soft_body->setTotalMass(total_mass);
  354. btSoftBodyHelpers::ReoptimizeLinkOrder(bt_soft_body);
  355. bt_soft_body->updateBounds();
  356. // Set pinned nodes
  357. for (int i = pinned_nodes.size() - 1; 0 <= i; --i) {
  358. bt_soft_body->setMass(pinned_nodes[i], 0);
  359. }
  360. }
  361. void SoftBodyBullet::pin_node(int p_node_index) {
  362. if (-1 == search_node_pinned(p_node_index)) {
  363. pinned_nodes.push_back(p_node_index);
  364. }
  365. }
  366. void SoftBodyBullet::unpin_node(int p_node_index) {
  367. const int id = search_node_pinned(p_node_index);
  368. if (-1 != id) {
  369. pinned_nodes.remove(id);
  370. }
  371. }
  372. int SoftBodyBullet::search_node_pinned(int p_node_index) const {
  373. for (int i = pinned_nodes.size() - 1; 0 <= i; --i) {
  374. if (p_node_index == pinned_nodes[i]) {
  375. return i;
  376. }
  377. }
  378. return -1;
  379. }