From 3ecddb724a27d49f2e72df5ee704d73ce74d1a40 Mon Sep 17 00:00:00 2001 From: Leandro Dorileo Date: Wed, 12 Sep 2012 21:49:14 +0000 Subject: [PATCH] ephysics: softbody ** linear/angular joints: We don't need the linear and angular joints for soft bodies. Actually these joint's are pulling the soft body towards (0, 0, 0). The soft body is anchored with the rigid one, so limiting the rigid body angular and linear movements seems to be enough. ** soft body configs: Some soft body configurations were tweaked to fix issues of instability of soft bodies. ** soft body hardness API: Soft body hardness API was introduced as well. ** points of deformation: The points of deformation were inverted; ** soft body mass: Fixed issues with soft body mass changing, now it doesn't "explode" after changing its mass. Patch by: Leandro Dorileo SVN revision: 76560 --- legacy/ephysics/src/bin/test_soft_body.c | 2 + legacy/ephysics/src/lib/EPhysics.h | 34 +++++ legacy/ephysics/src/lib/ephysics_body.cpp | 172 +++++++++++++++------- 3 files changed, 151 insertions(+), 57 deletions(-) diff --git a/legacy/ephysics/src/bin/test_soft_body.c b/legacy/ephysics/src/bin/test_soft_body.c index ef54d154f4..4a73670a9e 100644 --- a/legacy/ephysics/src/bin/test_soft_body.c +++ b/legacy/ephysics/src/bin/test_soft_body.c @@ -51,6 +51,7 @@ _world_populate(Test_Data *test_data) test_data->evas_objs = eina_list_append(test_data->evas_objs, evas_obj); fall_body = ephysics_body_circle_add(test_data->world); + ephysics_body_mass_set(fall_body, 2); ephysics_body_evas_object_set(fall_body, evas_obj, EINA_TRUE); ephysics_body_restitution_set(fall_body, 0.95); ephysics_body_friction_set(fall_body, 0.1); @@ -75,6 +76,7 @@ _world_populate(Test_Data *test_data) test_data->evas_objs = eina_list_append(test_data->evas_objs, evas_obj); fall_body = ephysics_body_soft_box_add(test_data->world); + ephysics_body_soft_body_hardness_set(fall_body, 50); ephysics_body_evas_object_set(fall_body, evas_obj, EINA_TRUE); ephysics_body_event_callback_add(fall_body, EPHYSICS_CALLBACK_BODY_UPDATE, update_object_cb, shadow); diff --git a/legacy/ephysics/src/lib/EPhysics.h b/legacy/ephysics/src/lib/EPhysics.h index 76250b91fc..fa034690e4 100644 --- a/legacy/ephysics/src/lib/EPhysics.h +++ b/legacy/ephysics/src/lib/EPhysics.h @@ -1292,6 +1292,40 @@ typedef enum _EPhysics_Callback_Body_Type */ typedef void (*EPhysics_Body_Event_Cb)(void *data, EPhysics_Body *body, void *event_info); +/** + * @brief + * Set the soft body hardness percentage. + * + * The hardness percentage will define how the soft body is supposed to deform, + * its default is set to 100%. The soft body mass will also interfere on soft + * body deformation, so bare in mind that the bodies mass must also be changed to + * have different deformation results. + * + * Valid values vary from 0 to 100. + * + * @param body The body to be set. + * @param hardness The percentage of deformation. + * + * @see ephysics_body_soft_body_hardness_get() + * @see ephysics_body_mass_set() form body mass changing. + * + * @ingroup EPhysics_Body + */ +EAPI void ephysics_body_soft_body_hardness_set(EPhysics_Body *body, double hardness); + +/** + * @brief + * Get the soft body hardness percentage. + * + * @param body The body of interest. + * @return The deformation percentage. + * + * @see ephysics_body_soft_body_hardness_set() + * + * @ingroup EPhysics_Body + */ +EAPI double ephysics_body_soft_body_hardness_get(const EPhysics_Body *body); + /** * @brief * Create a new circle physics body. diff --git a/legacy/ephysics/src/lib/ephysics_body.cpp b/legacy/ephysics/src/lib/ephysics_body.cpp index 0cc3bf2607..ddf6a16da4 100644 --- a/legacy/ephysics/src/lib/ephysics_body.cpp +++ b/legacy/ephysics/src/lib/ephysics_body.cpp @@ -305,6 +305,41 @@ _ephysics_body_soft_body_points_distance_get(const EPhysics_Body *body, double d } } +static void +_ephysics_body_soft_body_anchors_rebuild(int node, btRigidBody *rigid_body, btSoftBody *soft_body) +{ + btTransform world_trans = rigid_body->getWorldTransform(); + btVector3 local = world_trans.inverse() * soft_body->m_nodes[node].m_x; + + for (int i = 0; i < soft_body->m_anchors.size(); i++) + { + if (soft_body->m_anchors[i].m_node == &soft_body->m_nodes[node]) + soft_body->m_anchors[i].m_local = local; + } +} + +static void +_ephysics_body_soft_body_constraints_rebuild(EPhysics_Body *body) +{ + btSoftBody *soft_body = body->soft_body; + btRigidBody *rigid_body = body->rigid_body; + + if (soft_body->m_anchors.size() > 0) + { + for (int i = 0; i < soft_body->m_nodes.size(); i++) + _ephysics_body_soft_body_anchors_rebuild(i, rigid_body, soft_body); + } + else + { + for (int i = 0; i < soft_body->m_nodes.size(); i++) + soft_body->appendAnchor(i, rigid_body); + } + + soft_body->generateClusters(0); + soft_body->generateBendingConstraints(10, soft_body->m_materials[0]); + _ephysics_body_soft_body_points_distance_get(body, body->distances); +} + static void _ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h) { @@ -316,13 +351,8 @@ _ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h) if (body->soft_body) { - body->soft_body->m_anchors.resize(0); body->soft_body->scale(btVector3(sx, sy, 1)); - - for (int i = 0; i < body->soft_body->m_nodes.size(); i++) - body->soft_body->appendAnchor(i, body->rigid_body); - - _ephysics_body_soft_body_points_distance_get(body, body->distances); + _ephysics_body_soft_body_constraints_rebuild(body); } else { @@ -387,15 +417,10 @@ _ephysics_body_geometry_set(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Eva body_scale = btVector3(sx, sy, 1); if (body->soft_body) { - body->soft_body->m_anchors.resize(0); body->soft_body->scale(btVector3(sx, sy, 1)); body->rigid_body->proceedToTransform(trans); body->soft_body->transform(trans); - - for (int i = 0; i < body->soft_body->m_nodes.size(); i++) - body->soft_body->appendAnchor(i, body->rigid_body); - - _ephysics_body_soft_body_points_distance_get(body, body->distances); + _ephysics_body_soft_body_constraints_rebuild(body); } else { @@ -682,12 +707,59 @@ ephysics_body_soft_body_get(const EPhysics_Body *body) return body->soft_body; } +EAPI void +ephysics_body_soft_body_hardness_set(EPhysics_Body *body, double hardness) +{ + btSoftBody *soft_body; + + if (!body) + { + ERR("Can't set soft body's hardness, body is null."); + return; + } + + if (!body->soft_body) + { + ERR("Can't set soft body's hardness, body seems not to be a soft body."); + return; + } + + if (hardness < 0 || hardness > 100) + { + ERR("Can't set soft body's hardness, it must be between 0 and 100."); + return; + } + + soft_body = body->soft_body; + soft_body->m_cfg.kAHR = (hardness / 100) * 0.6; + soft_body->m_materials[0]->m_kVST = (hardness / 100); + soft_body->m_materials[0]->m_kLST = (hardness / 100); + soft_body->m_materials[0]->m_kAST = (hardness / 100); + DBG("Soft body hardness set."); +} + +EAPI double +ephysics_body_soft_body_hardness_get(const EPhysics_Body *body) +{ + if (!body) + { + ERR("Can't get soft body's hardness, body is null."); + return 0; + } + + if (!body->soft_body) + { + ERR("Can't get soft body's hardness, body seems not to be a soft body."); + return 0; + } + + return (body->soft_body->m_materials[0]->m_kVST * 100); +} + static EPhysics_Body * _ephysics_body_soft_add(EPhysics_World *world, btCollisionShape *collision_shape, btSoftBody *soft_body) { EPhysics_Body *body; - btSoftBody::AJoint::Specs angular_joint; - btSoftBody::LJoint::Specs linear_joint; body = _ephysics_body_add(world, collision_shape, "soft box", 0.5, 0.5); if (!body) @@ -695,33 +767,19 @@ _ephysics_body_soft_add(EPhysics_World *world, btCollisionShape *collision_shape ephysics_body_del(body); return NULL; } - body->soft_body = soft_body; body->soft_body->setUserPointer(body); - - body->soft_body->getCollisionShape()->setMargin(0.22); - - soft_body->m_materials[0]->m_kLST = 0.35; - soft_body->setPose(true, false); + body->soft_body->setTotalMass(body->mass); body->soft_body->m_cfg.collisions += btSoftBody::fCollision::SDF_RS; - body->soft_body->m_cfg.collisions += btSoftBody::fCollision::CL_SS; + body->soft_body->m_cfg.collisions += btSoftBody::fCollision::VF_SS; - body->soft_body->generateClusters(body->soft_body->m_nodes.size()); + ephysics_body_soft_body_hardness_set(body, 100); - angular_joint.erp = 0.; - angular_joint.cfm = 0.; - angular_joint.axis = btVector3(0, 0, 1); - body->soft_body->appendAngularJoint(angular_joint); - - linear_joint.erp = 0.; - linear_joint.cfm = 0.; - linear_joint.position = btVector3(0, 0, 0); - body->soft_body->appendLinearJoint(linear_joint, body->rigid_body); - - for (int i = 0; i < body->soft_body->m_nodes.size(); i++) - body->soft_body->appendAnchor(i, body->rigid_body); + body->rigid_body->setCollisionFlags( + btCollisionObject::CF_NO_CONTACT_RESPONSE); + _ephysics_body_soft_body_constraints_rebuild(body); ephysics_world_soft_body_add(world, body); return body; } @@ -750,7 +808,7 @@ ephysics_body_soft_circle_add(EPhysics_World *world) world_info = ephysics_world_info_get(world); soft_body = btSoftBodyHelpers::CreateFromTriMesh(*world_info, cylinder_vertices, &cylinder_indices[0][0], - CYLINDER_NUM_TRIANGLES); + CYLINDER_NUM_TRIANGLES); if (!soft_body) { ERR("Couldn't create a new soft body."); @@ -762,20 +820,20 @@ ephysics_body_soft_circle_add(EPhysics_World *world) goto no_body; body->points_deform[0][0] = 72; - body->points_deform[0][1] = 6; - body->points_deform[0][2] = 65; + body->points_deform[0][1] = 69; + body->points_deform[0][2] = 3; body->points_deform[1][0] = 72; - body->points_deform[1][1] = 69; - body->points_deform[1][2] = 3; + body->points_deform[1][1] = 6; + body->points_deform[1][2] = 65; - body->points_deform[2][0] = 57; - body->points_deform[2][1] = 3; - body->points_deform[2][2] = 76; + body->points_deform[2][0] = 54; + body->points_deform[2][1] = 47; + body->points_deform[2][2] = 65; - body->points_deform[3][0] = 54; - body->points_deform[3][1] = 47; - body->points_deform[3][2] = 65; + body->points_deform[3][0] = 57; + body->points_deform[3][1] = 3; + body->points_deform[3][2] = 76; return body; @@ -843,21 +901,21 @@ ephysics_body_soft_box_add(EPhysics_World *world) if (!body) goto no_body; - body->points_deform[0][0] = 27; - body->points_deform[0][1] = 80; - body->points_deform[0][2] = 69; + body->points_deform[0][0] = 85; + body->points_deform[0][1] = 12; + body->points_deform[0][2] = 30; - body->points_deform[1][0] = 85; - body->points_deform[1][1] = 12; - body->points_deform[1][2] = 30; + body->points_deform[1][0] = 27; + body->points_deform[1][1] = 80; + body->points_deform[1][2] = 69; - body->points_deform[2][0] = 18; - body->points_deform[2][1] = 62; - body->points_deform[2][2] = 8; + body->points_deform[2][0] = 50; + body->points_deform[2][1] = 40; + body->points_deform[2][2] = 60; - body->points_deform[3][0] = 50; - body->points_deform[3][1] = 40; - body->points_deform[3][2] = 60; + body->points_deform[3][0] = 18; + body->points_deform[3][1] = 62; + body->points_deform[3][2] = 8; return body;