From 218004c9e311434b051fbf254f1be0342984bd40 Mon Sep 17 00:00:00 2001 From: Bruno Dilly Date: Mon, 20 Aug 2012 22:15:52 +0000 Subject: [PATCH] EPhysics: add forces API Implement functions to make it possible to control forces acting over a body. SVN revision: 75476 --- legacy/ephysics/src/lib/EPhysics.h | 141 ++++++++++++++++++++- legacy/ephysics/src/lib/ephysics_body.cpp | 104 +++++++++++++++ legacy/ephysics/src/lib/ephysics_private.h | 6 + legacy/ephysics/src/lib/ephysics_world.cpp | 4 + 4 files changed, 253 insertions(+), 2 deletions(-) diff --git a/legacy/ephysics/src/lib/EPhysics.h b/legacy/ephysics/src/lib/EPhysics.h index dec2024635..4809864ca2 100644 --- a/legacy/ephysics/src/lib/EPhysics.h +++ b/legacy/ephysics/src/lib/EPhysics.h @@ -2185,7 +2185,7 @@ EAPI void ephysics_body_torque_impulse_apply(EPhysics_Body *body, double roll); * or can be used to lead to both behaviors with * @ref ephysics_body_impulse_apply(). * - * It will resulte in a central impulse with impulse (@p x, @p y) and a + * It will result in a central impulse with impulse (@p x, @p y) and a * torque impulse that will be calculated as a cross product on impulse * and relative position. * @@ -2300,7 +2300,7 @@ EAPI double ephysics_body_rotation_get(const EPhysics_Body *body); * @note The unit used for rotation is degrees. * * @param body The physics body. - * @param The amount of degrees @p body should be rotated. + * @param rotation The amount of degrees @p body should be rotated. * * @see ephysics_body_rotation_get() * @@ -2346,6 +2346,143 @@ EAPI void ephysics_body_data_set(EPhysics_Body *body, void *data); */ EAPI void *ephysics_body_data_get(const EPhysics_Body *body); +/** + * @brief + * Apply a force on the center of a body. + * + * Applying a force to a body will lead it to change its velocity. + * + * Force is the product of mass and acceleration. So, keeping the mass + * fixed, when force is applied acceleration will change, and consequently, + * velocity will gradually be changes. + * + * Force = mass * acceleration + * + * Final velocity = initial velocity + acceleration * time + * + * While a force is applied, it will be acting over a body. It can be canceled + * by applying an inverse force, or just calling + * @ref ephysics_body_forces_clear(). + * + * This force will be applied on body's center, so it won't implies in + * changing angular acceleration. For that, it is possible to apply a torque + * with @ref ephysics_body_torque_apply(). + * + * If the force shouldn't be applied on body's center, it can be applied on + * a relative point with @ref ephysics_body_force_apply(). + * + * @note Force is measured in kg * p / s / s. + * + * @param body The physics body which over the force will be applied. + * @param x The axis x component of force. + * @param y The axis y component of force. + * + * @see ephysics_body_torque_apply(). + * @see ephysics_body_force_apply(). + * @see ephysics_body_forces_get(). + * + * @ingroup EPhysics_Body + */ +EAPI void ephysics_body_central_force_apply(EPhysics_Body *body, double x, double y); + +/** + * @brief + * Apply a torque over a body. + * + * A torque will be applied over the @p body to change the angular acceleration + * of this body. It will leads to a change on angular velocity over time. + * And the body will rotate around Z axis considering this angular velocity. + * + * @param body The physics body that will receive the torque. + * @param torque Torque to change angular acceleration of the body around Z + * axis (rotate on x - y plane). + * Negative values will accelerate it on anti clock rotation. + * + * @see ephysics_body_central_force_apply(). + * @see ephysics_body_force_apply(). + * @see ephysics_body_forces_get(). + * + * @ingroup EPhysics_Body + */ +EAPI void ephysics_body_torque_apply(EPhysics_Body *body, double torque); + +/** + * @brief + * Apply a force over a body. + * + * A force will be applied over the body to change it's linear and angular + * accelerations. + * + * It can be applied in the center of the body, avoiding affecting angular + * acceleration, with @ref ephysics_body_central_force_apply(), + * it can be applied only to change angular acceleration, with + * @ref ephysics_body_torque_apply(), or can be used to lead to both + * behaviors with @ref ephysics_body_force_apply(). + * + * It will result in a central force with force (@p x, @p y) and a + * torque that will be calculated as a cross product on force + * and relative position. + * + * @param body The physics body that will receive the impulse. + * @param x The axis x component of force. + * @param y The axis y component of force. + * @param pos_x The axis x component of the relative position to apply force. + * @param pos_y The axis y component of the relative position to apply force. + * + * @note Force is measured in kg * p / s / s and position in p (pixels, or + * Evas coordinates). + * + * @see ephysics_body_central_force_apply(). + * @see ephysics_body_torque_apply(). + * @see ephysics_body_forces_get(). + * + * @ingroup EPhysics_Body + */ +EAPI void ephysics_body_force_apply(EPhysics_Body *body, double x, double y, Evas_Coord pos_x, Evas_Coord pos_y); + +/** + * @brief + * Get physics body forces. + * + * Get all the forces applied over a body. + * + * @param body The physics body. + * @param x The axis x component of total force. + * @param y The axis y component of total force. + * @param torque The torque. + * + * @see ephysics_body_force_apply() for more details. + * @see ephysics_body_central_force_apply(). + * @see ephysics_body_torque_apply(). + * @see ephysics_body_forces_clear(). + * + * @ingroup EPhysics_Body + */ +EAPI void ephysics_body_forces_get(const EPhysics_Body *body, double *x, double *y, double *torque); + +/** + * @brief + * Clear all the forces applied to a body. + * + * It will remove all the forces previously applied. So linear acceleration + * and angular acceleration will be set to 0. + * + * It won't interfere with world's gravity, the body will continue to be + * accelerated considering gravity. + * + * It won't affect damping. + * + * @param body The physics body that will have applied forces set to 0. + * + * @see ephysics_body_central_force_apply(). + * @see ephysics_body_torque_apply(). + * @see ephysics_body_force_apply(). + * @see ephysics_body_forces_get(). + * + * @ingroup EPhysics_Body + */ +EAPI void ephysics_body_forces_clear(EPhysics_Body *body); + /** * @} */ diff --git a/legacy/ephysics/src/lib/ephysics_body.cpp b/legacy/ephysics/src/lib/ephysics_body.cpp index a907008300..c495bcb59f 100644 --- a/legacy/ephysics/src/lib/ephysics_body.cpp +++ b/legacy/ephysics/src/lib/ephysics_body.cpp @@ -26,6 +26,15 @@ struct _EPhysics_Body_Collision { Evas_Coord y; }; +static void +_ephysics_body_forces_update(EPhysics_Body *body) +{ + body->force.x = body->rigid_body->getTotalForce().getX(); + body->force.y = body->rigid_body->getTotalForce().getY(); + body->force.torque = body->rigid_body->getTotalTorque().getZ(); + body->rigid_body->clearForces(); +} + static inline void _ephysics_body_sleeping_threshold_set(EPhysics_Body *body, double linear_threshold, double angular_threshold, double rate) { @@ -463,6 +472,16 @@ _ephysics_body_outside_render_area_check(EPhysics_Body *body) } } +void +ephysics_body_forces_apply(EPhysics_Body *body) +{ + double rate = ephysics_world_rate_get(body->world); + body->rigid_body->activate(1); + body->rigid_body->applyCentralForce(btVector3(body->force.x / rate, + body->force.y / rate, 0)); + body->rigid_body->applyTorque(btVector3(0, 0, body->force.torque)); +} + void ephysics_body_recalc(EPhysics_Body *body, double rate) { @@ -1386,6 +1405,91 @@ ephysics_body_data_get(const EPhysics_Body *body) return body->data; } +EAPI void +ephysics_body_central_force_apply(EPhysics_Body *body, double x, double y) +{ + double rate; + + if (!body) + { + ERR("Can't apply force to a null body."); + return; + } + + rate = ephysics_world_rate_get(body->world); + ephysics_body_forces_apply(body); + body->rigid_body->applyCentralForce(btVector3(x / rate, y / rate, 0)); + _ephysics_body_forces_update(body); +} + +EAPI void +ephysics_body_force_apply(EPhysics_Body *body, double x, double y, Evas_Coord pos_x, Evas_Coord pos_y) +{ + double rate; + + if (!body) + { + ERR("Can't apply force to a null body."); + return; + } + + rate = ephysics_world_rate_get(body->world); + ephysics_body_forces_apply(body); + body->rigid_body->applyForce(btVector3(x / rate, y / rate, 0), + btVector3((double) pos_x / rate, + (double) pos_y / rate, 0)); + _ephysics_body_forces_update(body); +} + +EAPI void +ephysics_body_torque_apply(EPhysics_Body *body, double torque) +{ + double rate; + + if (!body) + { + ERR("Can't apply force to a null body."); + return; + } + + rate = ephysics_world_rate_get(body->world); + ephysics_body_forces_apply(body); + body->rigid_body->applyTorque(btVector3(0, 0, -torque)); + _ephysics_body_forces_update(body); +} + +EAPI void +ephysics_body_forces_get(const EPhysics_Body *body, double *x, double *y, double *torque) +{ + double rate; + + if (!body) + { + ERR("Can't get forces from a null body."); + return; + } + + rate = ephysics_world_rate_get(body->world); + + if (x) *x = body->force.x * rate; + if (y) *y = body->force.y * rate; + if (torque) *torque = -body->force.torque; +} + +EAPI void +ephysics_body_forces_clear(EPhysics_Body *body) +{ + if (!body) + { + ERR("Can't clear forces of a null body."); + return; + } + + body->force.x = 0; + body->force.y = 0; + body->force.torque = 0; +} + #ifdef __cplusplus } #endif diff --git a/legacy/ephysics/src/lib/ephysics_private.h b/legacy/ephysics/src/lib/ephysics_private.h index eb7669fdf2..3a3dad4736 100644 --- a/legacy/ephysics/src/lib/ephysics_private.h +++ b/legacy/ephysics/src/lib/ephysics_private.h @@ -75,6 +75,11 @@ struct _EPhysics_Body { Eina_List *collision_groups; Eina_List *to_delete; double mass; + struct { + double x; + double y; + double torque; + } force; Eina_Bool active:1; Eina_Bool deleted:1; }; @@ -101,6 +106,7 @@ void ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact btRigidBody *ephysics_body_rigid_body_get(const EPhysics_Body *body); void ephysics_body_active_set(EPhysics_Body *body, Eina_Bool active); void ephysics_body_recalc(EPhysics_Body *body, double rate); +void ephysics_body_forces_apply(EPhysics_Body *body); /* Camera */ EPhysics_Camera *ephysics_camera_add(EPhysics_World *world); diff --git a/legacy/ephysics/src/lib/ephysics_world.cpp b/legacy/ephysics/src/lib/ephysics_world.cpp index 292a42c1b6..a0a4c5e023 100644 --- a/legacy/ephysics/src/lib/ephysics_world.cpp +++ b/legacy/ephysics/src/lib/ephysics_world.cpp @@ -245,12 +245,16 @@ _simulate_worlds(void *data) EINA_INLIST_FOREACH(lworlds, world) { double time_now, delta; + EPhysics_Body *body; if (!world->running) continue; world->walking++; + EINA_INLIST_FOREACH(world->bodies, body) + ephysics_body_forces_apply(body); + time_now = ecore_time_get(); delta = time_now - world->last_update; world->last_update = time_now;