EPhysics - Rotating Forever

The purpose of this example is to demonstrate the EPhysics Rotate usage - The code applies different ways to rotate an EPhysics_Body, such as torque, torque impulse and rotation set.

For this example we'll have an EPhysics_World with gravity setted to zero, and four basic EPhysics_Bodys.

The basic concepts like - defining an EPhysics_World, render geometry, physics limiting boundaries, add an EPhysics_Body, associate it to evas objects, change restitution, friction and impulse properties, were already covered in EPhysics - Bouncing Ball

# Rotating

For the first body we'll apply a torque impulse to make it rotate around Z axis (rotate on x-y plane). Will make the body rolls on clockwise rotation, if the value is negative, the impulse will be on counter clockwise.

ephysics_body_torque_impulse_apply(body, 0, 0, 1);
ephysics_body_torque_impulse_apply
EAPI void ephysics_body_torque_impulse_apply(EPhysics_Body *body, double pitch, double yaw, double roll)
Apply a torque impulse over a body.

For the second body we'll use an offset to apply the force, the three last parameters are responsible to set a relative position to apply the force.In other words, the force applied with an offset will make the body rotates and move around the other cubes.

ephysics_body_impulse_apply(body, 30, 0, 0, 0, -10, 0);
ephysics_body_impulse_apply
EAPI void ephysics_body_impulse_apply(EPhysics_Body *body, double x, double y, double z, Evas_Coord pos_x, Evas_Coord pos_y, Evas_Coord pos_z)
Apply an impulse over a body.

For the third body we'll use a timer to rotate the body and a callback to delete it.

timer = ecore_timer_add(1, _rotate_cb, body);
ephysics_body_event_callback_add(body,
EPHYSICS_CALLBACK_BODY_DEL,
_del_cb, timer);
ephysics_body_event_callback_add
EAPI void ephysics_body_event_callback_add(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func, const void *data)
Register a callback to a type of physics body event.
EPHYSICS_CALLBACK_BODY_DEL
@ EPHYSICS_CALLBACK_BODY_DEL
Body being deleted (called before free).
Definition EPhysics.h:2265
ecore_timer_add
Ecore_Timer * ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
Creates a timer to call the given function in the given period of time.
Definition ecore_timer.c:189
_del_cb(void *data, EPhysics_Body *body __UNUSED__, void *event_info __UNUSED__)
{
ecore_timer_del(data);
}
EPhysics_Body
struct _EPhysics_Body EPhysics_Body
Body handle, represents an object on EPhysics world.
Definition EPhysics.h:655
ecore_timer_del
void * ecore_timer_del(Ecore_Timer *timer)
Deletes the specified timer from the timer list.
Definition ecore_timer.c:238

In the function we'll get the body rotation on z axis in degrees and handle it increasing 5 degrees on its position on z axis on each tick of the timer.

_rotate_cb(void *data)
{
EPhysics_Quaternion *quat_prev, quat_delta, quat;
EPhysics_Body *body = data;
quat_prev = ephysics_body_rotation_get(body, NULL);
ephysics_quaternion_set(&quat_delta, 0, 0, -0.15, 0.98);
ephysics_quaternion_normalize(&quat_delta);
ephysics_body_rotation_set(
body, ephysics_quaternion_multiply(&quat_delta, quat_prev, &quat));
free(quat_prev);
return EINA_TRUE;
}
ephysics_body_rotation_set
EAPI void ephysics_body_rotation_set(EPhysics_Body *body, EPhysics_Quaternion *quat)
Set body's rotation.
ephysics_body_rotation_get
EAPI EPhysics_Quaternion * ephysics_body_rotation_get(const EPhysics_Body *body, EPhysics_Quaternion *rotation)
Get body's rotation quaternion.
EPhysics_Quaternion
struct _EPhysics_Quaternion EPhysics_Quaternion
Quaternion handle, represents a quaternion to be used to rotate bodies.
Definition EPhysics.h:182
ephysics_quaternion_multiply
EAPI EPhysics_Quaternion * ephysics_quaternion_multiply(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, EPhysics_Quaternion *result)
Multiply two quaternions.
ephysics_quaternion_set
EAPI void ephysics_quaternion_set(EPhysics_Quaternion *quat, double x, double y, double z, double w)
Set quaternion values.
ephysics_quaternion_normalize
EAPI void ephysics_quaternion_normalize(EPhysics_Quaternion *quat)
Normalize the quaternion.
EINA_TRUE
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition eina_types.h:539

For the forth body we'll use 2 timers, but before that, we'll apply an initial torque, changing the body angular acceleration and a callback to delete the timers we'll add.

ephysics_body_torque_apply(body, 0, 0, 2);
ephysics_body_torque_apply
EAPI void ephysics_body_torque_apply(EPhysics_Body *body, double torque_x, double torque_y, double torque_z)
Apply a torque over a body.
ephysics_body_event_callback_add(body,
EPHYSICS_CALLBACK_BODY_DEL,

Just the callback function to delete the timers.

_del_torque_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
{
Ecore_Timer *timer;
timer = evas_object_data_get(obj, "increase_timer");
if (timer)
ecore_timer_del(timer);
timer = evas_object_data_get(obj, "stop_timer");
if (timer)
ecore_timer_del(timer);
}
Ecore_Timer
Eo Ecore_Timer
A handle for timers.
Definition Ecore_Common.h:3085
Evas
Eo Evas
An opaque handle to an Evas canvas.
Definition Evas_Common.h:163
Evas_Object
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition Evas_Common.h:185

As we commented we'll use 2 timers, one to increase the torque and another to stop the torque, cleaning the forces related to the body.

timer = ecore_timer_add(3, _increase_torque_cb, body);
evas_object_data_set(cube, "increase_timer", timer);
timer = ecore_timer_add(5, _stop_torque_cb, body);
evas_object_data_set(cube, "stop_timer", timer);
evas_object_data_set
EVAS_API void evas_object_data_set(Evas_Object *eo_obj, const char *key, const void *data)
Set an attached data pointer to an object with a given string key.
Definition evas_data.c:5

In the increase function we'll apply a torque over the body, changing its angular acceleration, it will leads to a change on angular velocity over time. We're using a timer to increase the angular acceleration on each tick of the timer.

_increase_torque_cb(void *data)
{
EPhysics_Body *body = data;
Evas_Object *obj;
ephysics_body_torque_apply(body, 0, 0, 2);
obj = ephysics_body_evas_object_get(body);
evas_object_data_set(obj, "increase_timer", NULL);
return EINA_FALSE;
}
ephysics_body_evas_object_get
EAPI Evas_Object * ephysics_body_evas_object_get(const EPhysics_Body *body)
Get the evas object associated to a physics body.
EINA_FALSE
#define EINA_FALSE
boolean value FALSE (numerical value 0)
Definition eina_types.h:533

In the stop function we'll clear all the forces applied to the body, setting its linear and angular acceleration to zero. We're using this timer to "control" the body velocity, since we are increasing it by another timer. Note that we set the acceleration to zero not the velocity.

_stop_torque_cb(void *data)
{
EPhysics_Body *body = data;
Evas_Object *obj;
ephysics_body_forces_clear(body);
obj = ephysics_body_evas_object_get(body);
evas_object_data_set(obj, "stop_timer", NULL);
return EINA_FALSE;
}
ephysics_body_forces_clear
EAPI void ephysics_body_forces_clear(EPhysics_Body *body)
Clear all the forces applied to a body.

Here we finish the example. The full source code can be found at test_rotating_forever.c.