EPhysics: body collision data

This patch introduces a wrapper(EPhysics_Body_Collision) to hold
the collision data(the contact body and collision position).

This data type is used by EPHYSICS_CALLBACK_BODY_COLLISION callback. The
collision detection test is migrated to the new API as well.


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



SVN revision: 74500
This commit is contained in:
Leandro Dorileo 2012-07-27 14:49:37 +00:00 committed by Bruno Dilly
parent 34734a4a72
commit 6a2d290fce
5 changed files with 138 additions and 16 deletions

View File

@ -14,19 +14,20 @@ struct _Collision_Data {
};
static void
_collision_cb(void *data, EPhysics_Body *body __UNUSED__, void *event_info __UNUSED__)
_collision_cb(void *data, EPhysics_Body *body __UNUSED__, void *event_info)
{
EPhysics_Body *contact_body;
Collision_Data *collision_data = data;
Evas_Object *obj;
int x;
EPhysics_Body_Collision *collision = event_info;
int x, y;
if (event_info != collision_data->sphere2) return;
contact_body = ephysics_body_collision_contact_body_get(collision);
if (contact_body != collision_data->sphere2) return;
ephysics_body_collision_position_get(collision, &x, &y);
INF("Collision Detected");
obj = ephysics_body_evas_object_get(collision_data->sphere);
evas_object_geometry_get(obj, &x, NULL, NULL, NULL);
evas_object_move(collision_data->impact, x - 4, FLOOR_Y - 80);
evas_object_move(collision_data->impact, x, y);
elm_object_signal_emit(collision_data->impact, "impact,show",
"ephysics_test");
}

View File

