From 6a2d290fcec8793cf0777deaf3cbaf33c70edb48 Mon Sep 17 00:00:00 2001 From: Leandro Dorileo Date: Fri, 27 Jul 2012 14:49:37 +0000 Subject: [PATCH] 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 SVN revision: 74500 --- .../src/bin/test_collision_detection.c | 15 ++-- legacy/ephysics/src/lib/EPhysics.h | 72 +++++++++++++++++-- legacy/ephysics/src/lib/ephysics_body.cpp | 61 +++++++++++++++- legacy/ephysics/src/lib/ephysics_private.h | 2 +- legacy/ephysics/src/lib/ephysics_world.cpp | 4 +- 5 files changed, 138 insertions(+), 16 deletions(-) diff --git a/legacy/ephysics/src/bin/test_collision_detection.c b/legacy/ephysics/src/bin/test_collision_detection.c index c87d599e52..7f3b2b534e 100644 --- a/legacy/ephysics/src/bin/test_collision_detection.c +++ b/legacy/ephysics/src/bin/test_collision_detection.c @@ -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"); } diff --git a/legacy/ephysics/src/lib/EPhysics.h b/legacy/ephysics/src/lib/EPhysics.h index 0732be68fa..0be3ec4dec 100644 --- a/legacy/ephysics/src/lib/EPhysics.h +++ b/legacy/ephysics/src/lib/EPhysics.h @@ -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. diff --git a/legacy/ephysics/src/lib/ephysics_body.cpp b/legacy/ephysics/src/lib/ephysics_body.cpp index 3d351bbe4e..f7be1878b8 100644 --- a/legacy/ephysics/src/lib/ephysics_body.cpp +++ b/legacy/ephysics/src/lib/ephysics_body.cpp @@ -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); + } } } diff --git a/legacy/ephysics/src/lib/ephysics_private.h b/legacy/ephysics/src/lib/ephysics_private.h index 0970ba4c01..8ef80422ed 100644 --- a/legacy/ephysics/src/lib/ephysics_private.h +++ b/legacy/ephysics/src/lib/ephysics_private.h @@ -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); diff --git a/legacy/ephysics/src/lib/ephysics_world.cpp b/legacy/ephysics/src/lib/ephysics_world.cpp index f29fdbe58d..d2c20a4b06 100644 --- a/legacy/ephysics/src/lib/ephysics_world.cpp +++ b/legacy/ephysics/src/lib/ephysics_world.cpp @@ -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; }