EPhysics: generic constraint

This patch changes how constraints are created and configured, now we
use a bullet generic implementation which let us operate on the 6
degrees of freedom(linear and angular ones).

We have used 6dof for slider constraint but now we assume 2 types of
constraints, single body - simply ephysics_constraint_add(body) - and a linked
one - ephysics_constraint_linked_add(body1, body2) used to constrain 2 bodies
linked together.

Having said that we introduce the following changes:

+ migrate p2p constraint to 6Dof

We want to have a constraint api generic enouth to allow many different
constraint behaviour, 6Dof was picked to do that, so p2p needs a migration.

+ move ephysics_constraint_slider_* functions

Since the whole constraint infra-sctructure is being migrated to 6Dof the
linear and angular limit functions - previously used only by slider constraint -
now looks more generic enough to be used by constraint in general.

+ add constraint anchor API

Instead of telling the anchoring positioning in the constraint creating we have
set it's default value to the the middle os the body and if the user wants to change
it call ephysics_constraint_anchor_set and reset it.

The ephysics_constraint_anchor_set() considers the canvas coordinate instead of using
the body orientation. So now one can tell a constraints anchor is set to 100, 10, 0
in the canvas coordinate system and not (body_center.x - 20, body_center.y - 5, body_center.z - 1).

+ constraint migrate the bt_constraint

Since we're working only with 6Dof constraints it is reasonable to change the constraints
bt_constraint field to btGeneric6DofConstraint.

+ add 3 axes to constraints

Now constraints API knows about x, y and z axes - linear and angular limiting, anchor
setting and the constraint creation functions are fully supported.

+ constraint calls are renamed

The constraint calls were renamed so ephysics_constraint_p2p_add() now is known as
ephysics_constraint_linked_add() and ephysics_constraint_slider_add() became
ephysics_constraint_add() where the first one is meant for constrain 2 bodies and
the second one for single body constraints.

--This line, and those below, will be ignored--


SVN revision: 79848
This commit is contained in:
Leandro Dorileo 2012-11-29 18:51:51 +00:00
parent 603239627c
commit 0b558bc80c
6 changed files with 335 additions and 218 deletions

View File

@ -4,12 +4,27 @@
#include "ephysics_test.h"
static void
_constraint_set(Test_Data *test_data, EPhysics_Body *body1, EPhysics_Body *body2)
{
EPhysics_Constraint *constraint;
Evas_Coord b1x, b1y, b1z, b1w, b1h, b1d, b2x, b2y, b2z, b2w, b2h, b2d;
ephysics_body_geometry_get(body1, &b1x, &b1y, &b1z, &b1w, &b1h, &b1d);
ephysics_body_geometry_get(body2, &b2x, &b2y, &b2z, &b2w, &b2h, &b2d);
constraint = ephysics_constraint_linked_add(body1, body2);
ephysics_constraint_anchor_set(constraint, b1x + b1w / 2, b1y + b1h / 2 + 100,
b1z, b2x + b2w / 2, b2y + b2h / 2, b2z);
test_data->constraints = eina_list_append(test_data->constraints, constraint);
}
static void
_world_populate(Test_Data *test_data)
{
EPhysics_Body *box_body1, *box_body2;
Evas_Object *box1, *box2, *sh1, *sh2;
EPhysics_Constraint *constraint;
sh1 = elm_layout_add(test_data->win);
elm_layout_file_set(
@ -52,18 +67,15 @@ _world_populate(Test_Data *test_data)
test_data->evas_objs = eina_list_append(test_data->evas_objs, box2);
box_body2 = ephysics_body_box_add(test_data->world);
ephysics_body_mass_set(box_body2, 5);
ephysics_body_evas_object_set(box_body2, box2, EINA_TRUE);
ephysics_body_mass_set(box_body2, 5);
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_p2p_add(box_body1, box_body2, 0, 100, 0,
0);
test_data->constraints = eina_list_append(test_data->constraints,
constraint);
_constraint_set(test_data, box_body1, box_body2);
}
static void

View File

@ -60,10 +60,10 @@ _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_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);
constraint = ephysics_constraint_add(box_body2);
ephysics_constraint_linear_limit_set(constraint, 0, 0, 0,
HEIGHT - (HEIGHT / 8), 0, 0);
ephysics_constraint_angular_limit_set(constraint, 0, 0, 0, 0, 0, 45);
test_data->constraints = eina_list_append(test_data->constraints,
constraint);
@ -91,9 +91,8 @@ _world_populate(Test_Data *test_data)
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);
constraint = ephysics_constraint_add(box_body3);
ephysics_constraint_linear_limit_set(constraint, WIDTH - 120, 0, 0, 0, 0, 0);
ephysics_body_central_impulse_apply(box_body3, -240, 0, 0);
test_data->constraints = eina_list_append(test_data->constraints,
constraint);
@ -122,8 +121,8 @@ _world_populate(Test_Data *test_data)
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);
constraint = ephysics_constraint_add(box_body4);
ephysics_constraint_linear_limit_set(constraint, WIDTH / 3, 0, 0, 0, 0, 0);
ephysics_body_central_impulse_apply(box_body4, -600, 0, 0);
test_data->constraints = eina_list_append(test_data->constraints,
constraint);

