void SoftBodyBullet::reload_soft_body() { destroy_soft_body(); create_soft_body(); if (bt_soft_body) { // TODO the softbody set new transform considering the current transform as center of world // like if it's local transform, so I must fix this by setting nwe transform considering the old btTransform bt_trans; G_TO_B(transform, bt_trans); bt_soft_body->transform(bt_trans); bt_soft_body->generateBendingConstraints(2, mat0); mat0->m_kAST = stiffness; mat0->m_kLST = stiffness; mat0->m_kVST = stiffness; bt_soft_body->m_cfg.piterations = 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->setTotalMass(mass); } if (space) { // TODO remove this please space->add_soft_body(this); } }
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::set_trimesh_body_shape(PoolVector<int> p_indices, PoolVector<Vector3> p_vertices) { /// Assert the current soft body is destroyed destroy_soft_body(); /// Parse visual server indices to physical indices. /// Merge all overlapping vertices and create a map of physical vertices to visual server { /// 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 Vector<int> vs_indices_to_physics_table; { // Map vertices 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) { // Already rxisting vertex_id = e->value(); } else { // Create new one 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; { // Parse vertices to bullet 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); { // Parse indices 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(); } }