EPhysics: slider constraint

This patch introduces the slider constraint, adds an slider constraint
test, move p2p constraint from ephysics_constraint_add to
ephysics_constraint_p2p_add migrates its usage.

Further work will migrate the btConstraint of p2p for Generic6Dof constraint
since it's flexible enough to implement most of constraints.


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



SVN revision: 74699
This commit is contained in:
Leandro Dorileo 2012-07-31 22:24:20 +00:00 committed by Bruno Dilly
parent 70d44875dc
commit 701ed6b8fd
8 changed files with 434 additions and 8 deletions

View File

@ -30,7 +30,8 @@ test_jumping_balls.c \
test_no_gravity.c \
test_rotate.c \
test_velocity.c \
test_sleeping_threshold.c
test_sleeping_threshold.c \
test_slider.c
ephysics_logo_SOURCES = \
ephysics_logo.c

View File

@ -24,6 +24,7 @@ void test_no_gravity(void *data, Evas_Object *obj, void *event_info);
void test_rotate(void *data, Evas_Object *obj, void *event_info);
void test_velocity(void *data, Evas_Object *obj, void *event_info);
void test_sleeping(void *data, Evas_Object *obj, void *event_info);
void test_slider(void *data, Evas_Object *obj, void *event_info);
static void
_win_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
@ -166,6 +167,7 @@ _main_win_add(char *autorun __UNUSED__, Eina_Bool test_win_only __UNUSED__)
ADD_TEST("ROTATE", test_rotate);
ADD_TEST("VELOCITY", test_velocity);
ADD_TEST("SLEEPING THRESHOLD", test_sleeping);
ADD_TEST("SLIDER", test_slider);
elm_list_go(list);
}

View File

@ -60,7 +60,8 @@ _world_populate(Test_Data *test_data)
ephysics_body_friction_set(box_body2, 0.1);
test_data->bodies = eina_list_append(test_data->bodies, box_body2);
constraint = ephysics_constraint_add(box_body1, box_body2, 0, 100, 0, 0);
constraint = ephysics_constraint_p2p_add(box_body1, box_body2, 0, 100, 0,
0);
test_data->constraints = eina_list_append(test_data->constraints,
constraint);
}

View File

