EPhysics: soft body dragging support

This patch introduces an API to freeze(dragging_set) an specific
soft body trimesh face untill it gets called to unfreeze(dragging_unset) it.


Patch by: Leandro Dorileo <dorileo@profusion.mobi>



SVN revision: 78091
This commit is contained in:
Leandro Dorileo 2012-10-16 23:18:21 +00:00 committed by Bruno Dilly
parent f4fa980cce
commit 56bdc31570
5 changed files with 156 additions and 6 deletions

View File

@ -35,12 +35,16 @@ _mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_inf
grabbing->click_data.y = mdown->output.y - y;
grabbing->click_data.node = ephysics_body_soft_body_triangle_index_get(
grabbing->body, mdown->output.x, mdown->output.y);
ephysics_body_soft_body_dragging_set(grabbing->body,
grabbing->click_data.node);
}
static void
_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
Grabbing_Data *grabbing = data;
ephysics_body_soft_body_dragging_unset(grabbing->body);
grabbing->mouse_status = 0;
}

View File

@ -1762,6 +1762,44 @@ EAPI void ephysics_body_soft_body_hardness_set(EPhysics_Body *body, double hardn
*/
EAPI double ephysics_body_soft_body_hardness_get(const EPhysics_Body *body);
/**
* @brief
* Set the soft body dragging status.
*
* While dragging a soft body the user may want to freeze a specific trimesh
* face, after calling this function EPhysics will do freeze the @p triangle
* untill it gets a call to unset it with
* ephysics_body_soft_body_dragging_unset().
*
* @note Freezing a specific trimesh face means no forces are applied to it, no
* gravity enforced, that's @p triangle will have no mass untill it dragging gets
* unset.
*
* @param body The body of interest.
* @param triangle The triangle to freeze.
*
* @see ephysics_body_soft_body_dragging_unset().
* @see ephysics_body_soft_body_triangle_index_get().
*
* @ingroup EPhysics_Body
*/
EAPI void ephysics_body_soft_body_dragging_set(EPhysics_Body *body, int triangle);
/**
* @brief
* Unset the soft body dragging status.
*
* This function will tell EPhysics to not freeze - the previously dragging
* triangle set - any more.
*
* @param body The body to unset the dragging status.
*
* @see ephysics_body_soft_body_dragging_set() for dragging details.
*
* @ingroup EPhysics_Body
*/
EAPI void ephysics_body_soft_body_dragging_unset(EPhysics_Body *body);
/**
* @brief
* Get the triangle index of a soft body in @p x and @p y.

View File

@ -780,6 +780,23 @@ _ephysics_body_volume_get(const EPhysics_Body *body)
return vector.x() * vector.y() * vector.z();
}
void
_ephysics_body_soft_body_dragging_set(EPhysics_Body *body, int triangle)
{
btSoftBody::Face face;
btSoftBody::Node *node;
body->dragging_data.triangle = triangle;
body->dragging_data.dragging = EINA_TRUE;
face = body->soft_body->m_faces[triangle];
for (int i = 0; i < 3; i++)
{
node = face.m_n[i];
body->dragging_data.mass[i] = node->m_im;
}
}
static void
_ephysics_body_mass_set(EPhysics_Body *body, double mass)
{
@ -789,7 +806,12 @@ _ephysics_body_mass_set(EPhysics_Body *body, double mass)
mass = body->density * _ephysics_body_volume_get(body);
if (body->soft_body)
body->soft_body->setTotalMass(mass);
{
body->soft_body->setTotalMass(mass);
if (body->dragging_data.dragging)
_ephysics_body_soft_body_dragging_set(body,
body->dragging_data.triangle);
}
else
{
body->collision_shape->calculateLocalInertia(mass, inertia);
@ -1232,6 +1254,68 @@ ephysics_body_soft_body_hardness_set(EPhysics_Body *body, double hardness)
ephysics_world_lock_release(body->world);
}
EAPI void
ephysics_body_soft_body_dragging_set(EPhysics_Body *body, int triangle)
{
if (!body)
{
ERR("Can't set soft body dragging status, body is null.");
return;
}
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
{
ERR("Can set soft body dragging status, body must not be a rigid body.");
return;
}
if (triangle < 0 || triangle >= body->soft_body->m_faces.size())
{
ERR("Could not move soft body triangle, provided body triangle index "
"ranges from 0 to %d", body->soft_body->m_faces.size());
return;
}
ephysics_world_lock_take(body->world);
_ephysics_body_soft_body_dragging_set(body, triangle);
ephysics_world_lock_release(body->world);
DBG("Body %p appended to world's dragging bodies list.", body);
}
EAPI void
ephysics_body_soft_body_dragging_unset(EPhysics_Body *body)
{
btSoftBody::Face face;
btSoftBody::Node *node;
if (!body)
{
ERR("Can't unset soft body dragging status, body is null.");
return;
}
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
{
ERR("Can unset soft body dragging status, body must not be a rigid"
" body.");
return;
}
ephysics_world_lock_take(body->world);
face = body->soft_body->m_faces[body->dragging_data.triangle];
for (int i = 0; i < 3; i++)
{
node = face.m_n[i];
node->m_im = body->dragging_data.mass[i];
body->dragging_data.mass[i] = 0;
}
body->dragging_data.dragging = EINA_FALSE;
body->dragging_data.triangle = 0;
ephysics_world_lock_release(body->world);
}
EAPI double
ephysics_body_soft_body_hardness_get(const EPhysics_Body *body)
{
@ -1448,7 +1532,7 @@ no_body:
}
static void
_ephysics_body_soft_body_single_face_transform(btSoftBody *soft_body, int face_idx, int node_idx, btTransform trans, btScalar vel_reduction)
_ephysics_body_soft_body_single_face_transform(btSoftBody *soft_body, int face_idx, int node_idx, btTransform trans)
{
btSoftBody::Node *node;
ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
@ -1458,11 +1542,25 @@ _ephysics_body_soft_body_single_face_transform(btSoftBody *soft_body, int face_i
node->m_x = trans * node->m_x;
node->m_q = trans * node->m_q;
node->m_n = trans.getBasis() * node->m_n;
node->m_v *= vel_reduction;
vol = btDbvtVolume::FromCR(node->m_x, margin);
soft_body->m_ndbvt.update(node->m_leaf, vol);
}
void
ephysics_body_soft_body_dragging_apply(EPhysics_Body *body)
{
btSoftBody::Face face;
btSoftBody::Node *node;
face = body->soft_body->m_faces[body->dragging_data.triangle];
for (int i = 0; i < 3; i++)
{
node = face.m_n[i];
node->m_v *= 0;
node->m_im *= 0;
}
}
EAPI void
ephysics_body_soft_body_triangle_move(EPhysics_Body *body, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
{
@ -1505,7 +1603,7 @@ ephysics_body_soft_body_triangle_move(EPhysics_Body *body, int idx, Evas_Coord x
diff.setIdentity();
diff.setOrigin(new_pos - node->m_x);
_ephysics_body_soft_body_single_face_transform(body->soft_body, idx, i,
diff, 0.25);
diff);
if (!i) continue;
@ -1514,7 +1612,7 @@ ephysics_body_soft_body_triangle_move(EPhysics_Body *body, int idx, Evas_Coord x
{
if (m == idx) continue;
_ephysics_body_soft_body_single_face_transform(body->soft_body, m,
i, diff, 0.05);
i, diff);
}
}

View File

@ -117,6 +117,11 @@ struct _EPhysics_Body {
Eina_Bool light_apply:1;
int material_index;
Eina_Bool rebounding;
struct {
int triangle;
double mass[3];
Eina_Bool dragging;
} dragging_data;
};
extern int _ephysics_log_dom;
@ -153,6 +158,7 @@ void ephysics_body_recalc(EPhysics_Body *body, double rate);
void ephysics_body_forces_apply(EPhysics_Body *body);
void ephysics_body_activate(const EPhysics_Body *body, Eina_Bool activate);
void ephysics_body_evas_objects_restack(EPhysics_World *world);
void ephysics_body_soft_body_dragging_apply(EPhysics_Body *body);
/* Camera */
EPhysics_Camera *ephysics_camera_add(EPhysics_World *world);

View File

@ -589,7 +589,11 @@ _th_simulate(void *data, Ecore_Thread *th)
world->cur_th = th;
EINA_INLIST_FOREACH(world->bodies, body)
ephysics_body_forces_apply(body);
{
ephysics_body_forces_apply(body);
if (body->dragging_data.dragging)
ephysics_body_soft_body_dragging_apply(body);
}
time_now = ecore_time_get();
delta = time_now - world->last_update;