aboutsummaryrefslogtreecommitdiffstats
path: root/legacy/ephysics/src/lib/ephysics_constraints.cpp
diff options
context:
space:
mode:
authorLeandro Dorileo <dorileo@profusion.mobi>2012-11-29 18:51:51 +0000
committerLeandro Dorileo <dorileo@profusion.mobi>2012-11-29 18:51:51 +0000
commit0b558bc80ce7c6ed4bae0c64fd0c37cd0c8a1fab (patch)
tree21bb2b60852cde6eb5d6e9fa2af43b3023380f2e /legacy/ephysics/src/lib/ephysics_constraints.cpp
parentexamples:codegen: Removing the usage of externals (diff)
downloadefl-0b558bc80ce7c6ed4bae0c64fd0c37cd0c8a1fab.tar.gz
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
Diffstat (limited to 'legacy/ephysics/src/lib/ephysics_constraints.cpp')
-rw-r--r--legacy/ephysics/src/lib/ephysics_constraints.cpp339
1 files changed, 188 insertions, 151 deletions
diff --git a/legacy/ephysics/src/lib/ephysics_constraints.cpp b/legacy/ephysics/src/lib/ephysics_constraints.cpp
index ed5c5c8411..f97af58659 100644
--- a/legacy/ephysics/src/lib/ephysics_constraints.cpp
+++ b/legacy/ephysics/src/lib/ephysics_constraints.cpp
@@ -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->type = EPHYSICS_CONSTRAINT_P2P;
- ephysics_world_constraint_add(constraint->world, constraint,
- constraint->bt_constraint);
+ constraint->bt_constraint->getLinearLowerLimit(linear_limit);
- return EINA_TRUE;
-}
+ 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;
+ }
-static void
-_ephysics_constraint_p2p_recalc(EPhysics_Constraint *constraint, double rate)
-{
- ephysics_world_constraint_del(constraint->world, constraint,
- constraint->bt_constraint);
- delete constraint->bt_constraint;
+ if (upper_x || upper_y || upper_z)
+ {
+ constraint->bt_constraint->getLinearUpperLimit(linear_limit);
- _ephysics_constraint_p2p_set(constraint, rate);
+ 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_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)
+_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)
{
- btGeneric6DofConstraint *slider_constraint;
-
- slider_constraint = (btGeneric6DofConstraint *)constraint->bt_constraint;
- rate = ephysics_world_rate_get(constraint->world);
+ lower_x = (lower_x) / rate;
+ upper_x = (upper_x) / rate;
- left_x = (left_x) / rate;
- right_x = (right_x) / rate;
+ lower_y = (lower_y) / rate;
+ upper_y = (upper_y) / rate;
- under_y = (under_y) / rate;
- above_y = (above_y) / rate;
+ lower_z = (lower_z) / rate;
+ upper_z = (upper_z) / 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;