diff --git a/legacy/ephysics/src/bin/test_shapes.c b/legacy/ephysics/src/bin/test_shapes.c index 4e00b5aafd..3547dbbd6b 100644 --- a/legacy/ephysics/src/bin/test_shapes.c +++ b/legacy/ephysics/src/bin/test_shapes.c @@ -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); } diff --git a/legacy/ephysics/src/lib/EPhysics.h b/legacy/ephysics/src/lib/EPhysics.h index 3372c1c2e4..babe3b5ed4 100644 --- a/legacy/ephysics/src/lib/EPhysics.h +++ b/legacy/ephysics/src/lib/EPhysics.h @@ -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(). diff --git a/legacy/ephysics/src/lib/ephysics_body.cpp b/legacy/ephysics/src/lib/ephysics_body.cpp index b390108846..123192791b 100644 --- a/legacy/ephysics/src/lib/ephysics_body.cpp +++ b/legacy/ephysics/src/lib/ephysics_body.cpp @@ -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); @@ -702,7 +705,7 @@ _ephysics_body_soft_add(EPhysics_World *world, btCollisionShape *collision_shape body->soft_body->getCollisionShape()->setMargin(0.22); - soft_body->m_materials[0]->m_kLST = 0.35; + soft_body->m_materials[0]->m_kLST = 0.35; soft_body->setPose(true, false); body->soft_body->m_cfg.collisions += btSoftBody::fCollision::SDF_RS; @@ -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 diff --git a/legacy/ephysics/src/lib/ephysics_private.h b/legacy/ephysics/src/lib/ephysics_private.h index 1cd491e125..a9d29b1fdb 100644 --- a/legacy/ephysics/src/lib/ephysics_private.h +++ b/legacy/ephysics/src/lib/ephysics_private.h @@ -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]; diff --git a/legacy/ephysics/src/lib/ephysics_shape.cpp b/legacy/ephysics/src/lib/ephysics_shape.cpp index 7970b09e63..f75a4e6cf9 100644 --- a/legacy/ephysics/src/lib/ephysics_shape.cpp +++ b/legacy/ephysics/src/lib/ephysics_shape.cpp @@ -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;;