@ -0,0 +1,167 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "ephysics_test.h"
static void
_world_populate(Test_Data *test_data)
{
EPhysics_Body *box_body1, *box_body2, *box_body3, *box_body4;
Evas_Object *box1, *box2, *box3, *box4, *sh1, *sh2, *sh3, *sh4;
EPhysics_Constraint *constraint;
sh1 = elm_layout_add(test_data->win);
elm_layout_file_set(
sh1, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "shadow-cube");
evas_object_move(sh1, WIDTH / 6, FLOOR_Y);
evas_object_resize(sh1, 70, 3);
evas_object_show(sh1);
test_data->evas_objs = eina_list_append(test_data->evas_objs, sh1);
box1 = elm_image_add(test_data->win);
elm_image_file_set(
box1, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "blue-cube");
evas_object_move(box1, WIDTH / 6, FLOOR_Y - 70);
evas_object_resize(box1, 70, 70);
evas_object_show(box1);
test_data->evas_objs = eina_list_append(test_data->evas_objs, box1);
box_body1 = ephysics_body_box_add(test_data->world);
ephysics_body_mass_set(box_body1, 0);
ephysics_body_evas_object_set(box_body1, box1, EINA_TRUE);
ephysics_body_event_callback_add(box_body1, EPHYSICS_CALLBACK_BODY_UPDATE,
update_object_cb, sh1);
ephysics_body_restitution_set(box_body1, 0.3);
ephysics_body_friction_set(box_body1, 0.1);
test_data->bodies = eina_list_append(test_data->bodies, box_body1);
sh2 = elm_layout_add(test_data->win);
elm_layout_file_set(
sh2, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "shadow-cube");
evas_object_move(sh2, WIDTH / 6 + 60, FLOOR_Y);
evas_object_resize(sh2, 70, 3);
evas_object_show(sh2);
test_data->evas_objs = eina_list_append(test_data->evas_objs, sh2);
box2 = elm_image_add(test_data->win);
elm_image_file_set(
box2, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "purple-cube");
evas_object_move(box2, WIDTH / 6 + 65, HEIGHT / 8);
evas_object_resize(box2, 70, 70);
evas_object_show(box2);
test_data->evas_objs = eina_list_append(test_data->evas_objs, box2);
box_body2 = ephysics_body_box_add(test_data->world);
ephysics_body_evas_object_set(box_body2, box2, EINA_TRUE);
ephysics_body_event_callback_add(box_body2, EPHYSICS_CALLBACK_BODY_UPDATE,
update_object_cb, sh2);
ephysics_body_restitution_set(box_body2, 0.5);
ephysics_body_friction_set(box_body2, 0.1);
test_data->bodies = eina_list_append(test_data->bodies, box_body2);
constraint = ephysics_constraint_slider_add(box_body2);
ephysics_constraint_slider_linear_limit_set(constraint, 0,
HEIGHT - (HEIGHT / 8), 0, 0);
ephysics_constraint_slider_angular_limit_set(constraint, 0, 45);
test_data->constraints = eina_list_append(test_data->constraints,
constraint);
sh3 = elm_layout_add(test_data->win);
elm_layout_file_set(
sh3, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "shadow-cube");
evas_object_move(sh3, WIDTH / 6 + 60, FLOOR_Y);
evas_object_resize(sh3, 70, 3);
evas_object_show(sh3);
test_data->evas_objs = eina_list_append(test_data->evas_objs, sh3);
box3 = elm_image_add(test_data->win);
elm_image_file_set(
box3, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "blue-cube");
evas_object_move(box3, WIDTH - 120, HEIGHT / 8);
evas_object_resize(box3, 70, 70);
evas_object_show(box3);
test_data->evas_objs = eina_list_append(test_data->evas_objs, box3);
box_body3 = ephysics_body_box_add(test_data->world);
ephysics_body_evas_object_set(box_body3, box3, EINA_TRUE);
ephysics_body_event_callback_add(box_body3, EPHYSICS_CALLBACK_BODY_UPDATE,
update_object_cb, sh3);
ephysics_body_restitution_set(box_body3, 0.5);
ephysics_body_friction_set(box_body3, 0.1);
test_data->bodies = eina_list_append(test_data->bodies, box_body3);
constraint = ephysics_constraint_slider_add(box_body3);
ephysics_constraint_slider_linear_limit_set(constraint, WIDTH - 120, 0, 0,
0);
ephysics_body_central_impulse_apply(box_body3, -8, 0);
test_data->constraints = eina_list_append(test_data->constraints,
constraint);
sh4 = elm_layout_add(test_data->win);
elm_layout_file_set(
sh4, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "shadow-cube");
evas_object_move(sh4, WIDTH / 6 + 60, FLOOR_Y);
evas_object_resize(sh4, 70, 3);
evas_object_show(sh4);
test_data->evas_objs = eina_list_append(test_data->evas_objs, sh4);
box4 = elm_image_add(test_data->win);
elm_image_file_set(
box4, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "purple-cube");
evas_object_move(box4, WIDTH - 120, FLOOR_Y - 70);
evas_object_resize(box4, 70, 70);
evas_object_show(box4);
test_data->evas_objs = eina_list_append(test_data->evas_objs, box4);
box_body4 = ephysics_body_box_add(test_data->world);
ephysics_body_evas_object_set(box_body4, box4, EINA_TRUE);
ephysics_body_event_callback_add(box_body4, EPHYSICS_CALLBACK_BODY_UPDATE,
update_object_cb, sh4);
ephysics_body_restitution_set(box_body4, 0.5);
ephysics_body_friction_set(box_body4, 0.1);
test_data->bodies = eina_list_append(test_data->bodies, box_body4);
constraint = ephysics_constraint_slider_add(box_body4);
ephysics_constraint_slider_linear_limit_set(constraint, WIDTH / 3, 0, 0, 0);
ephysics_body_central_impulse_apply(box_body4, -20, 0);
test_data->constraints = eina_list_append(test_data->constraints,
constraint);
}
static void
_restart(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
{
Test_Data *test_data = data;
DBG("Restart pressed");
test_clean(test_data);
_world_populate(test_data);
}
void
test_slider(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
EPhysics_Body *boundary;
EPhysics_World *world;
Test_Data *test_data;
if (!ephysics_init())
return;
test_data = test_data_new();
test_win_add(test_data, "Slider", EINA_TRUE);
elm_layout_signal_callback_add(test_data->layout, "restart", "test-theme",
_restart, test_data);
world = ephysics_world_new();
ephysics_world_render_geometry_set(world, 50, 40, WIDTH - 100, FLOOR_Y - 40);
test_data->world = world;
boundary = ephysics_body_bottom_boundary_add(test_data->world);
ephysics_body_restitution_set(boundary, 0.65);
ephysics_body_friction_set(boundary, 3);
_world_populate(test_data);
}

View File

@ -2091,7 +2091,7 @@ typedef struct _EPhysics_Constraint EPhysics_Constraint; /**< Constraint handle,
/**
* @brief
* Create a new constraint between 2 bodies.
* Create a new constraint between 2 bodies(Point to Point constraint).
*
* The constraint will join two bodies(@p body1 and @p body2) limiting their
* movements based on specified anchors.
@ -2102,13 +2102,101 @@ typedef struct _EPhysics_Constraint EPhysics_Constraint; /**< Constraint handle,
* @param anchor_b1_y The fist body Y anchor.
* @param anchor_b2_x The second body X anchor.
* @param anchor_b2_y The second body Y anchor.
* @return A new constraint or @c NULL, on errors.
* @return A new p2p(point to point) constraint or @c NULL, on errors.
*
* @see ephysics_constraint_del().
*
* @ingroup EPhysics_Constraint
*/
EAPI EPhysics_Constraint *ephysics_constraint_add(EPhysics_Body *body1, EPhysics_Body *body2, Evas_Coord anchor_b1_x, Evas_Coord anchor_b1_y, Evas_Coord anchor_b2_x, Evas_Coord anchor_b2_y);
EAPI EPhysics_Constraint *ephysics_constraint_p2p_add(EPhysics_Body *body1, EPhysics_Body *body2, Evas_Coord anchor_b1_x, Evas_Coord anchor_b1_y, Evas_Coord anchor_b2_x, Evas_Coord anchor_b2_y);
/**
* @brief
* Create a new slider constraint.
*
* The constraint will limit the linear and angular moving of a body.
*
* @param body The body to apply the constraint.
*
* @see ephysics_constraint_slider_linear_limit_set() for linear moving limit
* configuration.
* @see ephysics_constraint_slider_angular_limit_set() for angular moving limit
* configuration.
* @return A new slider constraint or @c NULL on erros.
*
* @see ephysics_constraint_del().
*
* @ingroup EPhysics_Constraint
*/
EAPI EPhysics_Constraint *ephysics_constraint_slider_add(EPhysics_Body *body);
/**
* @brief
* Define the linear moving limits of a slider @p constraint.
*
* The linear limits are defined from the body's position on. The user will
* want to limit the movements to the left, right, under and above the rigid
* body. The unit for every limits are defined on Evas coordinates.
*
* @param constraint The constraint to be set.
* @param left_x The moving limit to the left on X axis - from the body's
* position on.
* @param under_y The moving limit down on Y axis - from the body's position
* on.
* @param right_x The moving limit to the right on X axis - from the body's
* position on.
* @param above_y The moving limit up on Y axis - from the body's position on.
*
* @see ephysics_constraint_slider_linear_limit_get()
* @ingroup EPhysics_Constraint
*/
EAPI void ephysics_constraint_slider_linear_limit_set(EPhysics_Constraint *constraint, Evas_Coord left_x, Evas_Coord under_y, Evas_Coord right_x, Evas_Coord above_y);
/**
* @brief
* Get the linear moving limits of a slider constraint.
*
* @param constraint The constraint to get linear limits from.
* @param left_x Pointer to set with the limit to the left on X axis.
* @param under_y Pointer to set with the limit down on Y axis.
* @param right_x Pointer to set with the limit to the right on X axis.
* @param above_y Pointer to set with the limit up on Y axis.
*
* @see ephysics_constraint_slider_linear_limit_set()
* @ingroup EPhysics_Constraint
*/
EAPI void ephysics_constraint_slider_linear_limit_get(const EPhysics_Constraint *constraint, Evas_Coord *left_x, Evas_Coord *under_y, Evas_Coord *right_x, Evas_Coord *above_y);
/**
* @brief
* Set the angular moving limits of a slider @p constraint.
*
* The angular moving limits is defined in degrees and will limit the moving on
* Z axis - counter clock and clock wise directions.
*
* @param constraint The constraint to be set.
* @param counter_clock_z Amount of degrees from 0.0 to 360.0 to limit
* counter clock rotation.
* @param clock_wise_z Amount of degrees from 0.0 to 360.0 to limit clock wise
* rotation.
*
* @see ephysics_constraint_slider_angular_limit_get()
* @ingroup EPhysics_Constraint
*/
EAPI void ephysics_constraint_slider_angular_limit_set(EPhysics_Constraint *constraint, Evas_Coord counter_clock_z, Evas_Coord clock_wise_z);
/**
* @brief
* Get the angular moving limits of a slider @p constraint.
*
* @param constraint The constraint to get the angular limits from.
* @param counter_clock_z Pointer to set with the counter clock limit degrees.
* @param clock_wise_z Pointer to set with the clock wise limit degrees.
*
* @see ephysics_constraint_slider_angular_limit_set()
* @ingroup EPhysics_Constraint
*/
EAPI void ephysics_constraint_slider_angular_limit_get(const EPhysics_Constraint *constraint, Evas_Coord *counter_clock_z, Evas_Coord *clock_wise_z);
/**
* @brief

View File

@ -10,8 +10,6 @@
extern "C" {
#endif
#define RAD_TO_DEG 57.29582 /* 2 * pi radians == 360 degree */
typedef struct _EPhysics_Body_Callback EPhysics_Body_Callback;
struct _EPhysics_Body_Callback {

View File

@ -8,13 +8,179 @@
extern "C" {
#endif
typedef enum _EPhysics_Constraint_Type {
EPHYSICS_CONSTRAINT_P2P,
EPHYSICS_CONSTRAINT_SLIDER,
} EPhysics_Constraint_Type;
struct _EPhysics_Constraint {
btTypedConstraint *bt_constraint;
EPhysics_World *world;
EPhysics_Constraint_Type type;
};
EAPI EPhysics_Constraint *
ephysics_constraint_add(EPhysics_Body *body1, EPhysics_Body *body2, Evas_Coord anchor_b1_x, Evas_Coord anchor_b1_y, Evas_Coord anchor_b2_x, Evas_Coord anchor_b2_y)
ephysics_constraint_slider_add(EPhysics_Body *body)
{
EPhysics_Constraint *constraint;
btTransform trans;
if (!body)
{
ERR("To create a constraint body must to be non null.");
return NULL;
}
constraint = (EPhysics_Constraint *) calloc(1, sizeof(EPhysics_Constraint));
if (!constraint)
{
ERR("Couldn't create a new constraint.");
return NULL;
}
trans.setIdentity();
constraint->bt_constraint = new
btGeneric6DofConstraint(*ephysics_body_rigid_body_get(body), trans,
false);
if (!constraint->bt_constraint)
{
ERR("Failed to create a btConstraint");
free(constraint);
return NULL;
}
constraint->type = EPHYSICS_CONSTRAINT_SLIDER;
constraint->world = ephysics_body_world_get(body);
ephysics_world_constraint_add(constraint->world, constraint->bt_constraint);
INF("Constraint added.");
return constraint;
}
EAPI void
ephysics_constraint_slider_linear_limit_set(EPhysics_Constraint *constraint, Evas_Coord left_x, Evas_Coord under_y, Evas_Coord right_x, Evas_Coord above_y)
{
btGeneric6DofConstraint *slider_constraint;
int rate;
if (!constraint)
{
ERR("Can't set constraint's linear limit, constraint is null.");
return;
}
if (constraint->type != EPHYSICS_CONSTRAINT_SLIDER)
{
ERR("Can't set linear limit, this is not an slider constraint.");
return;
}
slider_constraint = (btGeneric6DofConstraint *)constraint->bt_constraint;
rate = ephysics_world_rate_get(constraint->world);
left_x = (left_x) / rate;
right_x = (right_x) / rate;
under_y = (under_y) / rate;
above_y = (above_y) / rate;
slider_constraint->setLinearLowerLimit(btVector3(-left_x, -under_y, 0));
slider_constraint->setLinearUpperLimit(btVector3(right_x, above_y, 0));
}
EAPI void
ephysics_constraint_slider_linear_limit_get(const EPhysics_Constraint *constraint, Evas_Coord *left_x, Evas_Coord *under_y, Evas_Coord *right_x, Evas_Coord *above_y)
{
btGeneric6DofConstraint *slider_constraint;
btVector3 linear_limit;
int rate;
if (!constraint)
{
ERR("Can't get constraint's linear limit, constraint is null.");
return;
}
if (constraint->type != EPHYSICS_CONSTRAINT_SLIDER)
{
ERR("Can't get linear limit, this is not an slider constraint.");
return;
}
rate = ephysics_world_rate_get(constraint->world);
slider_constraint = (btGeneric6DofConstraint *)constraint->bt_constraint;
if (left_x || under_y)
slider_constraint->getLinearLowerLimit(linear_limit);
if (left_x) *left_x = linear_limit.getX() * rate;
if (under_y) *under_y = linear_limit.getY() * rate;
if (right_x || above_y)
slider_constraint->getLinearUpperLimit(linear_limit);
if (right_x) *right_x = linear_limit.getX() * rate;
if (above_y) *above_y = linear_limit.getY() * rate;
}
EAPI void
ephysics_constraint_slider_angular_limit_set(EPhysics_Constraint *constraint, Evas_Coord counter_clock_z, Evas_Coord clock_wise_z)
{
btGeneric6DofConstraint *slider_constraint;
if (!constraint)
{
ERR("Can't set constraint's angular limit, constraint is null.");
return;
}
if (constraint->type != EPHYSICS_CONSTRAINT_SLIDER)
{
ERR("Can't set angular limit, this is not an slider constraint.");
return;
}
slider_constraint = (btGeneric6DofConstraint *)constraint->bt_constraint;
slider_constraint->setAngularLowerLimit(btVector3(0, 0,
-counter_clock_z/RAD_TO_DEG));
slider_constraint->setAngularUpperLimit(btVector3(0, 0,
clock_wise_z/RAD_TO_DEG));
}
EAPI void
ephysics_constraint_slider_angular_limit_get(const EPhysics_Constraint *constraint, Evas_Coord *counter_clock_z, Evas_Coord *clock_wise_z)
{
btGeneric6DofConstraint *slider_constraint;
btVector3 angular_limit;
if (!constraint)
{
ERR("Can't get constraint's angular limit, constraint is null.");
return;
}
if (constraint->type != EPHYSICS_CONSTRAINT_SLIDER)
{
ERR("Can't get angular limit, this is not an slider constraint.");
return;
}
slider_constraint = (btGeneric6DofConstraint *)constraint->bt_constraint;
if (counter_clock_z)
{
slider_constraint->getAngularLowerLimit(angular_limit);
*counter_clock_z = angular_limit.getZ();
}
if (clock_wise_z)
{
slider_constraint->getAngularUpperLimit(angular_limit);
*clock_wise_z = angular_limit.getZ();
}
}
EAPI EPhysics_Constraint *
ephysics_constraint_p2p_add(EPhysics_Body *body1, EPhysics_Body *body2, Evas_Coord anchor_b1_x, Evas_Coord anchor_b1_y, Evas_Coord anchor_b2_x, Evas_Coord anchor_b2_y)
{
EPhysics_Constraint *constraint;
int rate;
@ -60,6 +226,7 @@ ephysics_constraint_add(EPhysics_Body *body1, EPhysics_Body *body2, Evas_Coord a
return NULL;
}
constraint->type = EPHYSICS_CONSTRAINT_P2P;
constraint->world = ephysics_body_world_get(body1);
ephysics_world_constraint_add(constraint->world, constraint->bt_constraint);

View File

@ -42,6 +42,8 @@
extern "C" {
#endif
#define RAD_TO_DEG 57.29582 /* 2 * pi radians == 360 degree */
typedef enum _EPhysics_World_Boundary
{
EPHYSICS_WORLD_BOUNDARY_TOP,