@ -922,6 +922,24 @@ EAPI Eina_Bool ephysics_world_bodies_outside_left_autodel_get(const EPhysics_Wor
typedef struct _EPhysics_Body EPhysics_Body; /**< Body handle, represents an object on EPhysics world. Created with @ref ephysics_body_circle_add() or @ref ephysics_body_box_add() and deleted with @ref ephysics_body_del(). */
/**
* @typedef EPhysics_Body_Collision
*
* Body collision wraps collision informations.
*
* EPhysics_Body_Collision is used on EPHYSICS_CALLBACK_BODY_COLLISION callback
* and is mostly interested to hold informations like:
* @li contact_body - the body which the collision occurred against;
* @li position - points the position where the collision happened;
*
* @see ephysics_body_collision_position_get()
* @see ephysics_body_collision_contact_body_get()
* @see EPHYSICS_CALLBACK_BODY_COLLISION and @ref
* ephysics_body_event_callback_add() for collision callback.
* @ingroup EPhysics_Body
*/
typedef struct _EPhysics_Body_Collision EPhysics_Body_Collision;
/**
* @enum _EPhysics_Callback_Body_Type
* @typedef EPhysics_Callback_Body_Type
@ -1504,12 +1522,25 @@ EAPI void ephysics_body_evas_object_update(EPhysics_Body *body);
*
* Update callbacks receives evas object set to body as event_info argument.
*
* Regarding EPHYSICS_CALLBACK_BODY_COLLISION:
* What follows is a list of details about each callback type:
*
* Callbacks are called just after the collision has been actually processed
* by the physics engine.
* - #EPHYSICS_CALLBACK_BODY_UPDATE: Called after every physics iteration. @p
* body points to the EPhysics_Body itself and @p event_info points to the
* evas object associated to the body.
*
* The other body involved in the collision is passed as event_info argument.
* - #EPHYSICS_CALLBACK_BODY_COLLISION: Called just after the collision has
* been actually processed by the physics engine. The body involved in the
* collision is passed as @p body argument. @p event_info is a pointer to
* @ref EPhysics_Body_Collision - note, this structure(@p event_info) is
* discarded/freed right after callback returns.
*
* - #EPHYSICS_CALLBACK_BODY_DEL: Called when a body deletion has been issued
* and just before the deletion actually happens. @p body points to the body
* being deleted and no @p event_info is provided.
*
* - #EPHYSICS_CALLBACK_BODY_STOPPED: Called when a body is found to be
* stopped. @p body points to the body of interest and @p event_info is a
* pointer to the evas object associated to it.
*
* @param body The physics body.
* @param type Type of callback to be listened by @p func.
@ -1564,6 +1595,39 @@ EAPI void *ephysics_body_event_callback_del(EPhysics_Body *body, EPhysics_Callba
*/
EAPI void *ephysics_body_event_callback_del_full(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func, void *data);
/**
* @brief
* Get the position(x, y) of a body's collision.
*
* Given a body collision data, fills @p x and @p y pointers with the position
* where the collision occurred.
*
* @param collision The body collision data of interest.
* @param x The x pointer to set the x coordinate to.
* @param y The y pointer to set the y coordinate to.
*
* @see EPHYSICS_CALLBACK_BODY_COLLISION and @ref
* ephysics_body_event_callback_add() for collision callback.
* @ingroup EPhysics_Body
*/
EAPI void ephysics_body_collision_position_get(const EPhysics_Body_Collision *collision, Evas_Coord *x, Evas_Coord *y);
/**
* @brief
* Get the body's collision contact body.
*
* Given a body collision data returns the contact body which a collision
* occurred against.
*
* @param collision The body collision of interest.
* @return The contact body of @p collision.
*
* @see EPHYSICS_CALLBACK_BODY_COLLISION and @ref
* ephysics_body_event_callback_add() for collision callback.
* @ingroup EPhysics_Body
*/
EAPI EPhysics_Body *ephysics_body_collision_contact_body_get(const EPhysics_Body_Collision *collision);
/**
* @brief
* Set body's coefficient of restitution.

View File

@ -32,6 +32,12 @@ struct _EPhysics_Body {
Eina_Bool active:1;
};
struct _EPhysics_Body_Collision {
EPhysics_Body *contact_body;
Evas_Coord x;
Evas_Coord y;
};
void
ephysics_body_active_set(EPhysics_Body *body, Eina_Bool active)
{
@ -237,10 +243,50 @@ ephysics_body_evas_object_update_select(EPhysics_Body *body)
_ephysics_body_outside_render_area_check(body);
}
static void
ephysics_body_collision_set(EPhysics_Body_Collision *collision, EPhysics_Body *contact_body, btVector3 position)
{
double rate;
int height;
EPhysics_World *world = contact_body->world;
ephysics_world_render_geometry_get(world, NULL, NULL, NULL, &height);
rate = ephysics_world_rate_get(world);
collision->contact_body = contact_body;
collision->x = position.getX() * rate;
collision->y = height - (position.getY() * rate);
}
EAPI void
ephysics_body_collision_position_get(const EPhysics_Body_Collision *collision, Evas_Coord *x, Evas_Coord *y)
{
if (!collision)
{
ERR("Can't get body's collision data, collision is null.");
return;
}
if (x) *x = collision->x;
if (y) *y = collision->y;
}
EAPI EPhysics_Body *
ephysics_body_collision_contact_body_get(const EPhysics_Body_Collision *collision)
{
if (!collision)
{
ERR("Can't get body's collision contact body, collision is null.");
return NULL;
}
return collision->contact_body;
}
void
ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body)
ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body, btVector3 position)
{
EPhysics_Body_Callback *cb;
EPhysics_Body_Collision *collision;
if ((!body) || (!contact_body))
return;
@ -248,7 +294,18 @@ ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body
EINA_INLIST_FOREACH(body->callbacks, cb)
{
if (cb->type == EPHYSICS_CALLBACK_BODY_COLLISION)
cb->func(cb->data, body, (void *) contact_body);
{
collision = (EPhysics_Body_Collision*)malloc(
sizeof(EPhysics_Body_Collision));
if (!collision)
{
ERR("Can't allocate collision data structure.");
continue;
}
ephysics_body_collision_set(collision, contact_body, position);
cb->func(cb->data, body, collision);
free(collision);
}
}
}

View File

@ -66,7 +66,7 @@ Eina_Bool ephysics_world_bodies_outside_autodel_get(const EPhysics_World *world)
void ephysics_body_evas_object_update_select(EPhysics_Body *body);
void ephysics_orphan_body_del(EPhysics_Body *body);
void ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body);
void ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body, btVector3 position);
btRigidBody *ephysics_body_rigid_body_get(const EPhysics_Body *body);
void ephysics_body_active_set(EPhysics_Body *body, Eina_Bool active);

View File

@ -123,8 +123,8 @@ _ephysics_world_contact_processed_cb(btManifoldPoint &cp, void *b0, void *b1)
body_0 = (EPhysics_Body *) rigid_body_0->getUserPointer();
body_1 = (EPhysics_Body *) rigid_body_1->getUserPointer();
ephysics_body_contact_processed(body_0, body_1);
ephysics_body_contact_processed(body_1, body_0);
ephysics_body_contact_processed(body_0, body_1, cp.getPositionWorldOnA());
ephysics_body_contact_processed(body_1, body_0, cp.getPositionWorldOnB());
return EINA_TRUE;
}