EPhysics: add forces API

Implement functions to make it possible to control forces acting
over a body.



SVN revision: 75476
This commit is contained in:
Bruno Dilly 2012-08-20 22:15:52 +00:00
parent 4bccde902a
commit 218004c9e3
4 changed files with 253 additions and 2 deletions

View File

@ -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);
/**
* @}
*/

View File

@ -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

View File

@ -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);

View File

@ -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;