forked from enlightenment/efl
EPhysics: improve convex shapes
Center of these shapes were wrong, now it's much better. But collision still seems a bit inaccurate. SVN revision: 75572
This commit is contained in:
parent
3627234fb8
commit
eae54a26ee
|
@ -9,68 +9,51 @@ _world_populate(Test_Data *test_data)
|
|||
{
|
||||
EPhysics_Shape *pentagon_shape, *hexagon_shape;
|
||||
EPhysics_Body *pentagon_body, *hexagon_body;
|
||||
EPhysics_Constraint *constraint;
|
||||
Evas_Object *pentagon, *hexagon;
|
||||
|
||||
pentagon = elm_image_add(test_data->win);
|
||||
elm_image_file_set(
|
||||
pentagon, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "pentagon");
|
||||
evas_object_move(pentagon, WIDTH / 3, HEIGHT / 2 - 30);
|
||||
evas_object_resize(pentagon, 70, 66);
|
||||
evas_object_resize(pentagon, 70, 68);
|
||||
evas_object_show(pentagon);
|
||||
test_data->evas_objs = eina_list_append(test_data->evas_objs, pentagon);
|
||||
|
||||
pentagon_shape = ephysics_shape_new();
|
||||
ephysics_shape_point_add(pentagon_shape, 0/70., 24/66.);
|
||||
ephysics_shape_point_add(pentagon_shape, 35/70., 0/66.);
|
||||
ephysics_shape_point_add(pentagon_shape, 70/70., 24/66.);
|
||||
ephysics_shape_point_add(pentagon_shape, 56/70., 66/66.);
|
||||
ephysics_shape_point_add(pentagon_shape, 14/70., 66/66.);
|
||||
ephysics_shape_point_add(pentagon_shape, -1, -9/33.);
|
||||
ephysics_shape_point_add(pentagon_shape, 0, -1);
|
||||
ephysics_shape_point_add(pentagon_shape, 1, -9/33.);
|
||||
ephysics_shape_point_add(pentagon_shape, -21/35., 1);
|
||||
ephysics_shape_point_add(pentagon_shape, 21/35., 1);
|
||||
|
||||
pentagon_body = ephysics_body_shape_add(test_data->world, pentagon_shape);
|
||||
ephysics_body_evas_object_set(pentagon_body, pentagon, EINA_TRUE);
|
||||
ephysics_body_restitution_set(pentagon_body, 1);
|
||||
ephysics_body_friction_set(pentagon_body, 0);
|
||||
test_data->bodies = eina_list_append(test_data->bodies, pentagon_body);
|
||||
|
||||
hexagon = elm_image_add(test_data->win);
|
||||
elm_image_file_set(
|
||||
hexagon, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "hexagon");
|
||||
evas_object_move(hexagon, WIDTH / 3 + 80, HEIGHT / 2 - 30 + 35);
|
||||
evas_object_move(hexagon, WIDTH / 3 + 80, HEIGHT / 2 - 30);
|
||||
evas_object_resize(hexagon, 70, 60);
|
||||
evas_object_show(hexagon);
|
||||
test_data->evas_objs = eina_list_append(test_data->evas_objs, hexagon);
|
||||
|
||||
hexagon_shape = ephysics_shape_new();
|
||||
ephysics_shape_point_add(hexagon_shape, 0, 0.5);
|
||||
ephysics_shape_point_add(hexagon_shape, 18/70., 0);
|
||||
ephysics_shape_point_add(hexagon_shape, 52/70., 0);
|
||||
ephysics_shape_point_add(hexagon_shape, 1, 0.5);
|
||||
ephysics_shape_point_add(hexagon_shape, 52/70., 1);
|
||||
ephysics_shape_point_add(hexagon_shape, 18/70., 1);
|
||||
ephysics_shape_point_add(hexagon_shape, 0, 30);
|
||||
ephysics_shape_point_add(hexagon_shape, 18, 0);
|
||||
ephysics_shape_point_add(hexagon_shape, 52, 0);
|
||||
ephysics_shape_point_add(hexagon_shape, 70, 30);
|
||||
ephysics_shape_point_add(hexagon_shape, 52, 60);
|
||||
ephysics_shape_point_add(hexagon_shape, 18, 60);
|
||||
|
||||
hexagon_body = ephysics_body_shape_add(test_data->world, hexagon_shape);
|
||||
ephysics_body_mass_set(hexagon_body, 5);
|
||||
ephysics_body_evas_object_set(hexagon_body, hexagon, EINA_TRUE);
|
||||
ephysics_body_restitution_set(hexagon_body, 1);
|
||||
ephysics_body_friction_set(hexagon_body, 0);
|
||||
test_data->bodies = eina_list_append(test_data->bodies, hexagon_body);
|
||||
|
||||
constraint = ephysics_constraint_p2p_add(pentagon_body, NULL, 8, 0,
|
||||
0, 0);
|
||||
test_data->constraints = eina_list_append(test_data->constraints,
|
||||
constraint);
|
||||
|
||||
constraint = ephysics_constraint_p2p_add(hexagon_body, NULL, 0, 0, 0, 0);
|
||||
test_data->constraints = eina_list_append(test_data->constraints,
|
||||
constraint);
|
||||
|
||||
ephysics_body_torque_impulse_apply(pentagon_body, 2);
|
||||
|
||||
ephysics_shape_del(pentagon_shape);
|
||||
ephysics_shape_del(hexagon_shape);
|
||||
|
||||
ephysics_world_serialize(test_data->world, "/tmp/test.bullet");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -86,6 +69,7 @@ _restart(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED_
|
|||
void
|
||||
test_shapes(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
|
||||
{
|
||||
EPhysics_Body *boundary;
|
||||
EPhysics_World *world;
|
||||
Test_Data *test_data;
|
||||
|
||||
|
@ -102,5 +86,12 @@ test_shapes(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info
|
|||
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_top_boundary_add(test_data->world);
|
||||
ephysics_body_left_boundary_add(test_data->world);
|
||||
ephysics_body_right_boundary_add(test_data->world);
|
||||
|
||||
_world_populate(test_data);
|
||||
}
|
||||
|
|
|
@ -205,6 +205,9 @@ EAPI void ephysics_shape_del(EPhysics_Shape *shape);
|
|||
* geometric shapes. The final shape will be constructed in such a way
|
||||
* it will have all the added points and will be convex.
|
||||
*
|
||||
* The center of mass will be the centroid, or geometric center of the
|
||||
* shape.
|
||||
*
|
||||
* The order of points doesn't matter.
|
||||
*
|
||||
* For example, to create a pentagon:
|
||||
|
@ -212,11 +215,11 @@ EAPI void ephysics_shape_del(EPhysics_Shape *shape);
|
|||
* @code
|
||||
* EPhysics_Shape *shape = ephysics_shape_new();
|
||||
*
|
||||
* ephysics_shape_point_add(shape, 0/70., 24/66.);
|
||||
* ephysics_shape_point_add(shape, 35/70., 0/66.);
|
||||
* ephysics_shape_point_add(shape, 70/70., 24/66.);
|
||||
* ephysics_shape_point_add(shape, 56/70., 66/66.);
|
||||
* ephysics_shape_point_add(shape, 14/70., 66/66.);
|
||||
* ephysics_shape_point_add(shape, 0, 24);
|
||||
* ephysics_shape_point_add(shape, 35, 0);
|
||||
* ephysics_shape_point_add(shape, 70, 24);
|
||||
* ephysics_shape_point_add(shape, 56, 66);
|
||||
* ephysics_shape_point_add(shape, 14, 66);
|
||||
*
|
||||
* ephysics_body_shape_add(world, shape);
|
||||
*
|
||||
|
@ -224,8 +227,8 @@ EAPI void ephysics_shape_del(EPhysics_Shape *shape);
|
|||
* @endcode
|
||||
*
|
||||
* @param shape The shape to be modified.
|
||||
* @param x Point position at x axis. Should be a value between 0 and 1.
|
||||
* @param y Point position at y axis. Should be a value between 0 and 1.
|
||||
* @param x Point position at x axis.
|
||||
* @param y Point position at y axis.
|
||||
* @return @c EINA_TRUE on success or EINA_FALSE on error.
|
||||
*
|
||||
* @see ephysics_shape_new().
|
||||
|
|
|
@ -193,7 +193,7 @@ ephysics_body_collision_group_list_get(const EPhysics_Body *body)
|
|||
}
|
||||
|
||||
static EPhysics_Body *
|
||||
_ephysics_body_add(EPhysics_World *world, btCollisionShape *collision_shape, const char *type)
|
||||
_ephysics_body_add(EPhysics_World *world, btCollisionShape *collision_shape, const char *type, double cm_x, double cm_y)
|
||||
{
|
||||
btRigidBody::btRigidBodyConstructionInfo *rigid_body_ci;
|
||||
btDefaultMotionState *motion_state;
|
||||
|
@ -244,6 +244,8 @@ _ephysics_body_add(EPhysics_World *world, btCollisionShape *collision_shape, con
|
|||
body->rigid_body = rigid_body;
|
||||
body->mass = mass;
|
||||
body->world = world;
|
||||
body->cm.x = cm_x;
|
||||
body->cm.y = cm_y;
|
||||
body->rigid_body->setUserPointer(body);
|
||||
body->rigid_body->setLinearFactor(btVector3(1, 1, 0));
|
||||
body->rigid_body->setAngularFactor(btVector3(0, 0, 1));
|
||||
|
@ -353,8 +355,8 @@ _ephysics_body_move(EPhysics_Body *body, Evas_Coord x, Evas_Coord y)
|
|||
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, &height);
|
||||
height += wy;
|
||||
|
||||
mx = (x + body->w / 2) / rate;
|
||||
my = (height - (y + body->h / 2)) / rate;
|
||||
mx = (x + body->w * body->cm.x) / rate;
|
||||
my = (height - (y + body->h * body->cm.y)) / rate;
|
||||
|
||||
body->rigid_body->getMotionState()->getWorldTransform(trans);
|
||||
trans.setOrigin(btVector3(mx, my, 0));
|
||||
|
@ -377,8 +379,8 @@ _ephysics_body_geometry_set(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Eva
|
|||
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, &height);
|
||||
height += wy;
|
||||
|
||||
mx = (x + w / 2) / rate;
|
||||
my = (height - (y + h / 2)) / rate;
|
||||
mx = (x + w * body->cm.x) / rate;
|
||||
my = (height - (y + h * body->cm.y)) / rate;
|
||||
sx = w / rate;
|
||||
sy = h / rate;
|
||||
|
||||
|
@ -513,8 +515,8 @@ _ephysics_body_evas_object_default_update(EPhysics_Body *body)
|
|||
|
||||
evas_object_geometry_get(body->evas_obj, NULL, NULL, &w, &h);
|
||||
rate = ephysics_world_rate_get(body->world);
|
||||
x = (int) (trans.getOrigin().getX() * rate) - w / 2 - cx;
|
||||
y = wh + wy - (int) (trans.getOrigin().getY() * rate) - h / 2 - cy;
|
||||
x = (int) (trans.getOrigin().getX() * rate) - w * body->cm.x - cx;
|
||||
y = wh + wy - (int) (trans.getOrigin().getY() * rate) - h * body->cm.y - cy;
|
||||
|
||||
evas_object_move(body->evas_obj, x, y);
|
||||
|
||||
|
@ -534,7 +536,8 @@ _ephysics_body_evas_object_default_update(EPhysics_Body *body)
|
|||
if (body->soft_body)
|
||||
_ephysics_body_soft_body_deform(body, rate, map);
|
||||
|
||||
evas_map_util_rotate(map, rot, x + (w / 2), y + (h / 2));
|
||||
evas_map_util_rotate(map, rot, x + (w * body->cm.x), y +
|
||||
(h * body->cm.y));
|
||||
evas_object_map_set(body->evas_obj, map);
|
||||
evas_object_map_enable_set(body->evas_obj, EINA_TRUE);
|
||||
evas_map_free(map);
|
||||
|
@ -690,7 +693,7 @@ _ephysics_body_soft_add(EPhysics_World *world, btCollisionShape *collision_shape
|
|||
btSoftBody::AJoint::Specs angular_joint;
|
||||
btSoftBody::LJoint::Specs linear_joint;
|
||||
|
||||
body = _ephysics_body_add(world, collision_shape, "soft box");
|
||||
body = _ephysics_body_add(world, collision_shape, "soft box", 0.5, 0.5);
|
||||
if (!body)
|
||||
{
|
||||
ephysics_body_del(body);
|
||||
|
@ -806,7 +809,7 @@ ephysics_body_circle_add(EPhysics_World *world)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return _ephysics_body_add(world, collision_shape, "circle");
|
||||
return _ephysics_body_add(world, collision_shape, "circle", 0.5, 0.5);
|
||||
}
|
||||
|
||||
EAPI EPhysics_Body *
|
||||
|
@ -883,13 +886,14 @@ ephysics_body_box_add(EPhysics_World *world)
|
|||
|
||||
collision_shape = new btBoxShape(btVector3(0.5, 0.5, 0.5));
|
||||
|
||||
return _ephysics_body_add(world, collision_shape, "box");
|
||||
return _ephysics_body_add(world, collision_shape, "box", 0.5, 0.5);
|
||||
}
|
||||
|
||||
EAPI EPhysics_Body *
|
||||
ephysics_body_shape_add(EPhysics_World *world, EPhysics_Shape *shape)
|
||||
{
|
||||
btConvexHullShape *full_shape, *simplified_shape;
|
||||
double max_x, max_y, min_x, min_y, cm_x, cm_y, range_x, range_y;
|
||||
const Eina_Inlist *points;
|
||||
EPhysics_Point *point;
|
||||
btShapeHull *hull;
|
||||
|
@ -908,6 +912,13 @@ ephysics_body_shape_add(EPhysics_World *world, EPhysics_Shape *shape)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
points = ephysics_shape_points_get(shape);
|
||||
if (eina_inlist_count(points) < 3)
|
||||
{
|
||||
ERR("At least 3 points are required to add a shape");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
full_shape = new btConvexHullShape();
|
||||
if (!full_shape)
|
||||
{
|
||||
|
@ -915,24 +926,65 @@ ephysics_body_shape_add(EPhysics_World *world, EPhysics_Shape *shape)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
points = ephysics_shape_points_get(shape);
|
||||
point = EINA_INLIST_CONTAINER_GET(points, EPhysics_Point);
|
||||
max_x = min_x = point->x;
|
||||
max_y = min_y = point->y;
|
||||
cm_x = cm_y = 0;
|
||||
|
||||
/* FIXME : only vertices should be used to calculate the center of mass */
|
||||
EINA_INLIST_FOREACH(points, point)
|
||||
{
|
||||
if (point->x > max_x) max_x = point->x;
|
||||
if (point->x < min_x) min_x = point->x;
|
||||
if (point->y > max_y) max_y = point->y;
|
||||
if (point->y < min_y) min_y = point->y;
|
||||
|
||||
cm_x += point->x;
|
||||
cm_y += point->y;
|
||||
}
|
||||
|
||||
cm_x /= eina_inlist_count(points);
|
||||
cm_y /= eina_inlist_count(points);
|
||||
range_x = max_x - min_x;
|
||||
range_y = max_y - min_y;
|
||||
|
||||
EINA_INLIST_FOREACH(points, point)
|
||||
{
|
||||
point3d = btVector3(point->x, point->y, 0);
|
||||
double x, y;
|
||||
|
||||
x = (point->x - cm_x) / range_x;
|
||||
y = - (point->y - cm_y) / range_y;
|
||||
|
||||
point3d = btVector3(x, y, -0.5);
|
||||
full_shape->addPoint(point3d);
|
||||
point3d = btVector3(point->x, point->y, 0.5);
|
||||
|
||||
point3d = btVector3(x, y, 0.5);
|
||||
full_shape->addPoint(point3d);
|
||||
}
|
||||
|
||||
hull = new btShapeHull(full_shape);
|
||||
if (!hull)
|
||||
{
|
||||
delete full_shape;
|
||||
ERR("Couldn't create a shape hull.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
margin = full_shape->getMargin();
|
||||
hull->buildHull(margin);
|
||||
simplified_shape = new btConvexHullShape(&(hull->getVertexPointer()->getX()),
|
||||
hull->numVertices());
|
||||
delete hull;
|
||||
delete full_shape;
|
||||
if (!simplified_shape)
|
||||
{
|
||||
ERR("Couldn't create a simplified shape.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _ephysics_body_add(world, (btCollisionShape *)simplified_shape,
|
||||
"generic");
|
||||
"generic", (cm_x - min_x) / range_x,
|
||||
1 - (cm_y - min_y) / range_y);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -85,6 +85,10 @@ struct _EPhysics_Body {
|
|||
double y;
|
||||
double torque;
|
||||
} force;
|
||||
struct {
|
||||
double x;
|
||||
double y;
|
||||
} cm;
|
||||
Eina_Bool active:1;
|
||||
Eina_Bool deleted:1;
|
||||
double distances[4][3];
|
||||
|
|
|
@ -80,12 +80,6 @@ ephysics_shape_point_add(EPhysics_Shape *shape, double x, double y)
|
|||
return EINA_FALSE;;
|
||||
}
|
||||
|
||||
if ((x < 0) || (x > 1) || (y < 0) || (y > 1))
|
||||
{
|
||||
ERR("Points should be between 0 and 1.");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
point = _ephysics_shape_point_new();
|
||||
if (!point)
|
||||
return EINA_FALSE;;
|
||||
|
|
Loading…
Reference in New Issue