123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- #include "soft_body_bullet.h"
- #include "bullet_types_converter.h"
- #include "bullet_utilities.h"
- #include "scene/3d/soft_body.h"
- #include "space_bullet.h"
- SoftBodyBullet::SoftBodyBullet() :
- CollisionObjectBullet(CollisionObjectBullet::TYPE_SOFT_BODY),
- bt_soft_body(NULL),
- isScratched(false),
- simulation_precision(5),
- total_mass(1.),
- linear_stiffness(0.5),
- areaAngular_stiffness(0.5),
- volume_stiffness(0.5),
- pressure_coefficient(0.),
- pose_matching_coefficient(0.),
- damping_coefficient(0.01),
- drag_coefficient(0.) {}
- SoftBodyBullet::~SoftBodyBullet() {
- }
- void SoftBodyBullet::reload_body() {
- if (space) {
- space->remove_soft_body(this);
- space->add_soft_body(this);
- }
- }
- void SoftBodyBullet::set_space(SpaceBullet *p_space) {
- if (space) {
- isScratched = false;
- space->remove_soft_body(this);
- }
- space = p_space;
- if (space) {
- space->add_soft_body(this);
- }
- }
- void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {}
- void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {}
- void SoftBodyBullet::update_visual_server(SoftBodyVisualServerHandler *p_visual_server_handler) {
- if (!bt_soft_body)
- return;
-
- const btSoftBody::tNodeArray &nodes(bt_soft_body->m_nodes);
- const int nodes_count = nodes.size();
- const Vector<int> *vs_indices;
- const void *vertex_position;
- const void *vertex_normal;
- for (int vertex_index = 0; vertex_index < nodes_count; ++vertex_index) {
- vertex_position = reinterpret_cast<const void *>(&nodes[vertex_index].m_x);
- vertex_normal = reinterpret_cast<const void *>(&nodes[vertex_index].m_n);
- vs_indices = &indices_table[vertex_index];
- const int vs_indices_size(vs_indices->size());
- for (int x = 0; x < vs_indices_size; ++x) {
- p_visual_server_handler->set_vertex((*vs_indices)[x], vertex_position);
- p_visual_server_handler->set_normal((*vs_indices)[x], vertex_normal);
- }
- }
-
- btVector3 aabb_min;
- btVector3 aabb_max;
- bt_soft_body->getAabb(aabb_min, aabb_max);
- btVector3 size(aabb_max - aabb_min);
- AABB aabb;
- B_TO_G(aabb_min, aabb.position);
- B_TO_G(size, aabb.size);
- p_visual_server_handler->set_aabb(aabb);
- }
- void SoftBodyBullet::set_soft_mesh(const Ref<Mesh> &p_mesh) {
- if (p_mesh.is_null())
- soft_mesh.unref();
- else
- soft_mesh = p_mesh;
- if (soft_mesh.is_null()) {
- destroy_soft_body();
- return;
- }
- Array arrays = soft_mesh->surface_get_arrays(0);
- ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & VS::ARRAY_FORMAT_INDEX));
- set_trimesh_body_shape(arrays[VS::ARRAY_INDEX], arrays[VS::ARRAY_VERTEX]);
- }
- void SoftBodyBullet::destroy_soft_body() {
- if (!bt_soft_body)
- return;
- if (space) {
-
- space->remove_soft_body(this);
- }
- destroyBulletCollisionObject();
- bt_soft_body = NULL;
- }
- void SoftBodyBullet::set_soft_transform(const Transform &p_transform) {
- reset_all_node_positions();
- move_all_nodes(p_transform);
- }
- void SoftBodyBullet::move_all_nodes(const Transform &p_transform) {
- if (!bt_soft_body)
- return;
- btTransform bt_transf;
- G_TO_B(p_transform, bt_transf);
- bt_soft_body->transform(bt_transf);
- }
- void SoftBodyBullet::set_node_position(int p_node_index, const Vector3 &p_global_position) {
- btVector3 bt_pos;
- G_TO_B(p_global_position, bt_pos);
- set_node_position(p_node_index, bt_pos);
- }
- void SoftBodyBullet::set_node_position(int p_node_index, const btVector3 &p_global_position) {
- if (bt_soft_body) {
- bt_soft_body->m_nodes[p_node_index].m_x = p_global_position;
- }
- }
- void SoftBodyBullet::get_node_position(int p_node_index, Vector3 &r_position) const {
- if (bt_soft_body) {
- B_TO_G(bt_soft_body->m_nodes[p_node_index].m_x, r_position);
- }
- }
- void SoftBodyBullet::get_node_offset(int p_node_index, Vector3 &r_offset) const {
- if (soft_mesh.is_null())
- return;
- Array arrays = soft_mesh->surface_get_arrays(0);
- PoolVector<Vector3> vertices(arrays[VS::ARRAY_VERTEX]);
- if (0 <= p_node_index && vertices.size() > p_node_index) {
- r_offset = vertices[p_node_index];
- }
- }
- void SoftBodyBullet::get_node_offset(int p_node_index, btVector3 &r_offset) const {
- Vector3 off;
- get_node_offset(p_node_index, off);
- G_TO_B(off, r_offset);
- }
- void SoftBodyBullet::set_node_mass(int node_index, btScalar p_mass) {
- if (0 >= p_mass) {
- pin_node(node_index);
- } else {
- unpin_node(node_index);
- }
- if (bt_soft_body) {
- bt_soft_body->setMass(node_index, p_mass);
- }
- }
- btScalar SoftBodyBullet::get_node_mass(int node_index) const {
- if (bt_soft_body) {
- return bt_soft_body->getMass(node_index);
- } else {
- return -1 == search_node_pinned(node_index) ? 1 : 0;
- }
- }
- void SoftBodyBullet::reset_all_node_mass() {
- if (bt_soft_body) {
- for (int i = pinned_nodes.size() - 1; 0 <= i; --i) {
- bt_soft_body->setMass(pinned_nodes[i], 1);
- }
- }
- pinned_nodes.resize(0);
- }
- void SoftBodyBullet::reset_all_node_positions() {
- if (soft_mesh.is_null())
- return;
- Array arrays = soft_mesh->surface_get_arrays(0);
- PoolVector<Vector3> vs_vertices(arrays[VS::ARRAY_VERTEX]);
- PoolVector<Vector3>::Read vs_vertices_read = vs_vertices.read();
- for (int vertex_index = bt_soft_body->m_nodes.size() - 1; 0 <= vertex_index; --vertex_index) {
- G_TO_B(vs_vertices_read[indices_table[vertex_index][0]], bt_soft_body->m_nodes[vertex_index].m_x);
- bt_soft_body->m_nodes[vertex_index].m_q = bt_soft_body->m_nodes[vertex_index].m_x;
- bt_soft_body->m_nodes[vertex_index].m_v = btVector3(0, 0, 0);
- bt_soft_body->m_nodes[vertex_index].m_f = btVector3(0, 0, 0);
- }
- }
- void SoftBodyBullet::set_activation_state(bool p_active) {
- if (p_active) {
- bt_soft_body->setActivationState(ACTIVE_TAG);
- } else {
- bt_soft_body->setActivationState(WANTS_DEACTIVATION);
- }
- }
- void SoftBodyBullet::set_total_mass(real_t p_val) {
- if (0 >= p_val) {
- p_val = 1;
- }
- total_mass = p_val;
- if (bt_soft_body) {
- bt_soft_body->setTotalMass(total_mass);
- }
- }
- void SoftBodyBullet::set_linear_stiffness(real_t p_val) {
- linear_stiffness = p_val;
- if (bt_soft_body) {
- mat0->m_kLST = linear_stiffness;
- }
- }
- void SoftBodyBullet::set_areaAngular_stiffness(real_t p_val) {
- areaAngular_stiffness = p_val;
- if (bt_soft_body) {
- mat0->m_kAST = areaAngular_stiffness;
- }
- }
- void SoftBodyBullet::set_volume_stiffness(real_t p_val) {
- volume_stiffness = p_val;
- if (bt_soft_body) {
- mat0->m_kVST = volume_stiffness;
- }
- }
- void SoftBodyBullet::set_simulation_precision(int p_val) {
- simulation_precision = p_val;
- if (bt_soft_body) {
- bt_soft_body->m_cfg.piterations = simulation_precision;
- bt_soft_body->m_cfg.viterations = simulation_precision;
- bt_soft_body->m_cfg.diterations = simulation_precision;
- bt_soft_body->m_cfg.citerations = simulation_precision;
- }
- }
- void SoftBodyBullet::set_pressure_coefficient(real_t p_val) {
- pressure_coefficient = p_val;
- if (bt_soft_body) {
- bt_soft_body->m_cfg.kPR = pressure_coefficient;
- }
- }
- void SoftBodyBullet::set_pose_matching_coefficient(real_t p_val) {
- pose_matching_coefficient = p_val;
- if (bt_soft_body) {
- bt_soft_body->m_cfg.kMT = pose_matching_coefficient;
- }
- }
- void SoftBodyBullet::set_damping_coefficient(real_t p_val) {
- damping_coefficient = p_val;
- if (bt_soft_body) {
- bt_soft_body->m_cfg.kDP = damping_coefficient;
- }
- }
- void SoftBodyBullet::set_drag_coefficient(real_t p_val) {
- drag_coefficient = p_val;
- if (bt_soft_body) {
- bt_soft_body->m_cfg.kDG = drag_coefficient;
- }
- }
- void SoftBodyBullet::set_trimesh_body_shape(PoolVector<int> p_indices, PoolVector<Vector3> p_vertices) {
-
- destroy_soft_body();
-
-
- {
-
- Vector<int> vs_indices_to_physics_table;
- {
- indices_table.resize(0);
- int index = 0;
- Map<Vector3, int> unique_vertices;
- const int vs_vertices_size(p_vertices.size());
- PoolVector<Vector3>::Read p_vertices_read = p_vertices.read();
- for (int vs_vertex_index = 0; vs_vertex_index < vs_vertices_size; ++vs_vertex_index) {
- Map<Vector3, int>::Element *e = unique_vertices.find(p_vertices_read[vs_vertex_index]);
- int vertex_id;
- if (e) {
-
- vertex_id = e->value();
- } else {
-
- unique_vertices[p_vertices_read[vs_vertex_index]] = vertex_id = index++;
- indices_table.push_back(Vector<int>());
- }
- indices_table.write[vertex_id].push_back(vs_vertex_index);
- vs_indices_to_physics_table.push_back(vertex_id);
- }
- }
- const int indices_map_size(indices_table.size());
- Vector<btScalar> bt_vertices;
- {
- bt_vertices.resize(indices_map_size * 3);
- PoolVector<Vector3>::Read p_vertices_read = p_vertices.read();
- for (int i = 0; i < indices_map_size; ++i) {
- bt_vertices.write[3 * i + 0] = p_vertices_read[indices_table[i][0]].x;
- bt_vertices.write[3 * i + 1] = p_vertices_read[indices_table[i][0]].y;
- bt_vertices.write[3 * i + 2] = p_vertices_read[indices_table[i][0]].z;
- }
- }
- Vector<int> bt_triangles;
- const int triangles_size(p_indices.size() / 3);
- {
- bt_triangles.resize(triangles_size * 3);
- PoolVector<int>::Read p_indices_read = p_indices.read();
- for (int i = 0; i < triangles_size; ++i) {
- bt_triangles.write[3 * i + 0] = vs_indices_to_physics_table[p_indices_read[3 * i + 2]];
- bt_triangles.write[3 * i + 1] = vs_indices_to_physics_table[p_indices_read[3 * i + 1]];
- bt_triangles.write[3 * i + 2] = vs_indices_to_physics_table[p_indices_read[3 * i + 0]];
- }
- }
- btSoftBodyWorldInfo fake_world_info;
- bt_soft_body = btSoftBodyHelpers::CreateFromTriMesh(fake_world_info, &bt_vertices[0], &bt_triangles[0], triangles_size, false);
- setup_soft_body();
- }
- }
- void SoftBodyBullet::setup_soft_body() {
- if (!bt_soft_body)
- return;
-
- setupBulletCollisionObject(bt_soft_body);
- bt_soft_body->m_worldInfo = NULL;
- bt_soft_body->getCollisionShape()->setMargin(0.01);
- bt_soft_body->setCollisionFlags(bt_soft_body->getCollisionFlags() & (~(btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT)));
-
- if (space) {
- space->add_soft_body(this);
- }
- mat0 = bt_soft_body->appendMaterial();
-
- bt_soft_body->generateBendingConstraints(2, mat0);
- mat0->m_kLST = linear_stiffness;
- mat0->m_kAST = areaAngular_stiffness;
- mat0->m_kVST = volume_stiffness;
-
-
-
-
-
-
-
-
-
- bt_soft_body->m_cfg.piterations = simulation_precision;
- bt_soft_body->m_cfg.viterations = simulation_precision;
- bt_soft_body->m_cfg.diterations = simulation_precision;
- bt_soft_body->m_cfg.citerations = simulation_precision;
- bt_soft_body->m_cfg.kDP = damping_coefficient;
- bt_soft_body->m_cfg.kDG = drag_coefficient;
- bt_soft_body->m_cfg.kPR = pressure_coefficient;
- bt_soft_body->m_cfg.kMT = pose_matching_coefficient;
- bt_soft_body->setTotalMass(total_mass);
- btSoftBodyHelpers::ReoptimizeLinkOrder(bt_soft_body);
- bt_soft_body->updateBounds();
-
- for (int i = pinned_nodes.size() - 1; 0 <= i; --i) {
- bt_soft_body->setMass(pinned_nodes[i], 0);
- }
- }
- void SoftBodyBullet::pin_node(int p_node_index) {
- if (-1 == search_node_pinned(p_node_index)) {
- pinned_nodes.push_back(p_node_index);
- }
- }
- void SoftBodyBullet::unpin_node(int p_node_index) {
- const int id = search_node_pinned(p_node_index);
- if (-1 != id) {
- pinned_nodes.remove(id);
- }
- }
- int SoftBodyBullet::search_node_pinned(int p_node_index) const {
- for (int i = pinned_nodes.size() - 1; 0 <= i; --i) {
- if (p_node_index == pinned_nodes[i]) {
- return i;
- }
- }
- return -1;
- }
|