EPhysics: triangle API

This patch introduces soft body's mesh triangle manipulation, for picking
the triangle of a body in X and Y and moving it as well.


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



SVN revision: 78088
This commit is contained in:
Leandro Dorileo 2012-10-16 23:12:47 +00:00 committed by Bruno Dilly
parent d06196ca8d
commit 4f73c6d46e
3 changed files with 177 additions and 20 deletions

View File

@ -1762,6 +1762,42 @@ 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
* Get the triangle index of a soft body in @p x and @p y.
*
* Given a point in @p x and @p y a ray cast is performed and if a triangle is
* found its index is returned.
*
* @param body The body to get the triangle index from.
* @param x The x coord.
* @param y The y coord.
* @return -1 If no triangle is found, a triangle index otherwise.
*
* @see ephysics_body_soft_body_triangle_move().
*
* @ingroup EPhysics_Body
*/
EAPI int ephysics_body_soft_body_triangle_index_get(EPhysics_Body *body, Evas_Coord x, Evas_Coord y);
/**
* @brief
* Move a body's triangle.
*
* Move the triangle of @p idx of @p body to @p x, @p y and @p z.
*
* @param body The body of interest.
* @param idx The triangle index.
* @param x The x coordinate.
* @param y The y coordinate.
* @param z The z coordinate.
*
* @see ephysics_body_soft_body_triangle_index_get().
*
* @ingroup EPhysics_Body
*/
EAPI void ephysics_body_soft_body_triangle_move(EPhysics_Body *body, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z);
/**
* @brief
* Create a new circle physics body.
@ -1875,15 +1911,15 @@ EAPI EPhysics_Body *ephysics_body_soft_box_add(EPhysics_World *world);
* example passing @p granularity of 20 will create a cloth with 20 rows and 20
* columns.
*
* By default EPhysics creates a cloth with 10 rows and 10 columns, these
* By default EPhysics creates a cloth with 15 rows and 15 columns, these
* default values will generally fit the most common scenarios.
*
* If the informed @p granularity is of 0 then the default value - of 10 - is
* If the informed @p granularity is of 0 then the default value - of 15 - is
* assumed.
*
* @param world The world this body will belong to.
* @param granularity Define - proportionally - the number of rows and columns,
* if 0 the default value - of 10 - is assumed.
* if 0 the default value - of 15 - is assumed.
* @return a bew body or @c NULL on erros.
*
* @see ephysics_body_del().

View File

@ -3,6 +3,7 @@
#endif
#include <Evas.h>
#include <Ecore.h>
#include <BulletCollision/CollisionShapes/btShapeHull.h>
#include <LinearMath/btGeometryUtil.h>
@ -37,7 +38,7 @@ typedef struct _EPhysics_Body_Soft_Body_Slice
{
int index;
Evas_Object *evas_obj;
int stacking;
double stacking;
} EPhysics_Body_Soft_Body_Slice;
static const Evas_Smart_Cb_Description _smart_callbacks[] =
@ -781,9 +782,9 @@ _ephysics_body_cloth_constraints_rebuild(EPhysics_Body *body)
}
}
}
soft_body->generateClusters(0);
soft_body->generateBendingConstraints(2, soft_body->m_materials[0]);
soft_body->generateBendingConstraints(2, soft_body->m_materials[
body->material_index]);
}
static void
@ -804,7 +805,8 @@ _ephysics_body_soft_body_constraints_rebuild(EPhysics_Body *body)
}
soft_body->generateClusters(0);
soft_body->generateBendingConstraints(10, soft_body->m_materials[0]);
soft_body->generateBendingConstraints(10, soft_body->m_materials[
body->material_index]);
}
inline static double
@ -1225,11 +1227,12 @@ ephysics_body_soft_body_get(const EPhysics_Body *body)
static void
_ephysics_body_soft_body_hardness_set(EPhysics_Body *body, double hardness)
{
int m = body->material_index;
btSoftBody *soft_body = body->soft_body;
soft_body->m_cfg.kAHR = (hardness / body->anchor_prop) * 0.6;
soft_body->m_materials[0]->m_kVST = (hardness / 1000);
soft_body->m_materials[0]->m_kLST = (hardness / 1000);
soft_body->m_materials[0]->m_kAST = (hardness / 1000);
soft_body->m_materials[m]->m_kVST = (hardness / 1000);
soft_body->m_materials[m]->m_kLST = (hardness / 1000);
soft_body->m_materials[m]->m_kAST = (hardness / 1000);
DBG("Soft body %p hardness set to %lf.", body, hardness);
}
@ -1274,7 +1277,7 @@ ephysics_body_soft_body_hardness_get(const EPhysics_Body *body)
return 0;
}
return (body->soft_body->m_materials[0]->m_kVST * 100);
return (body->soft_body->m_materials[body->material_index]->m_kVST * 100);
}
static void
@ -1287,7 +1290,6 @@ _ephysics_body_soft_body_default_config(EPhysics_Body *body, btSoftBody *soft_bo
body->soft_body->m_cfg.collisions += btSoftBody::fCollision::SDF_RS;
body->soft_body->m_cfg.collisions += btSoftBody::fCollision::VF_SS;
_ephysics_body_soft_body_hardness_set(body, 100);
}
@ -1306,6 +1308,7 @@ _ephysics_body_soft_body_add(EPhysics_World *world, btCollisionShape *collision_
return NULL;
}
body->material_index = 0;
body->anchor_prop = 1000;
body->type = EPHYSICS_BODY_TYPE_SOFT;
_ephysics_body_soft_body_default_config(body, soft_body);
@ -1413,8 +1416,8 @@ ephysics_body_cloth_add(EPhysics_World *world, unsigned short granularity)
EPhysics_Body *body;
btSoftBodyWorldInfo *world_info;
btSoftBody *soft_body;
const int rows = (!granularity) ? 10 : granularity;
const int columns = (!granularity) ? 10 : granularity;
const int rows = (!granularity) ? 15 : granularity;
const int columns = (!granularity) ? 15 : granularity;
if (!world)
{
@ -1424,10 +1427,10 @@ ephysics_body_cloth_add(EPhysics_World *world, unsigned short granularity)
world_info = ephysics_world_info_get(world);
soft_body = btSoftBodyHelpers::CreatePatch(*world_info,
btVector3(1, 2, 0.5),
btVector3(1, 1, 0.5),
btVector3(2, 2, 0.5),
btVector3(2, 1, 0.5),
btVector3(1, 2, 0),
btVector3(1, 1, 0),
btVector3(2, 2, 0),
btVector3(2, 1, 0),
rows, columns, 0, false);
if (!soft_body)
{
@ -1439,8 +1442,13 @@ ephysics_body_cloth_add(EPhysics_World *world, unsigned short granularity)
if (!body)
goto no_body;
soft_body->setPose(false, true);
soft_body->appendMaterial();
body->material_index = 1;
soft_body->m_cfg.piterations = 5;
_ephysics_body_soft_body_default_config(body, soft_body);
soft_body->m_cfg.piterations = 10;
_ephysics_body_cloth_constraints_rebuild(body);
body->slices = soft_body->m_faces.size();
@ -1456,7 +1464,7 @@ ephysics_body_cloth_add(EPhysics_World *world, unsigned short granularity)
body->cloth_columns = columns;
body->cloth_rows = rows;
body->anchor_prop = 100;
body->anchor_prop = 1;
body->type = EPHYSICS_BODY_TYPE_CLOTH;
ephysics_world_soft_body_add(world, body);
@ -1469,6 +1477,118 @@ no_body:
return NULL;
}
static void
_ephysics_body_soft_body_single_face_transform(btSoftBody *soft_body, int face_idx, int node_idx, btTransform trans, btScalar vel_reduction)
{
btSoftBody::Node *node;
ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
const btScalar margin = soft_body->getCollisionShape()->getMargin();
node = soft_body->m_faces[face_idx].m_n[node_idx];
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);
}
EAPI void
ephysics_body_soft_body_triangle_move(EPhysics_Body *body, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
{
btScalar xx, yy, zz;
Evas_Coord wh;
double rate;
btVector3 new_pos;
btTransform diff;
btSoftBody::Face face;
btSoftBody::Node *node;
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
{
ERR("Could not move soft body triangle, body must be soft or cloth.");
return;
}
if (idx < 0 || idx >= 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;
}
rate = ephysics_world_rate_get(body->world);
ephysics_world_render_geometry_get(body->world, NULL, NULL, NULL, &wh);
xx = x / rate;
yy = (wh - y) / rate;
zz = z / rate;
new_pos = btVector3(xx, yy, zz);
ephysics_world_lock_take(body->world);
face = body->soft_body->m_faces[idx];
for (int i = 0; i < 3; i++)
{
node = face.m_n[i];
diff.setIdentity();
diff.setOrigin(new_pos - node->m_x);
_ephysics_body_soft_body_single_face_transform(body->soft_body, idx, i,
diff, 0.25);
if (!i) continue;
diff.setOrigin(diff.getOrigin() * 0.1);
for (int m = 0; m < body->soft_body->m_faces.size(); m++)
{
if (m == idx) continue;
_ephysics_body_soft_body_single_face_transform(body->soft_body, m,
i, diff, 0.05);
}
}
body->soft_body->updateClusters();
body->soft_body->updateBounds();
body->soft_body->updateNormals();
body->soft_body->updatePose();
ephysics_world_lock_release(body->world);
}
EAPI int
ephysics_body_soft_body_triangle_index_get(EPhysics_Body *body, Evas_Coord x, Evas_Coord y)
{
btVector3 ray_from;
btVector3 ray_to;
btSoftBody::sRayCast result;
Evas_Coord wh, bw;
btScalar xx, yy;
double rate;
int index = -1;
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
{
ERR("Can't get node index, operation not permited to rigid bodies");
return -1;
}
ephysics_world_lock_take(body->world);
rate = ephysics_world_rate_get(body->world);
ephysics_world_render_geometry_get(body->world, NULL, NULL, NULL, &wh);
ephysics_body_geometry_get(body, NULL, NULL, NULL, &bw, NULL, NULL);
xx = x / rate;
yy = (wh - y) / rate;
ray_from = btVector3(xx, yy, -100);
ray_to = btVector3(xx, yy, 100);
if (body->soft_body->rayTest(ray_from, ray_to, result))
index = result.index;
ephysics_world_lock_release(body->world);
return index;
}
EAPI EPhysics_Body *
ephysics_body_soft_circle_add(EPhysics_World *world)
{

View File

@ -115,6 +115,7 @@ struct _EPhysics_Body {
Eina_Bool active:1;
Eina_Bool deleted:1;
Eina_Bool light_apply:1;
int material_index;
};
extern int _ephysics_log_dom;