View File

@ -4397,123 +4397,192 @@ EAPI Eina_Bool ephysics_body_clockwise_get(const EPhysics_Body *body);
* between bodies and the world. Constraints can limit movement angle,
* translation, or work like a motor.
*
* Constraints can be created with @ref ephysics_constraint_p2p_add()
* or @ref ephysics_constraint_slider_add() and removed
* Constraints can be created with @ref ephysics_constraint_linked_add()
* or @ref ephysics_constraint_add() and removed
* with @ref ephysics_constraint_del().
* Can be applied between two bodies or between a body and the world.
*/
typedef struct _EPhysics_Constraint EPhysics_Constraint; /**< Constraint handle, used to limit bodies movements. Created with @ref ephysics_constraint_p2p_add() or @ref ephysics_constraint_slider_add() and deleted with @ref ephysics_constraint_del(). */
typedef struct _EPhysics_Constraint EPhysics_Constraint; /**< Constraint handle, used to limit bodies movements. Created with @ref ephysics_constraint_linked_add() or @ref ephysics_constraint_add() and deleted with @ref ephysics_constraint_del(). */
/**
* @brief
* 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.
* The constraint will join two bodies(@p body1 and @p body2) with angular and
* linear movements limited by calling ephysics_constraint_linear_limit_set()
* and ephysics_constraint_angular_limit_set(). Anchors values can be defined
* with ephysics_constraint_anchor_set().
*
* @param body1 The first body to apply the constraint.
* @param body2 The second body to apply the constraint.
* @param anchor_b1_x The first body X anchor.
* @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 p2p(point to point) constraint or @c NULL, on errors.
* @return A new linked(joining 2 bodies) constraint or @c NULL, on errors.
*
* @see ephysics_constraint_del().
*
* @ingroup EPhysics_Constraint
*/
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);
EAPI EPhysics_Constraint *ephysics_constraint_linked_add(EPhysics_Body *body1, EPhysics_Body *body2);
/**
* @brief
* Create a new slider constraint.
* Change the constraints anchors values on both constrained bodies.
*
* The constraint will limit the linear and angular moving of a body.
* @note By default the anchors are in the middle of a body, if a body of 20, 20
* is positioned at (10, 10) then its anchor is set to (20, 20).
*
* @note There`s no need to inform @p anchor_b2_x, @p anchor_b2_y and @p
* anchor_b2_z if the constraint has been created using
* ephysics_constraint_add().
*
* @param constraint The constraint to be set.
* @param anchor_b1_x The first body X anchor.
* @param anchor_b1_y The first body Y anchor.
* @param anchor_b1_z The first body Z anchor.
* @param anchor_b2_x The second body X anchor.
* @param anchor_b2_y The second body Y anchor.
* @param anchor_b2_z The second body Z anchor.
*
* @see ephysics_constraint_anchor_get().
* @see ephysics_constraint_linked_add().
*
* @ingroup EPhysics_Constraint
*/
EAPI void ephysics_constraint_anchor_set(EPhysics_Constraint *constraint, Evas_Coord anchor_b1_x, Evas_Coord anchor_b1_y, Evas_Coord anchor_b1_z, Evas_Coord anchor_b2_x, Evas_Coord anchor_b2_y, Evas_Coord anchor_b2_z);
/**
* @brief
* Get the constraints anchors values on both constrained bodies.
*
* @param constraint The constraint to get anchor values from.
* @param anchor_b1_x Pointer to an Evas_Coord in which to store the first body
* X anchor value.
* @param anchor_b1_y Pointer to an Evas_Coord in which to store the first body
* Y anchor value.
* @param anchor_b1_z Pointer to an Evas_Coord in which to store the first body
* Z anchor value.
* @param anchor_b2_x Pointer to an Evas_Coord in which to store the second body
* X anchor value.
* @param anchor_b2_y Pointer to an Evas_Coord in which to store the second body
* Y anchor value.
* @param anchor_b2_z Pointer to an Evas_Coord in which to store the second body
* Z anchor value.
*
* @see ephysics_constraint_anchor_set().
* @see ephysics_constraint_linked_add().
*
* @ingroup EPhysics_Constraint
*/
EAPI void ephysics_constraint_anchor_get(const EPhysics_Constraint *constraint, Evas_Coord *anchor_b1_x, Evas_Coord *anchor_b1_y, Evas_Coord *anchor_b1_z, Evas_Coord *anchor_b2_x, Evas_Coord *anchor_b2_y, Evas_Coord *anchor_b2_z);
/**
* @brief
* Create a new constraint.
*
* The constraint will limit the linear and angular moving of a body. This simple
* constraint is designated to constraint a single body.
*
* @param body The body to apply the constraint.
*
* @see ephysics_constraint_slider_linear_limit_set() for linear moving limit
* @see ephysics_constraint_linear_limit_set() for linear moving limit
* configuration.
* @see ephysics_constraint_slider_angular_limit_set() for angular moving limit
* @see ephysics_constraint_angular_limit_set() for angular moving limit
* configuration.
* @return A new slider constraint or @c NULL on erros.
* @return A new constraint or @c NULL on erros.
*
* @see ephysics_constraint_del().
*
* @ingroup EPhysics_Constraint
*/
EAPI EPhysics_Constraint *ephysics_constraint_slider_add(EPhysics_Body *body);
EAPI EPhysics_Constraint *ephysics_constraint_add(EPhysics_Body *body);
/**
* @brief
* Define the linear moving limits of a slider @p constraint.
* Define the linear moving limits of a @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.
* want to limit the movements on X, Y and Z axis where lower == upper axis
* will be locked, lower > upper axis is free, lower < upper axis is limited to
* the range.
*
* 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.
* @param lower_x The lower linear moving limit on X axis.
* @param upper_x The upper linear moving limit on X axis.
* @param lower_y The lower linear moving limit on Y axis.
* @param upper_y The upper linear moving limit on Y axis.
* @param lower_z The lower linear moving limit on Z axis.
* @param upper_z The upper linear moving limit on Z axis.
*
* @see ephysics_constraint_slider_linear_limit_get()
*
* @see ephysics_constraint_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);
EAPI void ephysics_constraint_linear_limit_set(EPhysics_Constraint *constraint, Evas_Coord lower_x, Evas_Coord upper_x, Evas_Coord lower_y, Evas_Coord upper_y, Evas_Coord lower_z, Evas_Coord upper_z);
/**
* @brief
* Get the linear moving limits of a slider constraint.
* Get the linear moving limits of a @p 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.
* @param lower_x Pointer to set with the lower limit to the X axis.
* @param upper_x Pointer to set with the upper limit to the X axis.
* @param lower_y Pointer to set with the lower limit to the Y axis.
* @param upper_y Pointer to set with the upper limit to the Y axis.
* @param lower_z Pointer to set with the lower limit to the Z axis.
* @param upper_z Pointer to set with the upper limit to the Z axis.
*
* @see ephysics_constraint_slider_linear_limit_set()
* @see ephysics_constraint_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);
EAPI void ephysics_constraint_linear_limit_get(const EPhysics_Constraint *constraint, Evas_Coord *lower_x, Evas_Coord *upper_x, Evas_Coord *lower_y, Evas_Coord *upper_y, Evas_Coord *lower_z, Evas_Coord *upper_z);
/**
* @brief
* Set the angular moving limits of a slider @p constraint.
* Set the angular moving limits of a @p constraint.
*
* The angular moving limits is defined in degrees and will limit the moving on
* Z axis - counter clockwise and clockwise directions.
*
* @param constraint The constraint to be set.
* @param counter_clock_x Amount of degrees from 0.0 to 360.0 to limit counter
* clockwise rotation on X axis.
* @param clock_wise_x Amount of degrees from 0.0 to 360.0 to limit clockwise
* rotation on X axis.
* @param counter_clock_y Amount of degrees from 0.0 to 360.0 to limit counter
* clockwise rotation o Y axis.
* @param clock_wise_y Amount of degrees from 0.0 to 360.0 to limit clockwise
* rotation on Y axis.
* @param counter_clock_z Amount of degrees from 0.0 to 360.0 to limit
* counter clockwise rotation.
* counter clockwise rotation on Z axis.
* @param clock_wise_z Amount of degrees from 0.0 to 360.0 to limit clockwise
* rotation.
* rotation on Z axis.
*
* @see ephysics_constraint_slider_angular_limit_get()
* @see ephysics_constraint_angular_limit_get()
* @ingroup EPhysics_Constraint
*/
EAPI void ephysics_constraint_slider_angular_limit_set(EPhysics_Constraint *constraint, double counter_clock_z, double clock_wise_z);
EAPI void ephysics_constraint_angular_limit_set(EPhysics_Constraint *constraint, double counter_clock_x, double clock_wise_x, double counter_clock_y, double clock_wise_y, double counter_clock_z, double clock_wise_z);
/**
* @brief
* Get the angular moving limits of a slider @p constraint.
* Get the angular moving limits of a @p constraint.
*
* @param constraint The constraint to get the angular limits from.
* @param counter_clock_x Pointer to set with the counter clockwise limmit
* degrees on X axis.
* @param clock_wise_x Pointer to set with the clockwise limit degrees on X axis.
* @param counter_clock_y Pointer to set with the counter clockwise limit
* degrees on Y axis.
* @param clock_wise_y Pointer to set with the clockwise limit degrees on Y axis.
* @param counter_clock_z Pointer to set with the counter clockwise limit
* degrees.
* @param clock_wise_z Pointer to set with the clockwise limit degrees.
* degrees on Z axis.
* @param clock_wise_z Pointer to set with the clockwise limit degrees on Z axis.
*
* @see ephysics_constraint_slider_angular_limit_set()
* @see ephysics_constraint_angular_limit_set()
* @ingroup EPhysics_Constraint
*/
EAPI void ephysics_constraint_slider_angular_limit_get(const EPhysics_Constraint *constraint, double *counter_clock_z, double *clock_wise_z);
EAPI void ephysics_constraint_angular_limit_get(const EPhysics_Constraint *constraint, double *counter_clock_x, double *clock_wise_x, double *counter_clock_y, double *clock_wise_y, double *counter_clock_z, double *clock_wise_z);
/**
* @brief
@ -4521,7 +4590,7 @@ EAPI void ephysics_constraint_slider_angular_limit_get(const EPhysics_Constraint
*
* @param constraint The constraint to be deleted.
*
* @see ephysics_constraint_p2p_add() for more details.
* @see ephysics_constraint_linked_add() for more details.
* @see ephysics_constraint_slider_add() for more details.
*
* @ingroup EPhysics_Constraint

View File

@ -8,107 +8,67 @@
extern "C" {
#endif
typedef enum _EPhysics_Constraint_Type {
EPHYSICS_CONSTRAINT_P2P,
EPHYSICS_CONSTRAINT_SLIDER,
} EPhysics_Constraint_Type;
struct _EPhysics_Constraint {
btTypedConstraint *bt_constraint;
btGeneric6DofConstraint *bt_constraint;
EPhysics_World *world;
EPhysics_Constraint_Type type;
struct {
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;
} p2p;
EPhysics_Body *bodies[2];
};
/* FIXME: it shouldn't be this way.
* All constraints should be generic and have all these options
* set after add().
*/
static Eina_Bool
_ephysics_constraint_p2p_set(EPhysics_Constraint *constraint, double rate)
static void
_ephysics_constraint_linear_limit_get(const EPhysics_Constraint *constraint, Evas_Coord *lower_x, Evas_Coord *upper_x, Evas_Coord *lower_y, Evas_Coord *upper_y, Evas_Coord *lower_z, Evas_Coord *upper_z, double rate)
{
if (!constraint->p2p.body2)
constraint->bt_constraint = new btPoint2PointConstraint(
*ephysics_body_rigid_body_get(constraint->p2p.body1),
btVector3(constraint->p2p.anchor_b1_x / rate,
constraint->p2p.anchor_b1_y / rate, 0));
else
constraint->bt_constraint = new btPoint2PointConstraint(
*ephysics_body_rigid_body_get(constraint->p2p.body1),
*ephysics_body_rigid_body_get(constraint->p2p.body2),
btVector3(constraint->p2p.anchor_b1_x / rate,
constraint->p2p.anchor_b1_y / rate, 0),
btVector3(constraint->p2p.anchor_b2_x / rate,
constraint->p2p.anchor_b2_y / rate, 0));
btVector3 linear_limit;
if (!constraint->bt_constraint)
if (lower_x || lower_y || lower_z)
{
ERR("Failed to create a btConstraint");
free(constraint);
return EINA_FALSE;
constraint->bt_constraint->getLinearLowerLimit(linear_limit);
if (lower_x) *lower_x = linear_limit.getX() * rate;
if (lower_y) *lower_y = linear_limit.getY() * rate;
if (lower_z) *lower_z = linear_limit.getZ() * rate;
}
constraint->type = EPHYSICS_CONSTRAINT_P2P;
ephysics_world_constraint_add(constraint->world, constraint,
constraint->bt_constraint);
if (upper_x || upper_y || upper_z)
{
constraint->bt_constraint->getLinearUpperLimit(linear_limit);
return EINA_TRUE;
if (upper_x) *upper_x = linear_limit.getX() * rate;
if (upper_y) *upper_y = linear_limit.getY() * rate;
if (upper_z) *upper_z = linear_limit.getZ() * rate;
}
}
static void
_ephysics_constraint_p2p_recalc(EPhysics_Constraint *constraint, double rate)
_ephysics_constraint_linear_limit_set(EPhysics_Constraint *constraint, Evas_Coord lower_x, Evas_Coord upper_x, Evas_Coord lower_y, Evas_Coord upper_y, Evas_Coord lower_z, Evas_Coord upper_z, double rate)
{
ephysics_world_constraint_del(constraint->world, constraint,
constraint->bt_constraint);
delete constraint->bt_constraint;
lower_x = (lower_x) / rate;
upper_x = (upper_x) / rate;
_ephysics_constraint_p2p_set(constraint, rate);
}
lower_y = (lower_y) / rate;
upper_y = (upper_y) / rate;
static 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, double rate)
{
btGeneric6DofConstraint *slider_constraint;
lower_z = (lower_z) / rate;
upper_z = (upper_z) / rate;
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));
constraint->bt_constraint->setLinearLowerLimit(btVector3(-lower_x, -upper_y,
-lower_z));
constraint->bt_constraint->setLinearUpperLimit(btVector3(upper_x, upper_y,
upper_z));
}
void
ephysics_constraint_recalc(EPhysics_Constraint *constraint, double rate)
{
Evas_Coord left_x, under_y, right_x, above_y;
Evas_Coord lower_x, upper_x, lower_y, upper_y, lower_z, upper_z;
if (constraint->type == EPHYSICS_CONSTRAINT_P2P)
{
_ephysics_constraint_p2p_recalc(constraint, rate);
return;
}
ephysics_constraint_slider_linear_limit_get(constraint, &left_x, &under_y,
&right_x, &above_y);
_ephysics_constraint_slider_linear_limit_set(constraint, left_x, under_y,
right_x, above_y, rate);
_ephysics_constraint_linear_limit_get(constraint, &lower_x, &upper_x,
&lower_y, &upper_y, &lower_z, &upper_z, rate);
_ephysics_constraint_linear_limit_set(constraint, lower_x, upper_x, lower_y,
upper_y, lower_z, upper_z, rate);
}
EAPI EPhysics_Constraint *
ephysics_constraint_slider_add(EPhysics_Body *body)
ephysics_constraint_add(EPhysics_Body *body)
{
EPhysics_Constraint *constraint;
btTransform trans;
@ -119,13 +79,6 @@ ephysics_constraint_slider_add(EPhysics_Body *body)
return NULL;
}
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
{
ERR("Constraints are allowed only between rigid -> rigid bodies or "
"rigid -> soft bodies");
return NULL;
}
constraint = (EPhysics_Constraint *) calloc(1, sizeof(EPhysics_Constraint));
if (!constraint)
{
@ -135,6 +88,7 @@ ephysics_constraint_slider_add(EPhysics_Body *body)
ephysics_world_lock_take(ephysics_body_world_get(body));
trans.setIdentity();
trans.setOrigin(btVector3(0, 0, 0));
constraint->bt_constraint = new
btGeneric6DofConstraint(*ephysics_body_rigid_body_get(body), trans,
false);
@ -146,7 +100,7 @@ ephysics_constraint_slider_add(EPhysics_Body *body)
return NULL;
}
constraint->type = EPHYSICS_CONSTRAINT_SLIDER;
constraint->bodies[0] = body;
constraint->world = ephysics_body_world_get(body);
ephysics_world_constraint_add(constraint->world, constraint,
constraint->bt_constraint);
@ -157,32 +111,26 @@ ephysics_constraint_slider_add(EPhysics_Body *body)
}
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)
ephysics_constraint_linear_limit_set(EPhysics_Constraint *constraint, Evas_Coord lower_x, Evas_Coord upper_x, Evas_Coord lower_y, Evas_Coord upper_y, Evas_Coord lower_z, Evas_Coord upper_z)
{
double 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;
}
ephysics_world_lock_take(constraint->world);
_ephysics_constraint_slider_linear_limit_set(
constraint, left_x, under_y, right_x, above_y,
ephysics_world_rate_get(constraint->world));
rate = ephysics_world_rate_get(constraint->world);
_ephysics_constraint_linear_limit_set(constraint, lower_x, upper_x, lower_y,
upper_y, lower_z, upper_z, rate);
ephysics_world_lock_release(constraint->world);
}
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)
ephysics_constraint_linear_limit_get(const EPhysics_Constraint *constraint, Evas_Coord *lower_x, Evas_Coord *upper_x, Evas_Coord *lower_y, Evas_Coord *upper_y, Evas_Coord *lower_z, Evas_Coord *upper_z)
{
btGeneric6DofConstraint *slider_constraint;
btVector3 linear_limit;
int rate;
if (!constraint)
@ -191,31 +139,14 @@ ephysics_constraint_slider_linear_limit_get(const EPhysics_Constraint *constrain
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;
_ephysics_constraint_linear_limit_get(constraint, lower_x, upper_x, lower_y,
upper_y, lower_z, upper_z, rate);
}
EAPI void
ephysics_constraint_slider_angular_limit_set(EPhysics_Constraint *constraint, double counter_clock_z, double clock_wise_z)
ephysics_constraint_angular_limit_set(EPhysics_Constraint *constraint, double counter_clock_x, double clock_wise_x, double counter_clock_y, double clock_wise_y, double counter_clock_z, double clock_wise_z)
{
btGeneric6DofConstraint *slider_constraint;
if (!constraint)
{
@ -223,25 +154,20 @@ ephysics_constraint_slider_angular_limit_set(EPhysics_Constraint *constraint, do
return;
}
if (constraint->type != EPHYSICS_CONSTRAINT_SLIDER)
{
ERR("Can't set angular limit, this is not an slider constraint.");
return;
}
ephysics_world_lock_take(constraint->world);
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));
constraint->bt_constraint->setAngularLowerLimit(btVector3(
-counter_clock_x / RAD_TO_DEG, -counter_clock_y / RAD_TO_DEG,
-counter_clock_z/RAD_TO_DEG));
constraint->bt_constraint->setAngularUpperLimit(btVector3(
clock_wise_x / RAD_TO_DEG, clock_wise_y / RAD_TO_DEG,
clock_wise_z/RAD_TO_DEG));
ephysics_world_lock_release(constraint->world);
}
EAPI void
ephysics_constraint_slider_angular_limit_get(const EPhysics_Constraint *constraint, double *counter_clock_z, double *clock_wise_z)
ephysics_constraint_angular_limit_get(const EPhysics_Constraint *constraint, double *counter_clock_x, double *clock_wise_x, double *counter_clock_y, double *clock_wise_y, double *counter_clock_z, double *clock_wise_z)
{
btGeneric6DofConstraint *slider_constraint;
btVector3 angular_limit;
if (!constraint)
@ -250,39 +176,148 @@ ephysics_constraint_slider_angular_limit_get(const EPhysics_Constraint *constrai
return;
}
if (constraint->type != EPHYSICS_CONSTRAINT_SLIDER)
if (counter_clock_x)
{
ERR("Can't get angular limit, this is not an slider constraint.");
return;
constraint->bt_constraint->getAngularLowerLimit(angular_limit);
*counter_clock_x = angular_limit.getX() * RAD_TO_DEG;
}
if (clock_wise_x)
{
constraint->bt_constraint->getAngularUpperLimit(angular_limit);
*clock_wise_x = angular_limit.getX() * RAD_TO_DEG;
}
if (counter_clock_y)
{
constraint->bt_constraint->getAngularLowerLimit(angular_limit);
*counter_clock_y = angular_limit.getY() * RAD_TO_DEG;
}
if (clock_wise_y)
{
constraint->bt_constraint->getAngularUpperLimit(angular_limit);
*clock_wise_y = angular_limit.getY() * RAD_TO_DEG;
}
slider_constraint = (btGeneric6DofConstraint *)constraint->bt_constraint;
if (counter_clock_z)
{
slider_constraint->getAngularLowerLimit(angular_limit);
*counter_clock_z = angular_limit.getZ();
constraint->bt_constraint->getAngularLowerLimit(angular_limit);
*counter_clock_z = angular_limit.getZ() * RAD_TO_DEG;
}
if (clock_wise_z)
{
slider_constraint->getAngularUpperLimit(angular_limit);
*clock_wise_z = angular_limit.getZ();
constraint->bt_constraint->getAngularUpperLimit(angular_limit);
*clock_wise_z = angular_limit.getZ() * RAD_TO_DEG;
}
}
EAPI void
ephysics_constraint_anchor_set(EPhysics_Constraint *constraint, Evas_Coord anchor_b1_x, Evas_Coord anchor_b1_y, Evas_Coord anchor_b1_z, Evas_Coord anchor_b2_x, Evas_Coord anchor_b2_y, Evas_Coord anchor_b2_z)
{
btTransform anchor_b1;
btTransform anchor_b2;
btTransform center_mass;
double rate;
Evas_Coord b1x, b1y, b1z, b1w, b1h, b1d, b2x, b2y, b2z, b2w, b2h, b2d, wx, wy,
wh;
btScalar ab1x, ab1y, ab1z, ab2x, ab2y, ab2z;
if (!constraint)
{
ERR("Can't set constraint's anchors, constraint is null.");
return;
}
ephysics_world_lock_take(constraint->world);
ephysics_world_render_geometry_get(constraint->world, &wx, &wy, NULL, NULL,
&wh, NULL);
ephysics_body_geometry_get(constraint->bodies[0], &b1x, &b1y, &b1z, &b1w,
&b1h, &b1d);
rate = ephysics_world_rate_get(constraint->world);
ab1x = (anchor_b1_x - (b1x + b1w / 2)) / rate;
ab1y = (anchor_b1_y - (b1y + b1h / 2)) / rate;
ab1z = (anchor_b1_z - (b1z + b1d / 2)) / rate;
DBG("body1 anchor set to: %lf, %lf, %lf", ab1x, ab1y, ab1z);
anchor_b1.setIdentity();
anchor_b1.setOrigin(btVector3(ab1x, ab1y, ab1z));
if (constraint->bodies[1])
{
ephysics_body_geometry_get(constraint->bodies[1], &b2x, &b2y, &b2z, &b2w,
&b2h, &b2d);
ab2x = (anchor_b2_x - (b2x + b2w / 2)) / rate;
ab2y = (anchor_b2_y - (b2y + b2h / 2)) / rate;
ab2z = (anchor_b2_z - (b2z + b2d / 2)) / rate;
DBG("body2 anchor set to: %lf, %lf, %lf", ab2x, ab2y, ab2z);
anchor_b2.setIdentity();
anchor_b2.setOrigin(btVector3(ab2x, ab2y, ab2z));
}
else
{
anchor_b2.setIdentity();
anchor_b2.setOrigin(btVector3(anchor_b1.getOrigin().x(),
anchor_b1.getOrigin().y(),
anchor_b1.getOrigin().z()));
center_mass = constraint->bodies[0]->rigid_body->
getCenterOfMassTransform();
anchor_b1.setIdentity();
anchor_b1 = center_mass * anchor_b2;
}
constraint->bt_constraint->setFrames(anchor_b1, anchor_b2);
ephysics_world_lock_release(constraint->world);
}
EAPI void
ephysics_constraint_anchor_get(const EPhysics_Constraint *constraint, Evas_Coord *anchor_b1_x, Evas_Coord *anchor_b1_y, Evas_Coord *anchor_b1_z, Evas_Coord *anchor_b2_x, Evas_Coord *anchor_b2_y, Evas_Coord *anchor_b2_z)
{
btTransform anchor_b1;
btTransform anchor_b2;
double rate;
if (!constraint)
{
ERR("Can't set constraint's anchors, constraint is null.");
return;
}
rate = ephysics_world_rate_get(constraint->world);
anchor_b1 = constraint->bt_constraint->getFrameOffsetA();
anchor_b2 = constraint->bt_constraint->getFrameOffsetB();
if (anchor_b1_x) *anchor_b1_x = round(anchor_b1.getOrigin().x() * rate);
if (anchor_b1_y) *anchor_b1_y = round(anchor_b1.getOrigin().y() * rate);
if (anchor_b1_z) *anchor_b1_z = round(anchor_b1.getOrigin().z() * rate);
if (anchor_b2_x) *anchor_b2_x = round(anchor_b2.getOrigin().x() * rate);
if (anchor_b2_y) *anchor_b2_y = round(anchor_b2.getOrigin().y() * rate);
if (anchor_b2_z) *anchor_b2_z = round(anchor_b2.getOrigin().z() * rate);
}
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_linked_add(EPhysics_Body *body1, EPhysics_Body *body2)
{
EPhysics_Constraint *constraint;
if (!body1)
if (!body1 || !body2)
{
ERR("To create a constraint body1 must to be non null.");
ERR("To create a linked constraint body1 and bod2 must to be non null.");
return NULL;
}
if ((body2) &&
(ephysics_body_world_get(body1) != ephysics_body_world_get(body2)))
if (ephysics_body_world_get(body1) != ephysics_body_world_get(body2))
{
ERR("To create a constraint both bodies must belong to the same"
"world.");
@ -305,23 +340,25 @@ ephysics_constraint_p2p_add(EPhysics_Body *body1, EPhysics_Body *body2, Evas_Coo
}
constraint->world = ephysics_body_world_get(body1);
constraint->p2p.body1 = body1;
constraint->p2p.body2 = body2;
constraint->p2p.anchor_b1_x = anchor_b1_x;
constraint->p2p.anchor_b1_y = anchor_b1_y;
constraint->p2p.anchor_b2_x = anchor_b2_x;
constraint->p2p.anchor_b2_y = anchor_b2_y;
constraint->bodies[0] = body1;
constraint->bodies[1] = body2;
ephysics_world_lock_take(constraint->world);
if (!_ephysics_constraint_p2p_set(
constraint, ephysics_world_rate_get(ephysics_body_world_get(
constraint->p2p.body1))))
constraint->bt_constraint = new btGeneric6DofConstraint(
*ephysics_body_rigid_body_get(body1), *ephysics_body_rigid_body_get(body2),
btTransform(), btTransform(), false);
if (!constraint->bt_constraint)
{
ephysics_world_lock_release(constraint->world);
free(constraint);
return NULL;
}
ephysics_world_constraint_add(constraint->world, constraint,
constraint->bt_constraint);
ephysics_world_lock_release(constraint->world);
INF("Constraint added.");
return constraint;

View File

@ -175,8 +175,8 @@ int ephysics_world_shutdown(void);
Eina_Bool ephysics_world_body_add(EPhysics_World *world, EPhysics_Body *body);
Eina_Bool ephysics_world_body_del(EPhysics_World *world, EPhysics_Body *body);
Eina_Bool ephysics_world_soft_body_add(EPhysics_World *world, EPhysics_Body *body);
void ephysics_world_constraint_add(EPhysics_World *world, EPhysics_Constraint *constraint, btTypedConstraint *bt_constraint);
void ephysics_world_constraint_del(EPhysics_World *world, EPhysics_Constraint *constraint, btTypedConstraint *bt_constraint);
void ephysics_world_constraint_add(EPhysics_World *world, EPhysics_Constraint *constraint, btGeneric6DofConstraint *bt_constraint);
void ephysics_world_constraint_del(EPhysics_World *world, EPhysics_Constraint *constraint, btGeneric6DofConstraint *bt_constraint);
void ephysics_body_world_boundaries_resize(EPhysics_World *world);
void ephysics_world_boundary_set(EPhysics_World *world, EPhysics_World_Boundary boundary, EPhysics_Body *body);
EPhysics_Body *ephysics_world_boundary_get(const EPhysics_World *world, EPhysics_World_Boundary boundary);

View File

@ -500,14 +500,14 @@ ephysics_world_soft_body_add(EPhysics_World *world, EPhysics_Body *body)
}
void
ephysics_world_constraint_add(EPhysics_World *world, EPhysics_Constraint *constraint, btTypedConstraint *bt_constraint)
ephysics_world_constraint_add(EPhysics_World *world, EPhysics_Constraint *constraint, btGeneric6DofConstraint *bt_constraint)
{
world->dynamics_world->addConstraint(bt_constraint);
world->dynamics_world->addConstraint(bt_constraint, true);
world->constraints = eina_list_append(world->constraints, constraint);
}
void
ephysics_world_constraint_del(EPhysics_World *world, EPhysics_Constraint *constraint, btTypedConstraint *bt_constraint)
ephysics_world_constraint_del(EPhysics_World *world, EPhysics_Constraint *constraint, btGeneric6DofConstraint *bt_constraint)
{
world->dynamics_world->removeConstraint(bt_constraint);
world->constraints = eina_list_remove(world->constraints, constraint);