diff --git a/legacy/ephysics/src/bin/Makefile.am b/legacy/ephysics/src/bin/Makefile.am index 5f846ba06d..723a78e989 100644 --- a/legacy/ephysics/src/bin/Makefile.am +++ b/legacy/ephysics/src/bin/Makefile.am @@ -37,7 +37,8 @@ test_velocity.c \ test_shapes.c \ test_sleeping_threshold.c \ test_slider.c \ -test_win_resize.c +test_win_resize.c \ +test_soft_body.c ephysics_logo_SOURCES = \ ephysics_logo.c diff --git a/legacy/ephysics/src/bin/test.c b/legacy/ephysics/src/bin/test.c index 0c35888609..2aabdcab3b 100644 --- a/legacy/ephysics/src/bin/test.c +++ b/legacy/ephysics/src/bin/test.c @@ -37,6 +37,7 @@ void test_shapes(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); void test_win_resize(void *data, Evas_Object *obj, void *event_info); +void test_soft_body(void *data, Evas_Object *obj, void *event_info); static const EPhysics_Test tests[] = { {"Bouncing Ball", test_bouncing_ball}, @@ -61,6 +62,7 @@ static const EPhysics_Test tests[] = { {"Sleeping Threshold", test_sleeping}, {"Slider", test_slider}, {"Win Resize", test_win_resize}, + {"Soft Body", test_soft_body}, }; static void diff --git a/legacy/ephysics/src/bin/test_soft_body.c b/legacy/ephysics/src/bin/test_soft_body.c new file mode 100644 index 0000000000..edd08f6092 --- /dev/null +++ b/legacy/ephysics/src/bin/test_soft_body.c @@ -0,0 +1,160 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "ephysics_test.h" + +static void +_world_populate(Test_Data *test_data) +{ + Evas_Object *evas_obj, *shadow; + EPhysics_Body *fall_body; + + shadow = elm_layout_add(test_data->win); + elm_layout_file_set( + shadow, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "shadow-ball"); + evas_object_move(shadow, WIDTH / 3, FLOOR_Y); + evas_object_resize(shadow, 70, 3); + evas_object_show(shadow); + test_data->evas_objs = eina_list_append(test_data->evas_objs, shadow); + + evas_obj = elm_image_add(test_data->win); + elm_image_file_set( + evas_obj, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "big-red-ball"); + evas_object_move(evas_obj, WIDTH / 3, HEIGHT / 2); + evas_object_resize(evas_obj, 70, 70); + evas_object_show(evas_obj); + test_data->evas_objs = eina_list_append(test_data->evas_objs, evas_obj); + + fall_body = ephysics_body_soft_circle_add(test_data->world); + ephysics_body_evas_object_set(fall_body, evas_obj, EINA_TRUE); + ephysics_body_restitution_set(fall_body, 0.95); + ephysics_body_friction_set(fall_body, 0.1); + ephysics_body_event_callback_add(fall_body, EPHYSICS_CALLBACK_BODY_UPDATE, + update_object_cb, shadow); + test_data->bodies = eina_list_append(test_data->bodies, fall_body); + + shadow = elm_layout_add(test_data->win); + elm_layout_file_set( + shadow, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "shadow-ball"); + evas_object_move(shadow, WIDTH / 3, FLOOR_Y); + evas_object_resize(shadow, 70, 3); + evas_object_show(shadow); + test_data->evas_objs = eina_list_append(test_data->evas_objs, shadow); + + evas_obj = elm_image_add(test_data->win); + elm_image_file_set( + evas_obj, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "big-blue-ball"); + evas_object_move(evas_obj, WIDTH / 3, HEIGHT / 4); + evas_object_resize(evas_obj, 70, 70); + evas_object_show(evas_obj); + test_data->evas_objs = eina_list_append(test_data->evas_objs, evas_obj); + + fall_body = ephysics_body_circle_add(test_data->world); + ephysics_body_evas_object_set(fall_body, evas_obj, EINA_TRUE); + ephysics_body_mass_set(fall_body, 1200); + ephysics_body_restitution_set(fall_body, 0.95); + ephysics_body_friction_set(fall_body, 0.1); + ephysics_body_event_callback_add(fall_body, EPHYSICS_CALLBACK_BODY_UPDATE, + update_object_cb, shadow); + test_data->bodies = eina_list_append(test_data->bodies, fall_body); + + shadow = elm_layout_add(test_data->win); + elm_layout_file_set( + shadow, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "shadow-ball"); + evas_object_move(shadow, WIDTH / 4, FLOOR_Y); + evas_object_resize(shadow, 70, 3); + evas_object_show(shadow); + test_data->evas_objs = eina_list_append(test_data->evas_objs, shadow); + + evas_obj = elm_image_add(test_data->win); + elm_image_file_set( + evas_obj, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "big-blue-ball"); + evas_object_move(evas_obj, WIDTH / 4, HEIGHT / 4); + evas_object_resize(evas_obj, 70, 70); + evas_object_show(evas_obj); + test_data->evas_objs = eina_list_append(test_data->evas_objs, evas_obj); + + fall_body = ephysics_body_circle_add(test_data->world); + ephysics_body_evas_object_set(fall_body, evas_obj, EINA_TRUE); + ephysics_body_mass_set(fall_body, 600); + ephysics_body_restitution_set(fall_body, 0.95); + ephysics_body_friction_set(fall_body, 0.1); + ephysics_body_central_impulse_apply(fall_body, 500, 150); + ephysics_body_event_callback_add(fall_body, EPHYSICS_CALLBACK_BODY_UPDATE, + update_object_cb, shadow); + test_data->bodies = eina_list_append(test_data->bodies, fall_body); + + shadow = elm_layout_add(test_data->win); + elm_layout_file_set( + shadow, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "shadow-cube"); + evas_object_move(shadow, WIDTH / 6 + 60, FLOOR_Y); + evas_object_resize(shadow, 70, 3); + evas_object_show(shadow); + test_data->evas_objs = eina_list_append(test_data->evas_objs, shadow); + + evas_obj = elm_image_add(test_data->win); + elm_image_file_set( + evas_obj, PACKAGE_DATA_DIR "/" EPHYSICS_TEST_THEME ".edj", "purple-cube"); + evas_object_move(evas_obj, WIDTH / 6 + 60, HEIGHT / 8); + evas_object_resize(evas_obj, 70, 70); + evas_object_show(evas_obj); + test_data->evas_objs = eina_list_append(test_data->evas_objs, evas_obj); + + fall_body = ephysics_body_soft_box_add(test_data->world); + ephysics_body_evas_object_set(fall_body, evas_obj, EINA_TRUE); + ephysics_body_event_callback_add(fall_body, EPHYSICS_CALLBACK_BODY_UPDATE, + update_object_cb, shadow); + ephysics_body_restitution_set(fall_body, 0.5); + ephysics_body_friction_set(fall_body, 0.1); + test_data->bodies = eina_list_append(test_data->bodies, fall_body); +} + +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_soft_body(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, "Soft Body", EINA_TRUE); + + elm_layout_signal_callback_add(test_data->layout, "restart", "test-theme", + _restart, test_data); + elm_object_signal_emit(test_data->layout, "borders,show", "ephysics_test"); + elm_object_signal_emit(test_data->layout, "arrows,show", "ephysics_test"); + + 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, 4); + + boundary = ephysics_body_right_boundary_add(test_data->world); + ephysics_body_restitution_set(boundary, 0.4); + ephysics_body_friction_set(boundary, 3); + + boundary = ephysics_body_left_boundary_add(test_data->world); + ephysics_body_restitution_set(boundary, 0.4); + ephysics_body_friction_set(boundary, 3); + + ephysics_body_top_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 4494881de4..da9f61c63f 100644 --- a/legacy/ephysics/src/lib/EPhysics.h +++ b/legacy/ephysics/src/lib/EPhysics.h @@ -1282,8 +1282,8 @@ typedef void (*EPhysics_Body_Event_Cb)(void *data, EPhysics_Body *body, void *ev * Create a new circle physics body. * * Its collision shape will be a circle of diameter 1. To change it's size - * @ref ephysics_body_geometry_set() should be used, so it can be deformed - * on x and y axises. + * @ref ephysics_body_geometry_set() should be used. + * * Any evas object can be associated to it with * @ref ephysics_body_evas_object_set(), * and it will collide as a circle (even if you have an evas rectangle). @@ -1300,13 +1300,35 @@ typedef void (*EPhysics_Body_Event_Cb)(void *data, EPhysics_Body *body, void *ev */ EAPI EPhysics_Body *ephysics_body_circle_add(EPhysics_World *world); +/** + * @brief + * Create a new deformable circle physics body. + * + * Its collision shape will be a circle of diameter 1. To change it's size + * @ref ephysics_body_geometry_set() should be used. + * + * Any evas object can be associated to it with + * @ref ephysics_body_evas_object_set(), + * and it will collide as a circle (even if you have an evas rectangle). + * + * Actually, since we're using a 3D backend, it will be a cylinder on + * z axis. + * + * @param world The world this body will belongs to. + * @return a new body or @c NULL, on errors. + * + * @see ephysics_body_del(). + * + * @ingroup EPhysics_Body + */ +EAPI EPhysics_Body *ephysics_body_soft_circle_add(EPhysics_World *world); + /** * @brief * Create a new box physics body. * * Its collision shape will be a box of dimensions 1 on all the axises. - * To change it's size @ref ephysics_body_geometry_set() should be used, - * so it can be deformed on x and y axises. + * To change it's size @ref ephysics_body_geometry_set() should be used. * * @param world The world this body will belongs to. * @return a new body or @c NULL, on errors. @@ -1318,6 +1340,23 @@ EAPI EPhysics_Body *ephysics_body_circle_add(EPhysics_World *world); */ EAPI EPhysics_Body *ephysics_body_box_add(EPhysics_World *world); +/** + * @brief + * Create a new deformable box physics body. + * + * Its collision shape will be a box of dimensions 1 on all the axises. + * To change it's size @ref ephysics_body_geometry_set() should be used. + * + * @param world The world this body will belongs to. + * @return a new body or @c NULL, on errors. + * + * @see ephysics_body_del(). + * @see ephysics_body_evas_object_set(). + * + * @ingroup EPhysics_Body + */ +EAPI EPhysics_Body *ephysics_body_soft_box_add(EPhysics_World *world); + /** * @brief * Create a new physics body using a custom shape. diff --git a/legacy/ephysics/src/lib/ephysics_body.cpp b/legacy/ephysics/src/lib/ephysics_body.cpp index 287ab605ed..505dfe6534 100644 --- a/legacy/ephysics/src/lib/ephysics_body.cpp +++ b/legacy/ephysics/src/lib/ephysics_body.cpp @@ -4,7 +4,10 @@ #include +#include + #include "ephysics_private.h" +#include "ephysics_trimesh.h" #ifdef __cplusplus extern "C" { @@ -236,6 +239,7 @@ _ephysics_body_add(EPhysics_World *world, btCollisionShape *collision_shape, con goto err_rigid_body; } + body->soft_body = NULL; body->collision_groups = NULL; body->collision_shape = collision_shape; body->rigid_body = rigid_body; @@ -277,6 +281,32 @@ _ephysics_body_evas_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj DBG("Evas object deleted. Updating body: %p", body); } +static void +_ephysics_body_soft_body_points_distance_get(const EPhysics_Body *body, double distances[4][3]) +{ + btVector3 center; + btScalar raius; + + body->soft_body->getCollisionShape()->getBoundingSphere(center, raius); + + for (int m = 0; m < 4; m++) + { + for (int n = 0; n < 3; n++) + { + btVector3 node; + double distance; + + node = body->soft_body-> + m_faces[body->points_deform[m][n]].m_n[1]->m_x; + + distance = sqrt(pow(center.x() - node.x(), 2) + + pow(center.y() - node.y(), 2)); + + distances[m][n] = distance; + } + } +} + static void _ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h) { @@ -286,10 +316,23 @@ _ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h) sx = w / rate; sy = h / rate; - body->collision_shape->setLocalScaling(btVector3(sx, sy, 1)); + if (body->soft_body) + { + body->soft_body->m_anchors.resize(0); + body->soft_body->scale(btVector3(sx, sy, 1)); - if(!body->rigid_body->isStaticObject()) - ephysics_body_mass_set(body, ephysics_body_mass_get(body)); + for (int i = 0; i < body->soft_body->m_nodes.size(); i++) + body->soft_body->appendAnchor(i, body->rigid_body); + + _ephysics_body_soft_body_points_distance_get(body, body->distances); + } + else + { + body->collision_shape->setLocalScaling(btVector3(sx, sy, 1)); + + if(!body->rigid_body->isStaticObject()) + ephysics_body_mass_set(body, ephysics_body_mass_get(body)); + } body->w = w; body->h = h; @@ -305,6 +348,7 @@ _ephysics_body_move(EPhysics_Body *body, Evas_Coord x, Evas_Coord y) double rate, mx, my; btTransform trans; int wy, height; + btVector3 body_scale; rate = ephysics_world_rate_get(body->world); ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, &height); @@ -329,6 +373,7 @@ _ephysics_body_geometry_set(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Eva double mx, my, sx, sy; btTransform trans; int wy, height; + btVector3 body_scale; ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, &height); height += wy; @@ -340,12 +385,28 @@ _ephysics_body_geometry_set(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Eva body->rigid_body->getMotionState()->getWorldTransform(trans); trans.setOrigin(btVector3(mx, my, 0)); - body->rigid_body->proceedToTransform(trans); - body->collision_shape->setLocalScaling(btVector3(sx, sy, 1)); + body_scale = btVector3(sx, sy, 1); + if (body->soft_body) + { + body->soft_body->m_anchors.resize(0); + body->soft_body->scale(btVector3(sx, sy, 1)); + body->rigid_body->proceedToTransform(trans); + body->soft_body->transform(trans); - if(!body->rigid_body->isStaticObject()) - ephysics_body_mass_set(body, ephysics_body_mass_get(body)); + for (int i = 0; i < body->soft_body->m_nodes.size(); i++) + body->soft_body->appendAnchor(i, body->rigid_body); + + _ephysics_body_soft_body_points_distance_get(body, body->distances); + } + else + { + body->collision_shape->setLocalScaling(body_scale); + body->rigid_body->proceedToTransform(trans); + + if (!body->rigid_body->isStaticObject()) + ephysics_body_mass_set(body, ephysics_body_mass_get(body)); + } body->rigid_body->getMotionState()->setWorldTransform(trans); @@ -358,6 +419,32 @@ _ephysics_body_geometry_set(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Eva DBG("Body %p scale changed to %lf, %lf.", body, sx, sy); } +static void +_ephysics_body_soft_body_deform(EPhysics_Body *body, double rate, Evas_Map *map) +{ + double curr_distances[4][3]; + + _ephysics_body_soft_body_points_distance_get(body, curr_distances); + + for (int m = 0; m < 4; m++) + { + Evas_Coord px, py, pz; + double dx = 0, dy = 0; + + evas_map_point_coord_get(map, m, &px, &py, &pz); + + for (int n = 0; n < 3; n++) + { + double diff = (curr_distances[m][n] - body->distances[m][n]); + dx += diff; + dy += diff; + } + + evas_map_point_coord_set(map, m, px - (dx * rate), py - (dy * rate), + pz); + } +} + static void _ephysics_body_evas_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { @@ -400,6 +487,7 @@ _ephysics_body_del(EPhysics_Body *body) delete body->rigid_body->getMotionState(); delete body->collision_shape; delete body->rigid_body; + delete body->soft_body; free(body); } @@ -443,6 +531,10 @@ _ephysics_body_evas_object_default_update(EPhysics_Body *body) map = evas_map_new(4); evas_map_util_points_populate_from_object(map, body->evas_obj); + + 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_object_map_set(body->evas_obj, map); evas_object_map_enable_set(body->evas_obj, EINA_TRUE); @@ -586,6 +678,117 @@ ephysics_body_rigid_body_get(const EPhysics_Body *body) return body->rigid_body; } +btSoftBody * +ephysics_body_soft_body_get(const EPhysics_Body *body) +{ + return body->soft_body; +} + +static EPhysics_Body * +_ephysics_body_soft_add(EPhysics_World *world, btCollisionShape *collision_shape, btSoftBody *soft_body, const char *type) +{ + EPhysics_Body *body; + btSoftBody::AJoint::Specs angular_joint; + btSoftBody::LJoint::Specs linear_joint; + + body = _ephysics_body_add(world, collision_shape, "soft box"); + if (!body) + { + ephysics_body_del(body); + return NULL; + } + + body->soft_body = soft_body; + body->soft_body->setUserPointer(body); + + body->soft_body->getCollisionShape()->setMargin(0.22); + + soft_body->m_materials[0]->m_kLST = 0.35; + soft_body->setPose(true, false); + + body->soft_body->m_cfg.collisions += btSoftBody::fCollision::SDF_RS; + body->soft_body->m_cfg.collisions += btSoftBody::fCollision::CL_SS; + + body->soft_body->generateClusters(body->soft_body->m_nodes.size()); + + angular_joint.erp = 0.; + angular_joint.cfm = 0.; + angular_joint.axis = btVector3(0, 0, 1); + body->soft_body->appendAngularJoint(angular_joint); + + linear_joint.erp = 0.; + linear_joint.cfm = 0.; + linear_joint.position = btVector3(0, 0, 0); + body->soft_body->appendLinearJoint(linear_joint, body->rigid_body); + + for (int i = 0; i < body->soft_body->m_nodes.size(); i++) + body->soft_body->appendAnchor(i, body->rigid_body); + + ephysics_world_soft_body_add(world, body); + return body; +} + +EAPI EPhysics_Body * +ephysics_body_soft_circle_add(EPhysics_World *world) +{ + EPhysics_Body *body; + btCollisionShape *shape; + btSoftBodyWorldInfo *world_info; + btSoftBody *soft_body; + + if (!world) + { + ERR("Can't add circle, world is null."); + return NULL; + } + + shape = new btCylinderShapeZ(btVector3(0.25, 0.25, 0.25)); + if (!shape) + { + ERR("Couldn't create a new cylinder shape."); + goto no_collision_shape; + } + + world_info = ephysics_world_info_get(world); + soft_body = btSoftBodyHelpers::CreateFromTriMesh(*world_info, + cylinder_vertices, &cylinder_indices[0][0], + CYLINDER_NUM_TRIANGLES); + if (!soft_body) + { + ERR("Couldn't create a new soft body."); + goto no_soft_body; + } + + body = _ephysics_body_soft_add(world, shape, soft_body, "soft circle"); + if (!body) + goto no_body; + + body->points_deform[0][0] = 72; + body->points_deform[0][1] = 6; + body->points_deform[0][2] = 65; + + body->points_deform[1][0] = 72; + body->points_deform[1][1] = 69; + body->points_deform[1][2] = 3; + + body->points_deform[2][0] = 57; + body->points_deform[2][1] = 3; + body->points_deform[2][2] = 76; + + body->points_deform[3][0] = 54; + body->points_deform[3][1] = 47; + body->points_deform[3][2] = 65; + + return body; + +no_body: + delete soft_body; +no_soft_body: + delete shape; +no_collision_shape: + return NULL; +} + EAPI EPhysics_Body * ephysics_body_circle_add(EPhysics_World *world) { @@ -598,10 +801,76 @@ ephysics_body_circle_add(EPhysics_World *world) } collision_shape = new btCylinderShapeZ(btVector3(0.5, 0.5, 0.5)); + if (!collision_shape) + { + ERR("Couldn't create a new cylinder shape."); + return NULL; + } return _ephysics_body_add(world, collision_shape, "circle"); } +EAPI EPhysics_Body * +ephysics_body_soft_box_add(EPhysics_World *world) +{ + EPhysics_Body *body; + btCollisionShape *shape; + btSoftBodyWorldInfo *world_info; + btSoftBody *soft_body; + + if (!world) + { + ERR("Can't add circle, world is null."); + return NULL; + } + + shape = new btBoxShape(btVector3(0.25, 0.25, 0.25)); + if (!shape) + { + ERR("Couldn't create a new box shape."); + goto no_collision_shape; + } + + world_info = ephysics_world_info_get(world); + soft_body = btSoftBodyHelpers::CreateFromTriMesh(*world_info, + cube_vertices, &cube_indices[0][0], + CUBE_NUM_TRIANGLES); + if (!soft_body) + { + ERR("Couldn't create a new soft body."); + goto no_soft_body; + } + + body = _ephysics_body_soft_add(world, shape, soft_body, "soft box"); + if (!body) + goto no_body; + + body->points_deform[0][0] = 27; + body->points_deform[0][1] = 80; + body->points_deform[0][2] = 69; + + body->points_deform[1][0] = 85; + body->points_deform[1][1] = 12; + body->points_deform[1][2] = 30; + + body->points_deform[2][0] = 18; + body->points_deform[2][1] = 62; + body->points_deform[2][2] = 8; + + body->points_deform[3][0] = 50; + body->points_deform[3][1] = 40; + body->points_deform[3][2] = 60; + + return body; + +no_body: + delete soft_body; +no_soft_body: + delete shape; +no_collision_shape: + return NULL; +} + EAPI EPhysics_Body * ephysics_body_box_add(EPhysics_World *world) { @@ -796,6 +1065,7 @@ ephysics_body_evas_object_set(EPhysics_Body *body, Evas_Object *evas_obj, Eina_B } body->evas_obj = evas_obj; + evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL, _ephysics_body_evas_obj_del_cb, body); @@ -932,9 +1202,14 @@ ephysics_body_mass_set(EPhysics_Body *body, double mass) } btVector3 inertia(0, 0, 0); - body->collision_shape->calculateLocalInertia(mass, inertia); - body->rigid_body->setMassProps(mass, inertia); - body->rigid_body->updateInertiaTensor(); + if (body->soft_body) + body->soft_body->setTotalMass(mass); + else + { + body->collision_shape->calculateLocalInertia(mass, inertia); + body->rigid_body->setMassProps(mass, inertia); + body->rigid_body->updateInertiaTensor(); + } body->mass = mass; DBG("Body %p mass changed to %lf.", body, mass); @@ -1380,6 +1655,10 @@ ephysics_body_rotation_set(EPhysics_Body *body, double rotation) body->rigid_body->getMotionState()->getWorldTransform(trans); quat.setEuler(0, 0, -rotation / RAD_TO_DEG); trans.setRotation(quat); + + if (body->soft_body) + body->soft_body->transform(trans); + body->rigid_body->proceedToTransform(trans); body->rigid_body->getMotionState()->setWorldTransform(trans); diff --git a/legacy/ephysics/src/lib/ephysics_private.h b/legacy/ephysics/src/lib/ephysics_private.h index 3a3dad4736..1cd491e125 100644 --- a/legacy/ephysics/src/lib/ephysics_private.h +++ b/legacy/ephysics/src/lib/ephysics_private.h @@ -5,6 +5,10 @@ # include #endif +#include +#include +#include +#include #include #include "EPhysics.h" @@ -65,6 +69,7 @@ struct _EPhysics_Body { EINA_INLIST; btCollisionShape *collision_shape; btRigidBody *rigid_body; + btSoftBody *soft_body; Evas_Object *evas_obj; EPhysics_World *world; int walking; @@ -82,6 +87,8 @@ struct _EPhysics_Body { } force; Eina_Bool active:1; Eina_Bool deleted:1; + double distances[4][3]; + int points_deform[4][3]; }; extern int _ephysics_log_dom; @@ -91,12 +98,14 @@ int ephysics_world_init(void); 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_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); Eina_Bool ephysics_world_bodies_outside_autodel_get(const EPhysics_World *world); +btSoftBodyWorldInfo *ephysics_world_info_get(const EPhysics_World *world); /* Body */ Eina_Bool ephysics_body_filter_collision(EPhysics_Body *body0, EPhysics_Body *body1); @@ -104,6 +113,7 @@ void ephysics_body_evas_object_update_select(EPhysics_Body *body); void ephysics_orphan_body_del(EPhysics_Body *body); void ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body, btVector3 position); btRigidBody *ephysics_body_rigid_body_get(const EPhysics_Body *body); +btSoftBody *ephysics_body_soft_body_get(const EPhysics_Body *body); void ephysics_body_active_set(EPhysics_Body *body, Eina_Bool active); void ephysics_body_recalc(EPhysics_Body *body, double rate); void ephysics_body_forces_apply(EPhysics_Body *body); diff --git a/legacy/ephysics/src/lib/ephysics_trimesh.h b/legacy/ephysics/src/lib/ephysics_trimesh.h new file mode 100644 index 0000000000..3d17c40a1c --- /dev/null +++ b/legacy/ephysics/src/lib/ephysics_trimesh.h @@ -0,0 +1,292 @@ +#ifndef EPHYSICS_TRIMESH_H +#define EPHYSICS_TRIMESH_H + +#define CYLINDER_NUM_VERTICES 46 +#define CYLINDER_NUM_TRIANGLES 80 + +static btScalar cylinder_vertices[CYLINDER_NUM_VERTICES * 3] = { + btScalar(0.378791), btScalar(-0.156900), btScalar(0.410000), + btScalar(0.381661), btScalar(0.142468), btScalar(0.410000), + btScalar(0.205276), btScalar(0.346467), btScalar(0.410000), + btScalar(-0.062845), btScalar(0.397499), btScalar(0.410000), + btScalar(-0.312196), btScalar(0.256566), btScalar(0.410000), + btScalar(-0.409345), btScalar(0.003295), btScalar(0.410000), + btScalar(-0.315929), btScalar(-0.250980), btScalar(0.410000), + btScalar(-0.085737), btScalar(-0.392946), btScalar(0.410000), + btScalar(0.181088), btScalar(-0.362629), btScalar(0.410000), + btScalar(0.378791), btScalar(-0.156900), btScalar(-0.410000), + btScalar(0.183474), btScalar(-0.361035), btScalar(-0.410000), + btScalar(-0.085737), btScalar(-0.392946), btScalar(-0.410000), + btScalar(-0.315929), btScalar(-0.250980), btScalar(-0.410000), + btScalar(-0.409345), btScalar(0.003295), btScalar(-0.410000), + btScalar(-0.312196), btScalar(0.256566), btScalar(-0.410000), + btScalar(-0.062845), btScalar(0.397499), btScalar(-0.410000), + btScalar(0.204218), btScalar(0.347174), btScalar(-0.410000), + btScalar(0.381661), btScalar(0.142468), btScalar(-0.410000), + btScalar(0.197462), btScalar(0.068348), btScalar(0.410000), + btScalar(-0.036961), btScalar(0.150675), btScalar(0.410000), + btScalar(0.067713), btScalar(-0.147128), btScalar(0.410000), + btScalar(-0.178972), btScalar(-0.060078), btScalar(0.410000), + btScalar(0.120907), btScalar(-0.105917), btScalar(-0.410000), + btScalar(-0.151098), btScalar(-0.043779), btScalar(-0.410000), + btScalar(0.039171), btScalar(0.161620), btScalar(-0.410000), + btScalar(0.311630), btScalar(-0.257414), btScalar(0.203297), + btScalar(-0.392051), btScalar(0.090235), btScalar(0.134737), + btScalar(-0.360756), btScalar(-0.183891), btScalar(0.144512), + btScalar(-0.141439), btScalar(-0.381866), btScalar(0.155320), + btScalar(0.110283), btScalar(-0.388063), btScalar(0.161516), + btScalar(0.320615), btScalar(-0.243966), btScalar(-0.082931), + btScalar(0.043971), btScalar(-0.401254), btScalar(-0.106715), + btScalar(-0.237476), btScalar(-0.324952), btScalar(-0.131440), + btScalar(-0.392954), btScalar(-0.085698), btScalar(-0.130760), + btScalar(-0.355705), btScalar(0.191451), btScalar(-0.132884), + btScalar(-0.115651), btScalar(0.386996), btScalar(-0.130213), + btScalar(0.169937), btScalar(0.370080), btScalar(-0.151207), + btScalar(0.388128), btScalar(0.109959), btScalar(-0.173023), + btScalar(0.401935), btScalar(-0.040547), btScalar(0.142301), + btScalar(0.319544), btScalar(0.245570), btScalar(0.129082), + btScalar(0.058047), btScalar(0.398454), btScalar(0.125903), + btScalar(-0.223604), btScalar(0.334221), btScalar(0.131019), + btScalar(-0.118588), btScalar(-0.126284), btScalar(-0.116393), + btScalar(0.107303), btScalar(0.062176), btScalar(0.066999), + btScalar(-0.052534), btScalar(0.162121), btScalar(-0.154024), + btScalar(-0.027084), btScalar(-0.147475), btScalar(0.173698), +}; + +static int cylinder_indices[CYLINDER_NUM_TRIANGLES][3] = { + {0, 1, 18}, + {1, 2, 18}, + {2, 3, 19}, + {18, 2, 19}, + {3, 4, 19}, + {8, 0, 20}, + {7, 8, 20}, + {0, 18, 20}, + {4, 5, 21}, + {19, 4, 21}, + {5, 6, 21}, + {6, 7, 21}, + {7, 20, 21}, + {18, 19, 20}, + {20, 19, 21}, + {9, 10, 22}, + {10, 11, 22}, + {11, 12, 23}, + {22, 11, 23}, + {12, 13, 23}, + {17, 9, 22}, + {13, 14, 23}, + {14, 15, 24}, + {23, 14, 24}, + {15, 16, 24}, + {16, 17, 24}, + {17, 22, 24}, + {23, 24, 22}, + {0, 8, 25}, + {5, 4, 26}, + {6, 5, 27}, + {5, 26, 27}, + {7, 6, 28}, + {6, 27, 28}, + {8, 7, 29}, + {25, 8, 29}, + {7, 28, 29}, + {10, 9, 30}, + {11, 10, 31}, + {10, 30, 31}, + {12, 11, 32}, + {11, 31, 32}, + {13, 12, 33}, + {12, 32, 33}, + {14, 13, 34}, + {13, 33, 34}, + {15, 14, 35}, + {14, 34, 35}, + {16, 15, 36}, + {15, 35, 36}, + {17, 16, 37}, + {16, 36, 37}, + {1, 0, 38}, + {2, 1, 39}, + {3, 2, 40}, + {4, 3, 41}, + {26, 4, 41}, + {3, 40, 41}, + {1, 38, 39}, + {17, 37, 9}, + {38, 0, 25}, + {30, 9, 37}, + {40, 2, 39}, + {39, 38, 37}, + {28, 27, 32}, + {31, 30, 29}, + {32, 31, 28}, + {33, 32, 27}, + {34, 33, 26}, + {36, 35, 40}, + {37, 36, 39}, + {30, 37, 38}, + {34, 26, 41}, + {27, 26, 33}, + {40, 39, 36}, + {28, 31, 29}, + {40, 35, 41}, + {30, 38, 25}, + {25, 29, 30}, + {41, 35, 34}, +}; + +#define CUBE_NUM_VERTICES 54 +#define CUBE_NUM_TRIANGLES 90 + +static btScalar cube_vertices[CUBE_NUM_VERTICES * 3] = { + btScalar(0.400000), btScalar(-0.400000), btScalar(-0.400000), + btScalar(0.400000), btScalar(-0.400000), btScalar(-0.129695), + btScalar(0.400000), btScalar(-0.400000), btScalar(0.157468), + btScalar(0.400000), btScalar(-0.400000), btScalar(0.400000), + btScalar(-0.400000), btScalar(-0.400000), btScalar(-0.400000), + btScalar(-0.137266), btScalar(-0.400000), btScalar(-0.400000), + btScalar(0.142832), btScalar(-0.400000), btScalar(-0.400000), + btScalar(-0.400000), btScalar(-0.400000), btScalar(0.400000), + btScalar(-0.400000), btScalar(-0.400000), btScalar(0.144537), + btScalar(-0.400000), btScalar(-0.400000), btScalar(-0.132810), + btScalar(0.147946), btScalar(-0.400000), btScalar(0.400000), + btScalar(-0.127038), btScalar(-0.400000), btScalar(0.400000), + btScalar(0.400000), btScalar(-0.156914), btScalar(-0.400000), + btScalar(0.400000), btScalar(0.110878), btScalar(-0.400000), + btScalar(0.400000), btScalar(0.400000), btScalar(-0.400000), + btScalar(0.400000), btScalar(0.400000), btScalar(0.400000), + btScalar(0.400000), btScalar(0.143565), btScalar(0.400000), + btScalar(0.400000), btScalar(-0.142881), btScalar(0.400000), + btScalar(0.400000), btScalar(0.400000), btScalar(-0.142285), + btScalar(0.400000), btScalar(0.400000), btScalar(0.142285), + btScalar(-0.400000), btScalar(-0.155504), btScalar(-0.400000), + btScalar(-0.400000), btScalar(0.143304), btScalar(-0.400000), + btScalar(-0.400000), btScalar(0.400000), btScalar(-0.400000), + btScalar(-0.137266), btScalar(0.400000), btScalar(-0.400000), + btScalar(0.142832), btScalar(0.400000), btScalar(-0.400000), + btScalar(-0.400000), btScalar(0.400000), btScalar(0.400000), + btScalar(-0.400000), btScalar(0.123157), btScalar(0.400000), + btScalar(-0.400000), btScalar(-0.151643), btScalar(0.400000), + btScalar(0.147946), btScalar(0.400000), btScalar(0.400000), + btScalar(-0.127038), btScalar(0.400000), btScalar(0.400000), + btScalar(-0.400000), btScalar(0.400000), btScalar(-0.145673), + btScalar(-0.400000), btScalar(0.400000), btScalar(0.145673), + btScalar(0.149457), btScalar(-0.400000), btScalar(0.029476), + btScalar(-0.118651), btScalar(-0.400000), btScalar(-0.091520), + btScalar(-0.116729), btScalar(-0.400000), btScalar(0.185444), + btScalar(0.400000), btScalar(-0.030750), btScalar(0.108353), + btScalar(0.400000), btScalar(-0.017128), btScalar(-0.173998), + btScalar(-0.098445), btScalar(-0.123516), btScalar(-0.400000), + btScalar(0.189421), btScalar(-0.129196), btScalar(-0.400000), + btScalar(0.028300), btScalar(0.131810), btScalar(-0.400000), + btScalar(-0.121334), btScalar(-0.101441), btScalar(0.400000), + btScalar(0.149876), btScalar(0.018849), btScalar(0.400000), + btScalar(-0.114236), btScalar(0.180350), btScalar(0.400000), + btScalar(0.140128), btScalar(0.400000), btScalar(0.051515), + btScalar(-0.119461), btScalar(0.400000), btScalar(-0.055704), + btScalar(-0.400000), btScalar(-0.140426), btScalar(-0.044838), + btScalar(-0.400000), btScalar(0.123997), btScalar(0.045044), + btScalar(-0.157858), btScalar(-0.190293), btScalar(0.146609), + btScalar(0.104141), btScalar(-0.199541), btScalar(0.222140), + btScalar(-0.207788), btScalar(0.065226), btScalar(0.172945), + btScalar(0.103299), btScalar(-0.168979), btScalar(-0.094225), + btScalar(0.130475), btScalar(0.068676), btScalar(-0.129420), + btScalar(0.065630), btScalar(0.075409), btScalar(0.150963), + btScalar(-0.172328), btScalar(0.041173), btScalar(-0.142551), +}; + +static int cube_indices[CUBE_NUM_TRIANGLES][3] = { + {0, 1, 6}, + {1, 2, 32}, + {2, 3, 10}, + {4, 5, 9}, + {5, 6, 33}, + {9, 5, 33}, + {8, 34, 7}, + {8, 9, 33}, + {10, 11, 34}, + {11, 7, 34}, + {2, 10, 32}, + {6, 1, 32}, + {34, 8, 33}, + {6, 32, 33}, + {10, 34, 32}, + {32, 34, 33}, + {36, 1, 12}, + {2, 1, 35}, + {3, 2, 17}, + {12, 13, 36}, + {13, 14, 18}, + {15, 16, 19}, + {19, 16, 35}, + {16, 17, 35}, + {18, 19, 35}, + {17, 2, 35}, + {0, 12, 1}, + {13, 18, 36}, + {35, 1, 36}, + {36, 18, 35}, + {6, 38, 0}, + {5, 4, 20}, + {6, 5, 37}, + {5, 20, 37}, + {13, 12, 38}, + {14, 13, 24}, + {20, 21, 37}, + {21, 22, 23}, + {23, 24, 39}, + {21, 23, 39}, + {24, 13, 39}, + {12, 0, 38}, + {13, 38, 39}, + {37, 21, 39}, + {39, 38, 37}, + {6, 37, 38}, + {10, 3, 17}, + {7, 11, 27}, + {27, 11, 40}, + {11, 10, 40}, + {16, 15, 28}, + {17, 16, 41}, + {26, 42, 25}, + {26, 27, 40}, + {28, 29, 42}, + {29, 25, 42}, + {16, 28, 41}, + {10, 17, 41}, + {10, 41, 40}, + {26, 40, 42}, + {42, 40, 41}, + {28, 42, 41}, + {18, 14, 24}, + {15, 19, 28}, + {19, 18, 43}, + {28, 19, 43}, + {23, 22, 30}, + {24, 23, 44}, + {25, 29, 31}, + {29, 28, 43}, + {23, 30, 44}, + {44, 30, 31}, + {43, 44, 29}, + {18, 24, 43}, + {31, 29, 44}, + {24, 44, 43}, + {4, 9, 20}, + {8, 7, 27}, + {9, 8, 45}, + {8, 27, 45}, + {22, 21, 30}, + {26, 25, 31}, + {26, 31, 46}, + {27, 26, 46}, + {31, 30, 46}, + {20, 9, 45}, + {30, 21, 46}, + {45, 27, 46}, + {46, 21, 45}, + {21, 20, 45}, +}; + +#endif diff --git a/legacy/ephysics/src/lib/ephysics_world.cpp b/legacy/ephysics/src/lib/ephysics_world.cpp index d8314cac4e..157cd219b8 100644 --- a/legacy/ephysics/src/lib/ephysics_world.cpp +++ b/legacy/ephysics/src/lib/ephysics_world.cpp @@ -10,6 +10,8 @@ extern "C" { #endif +#define DEFAULT_GRAVITY btVector3(0, -9.8, 0) + typedef struct _EPhysics_World_Callback EPhysics_World_Callback; struct _EPhysics_World_Callback { @@ -26,7 +28,9 @@ struct _EPhysics_World { btDefaultCollisionConfiguration* collision; btCollisionDispatcher* dispatcher; btSequentialImpulseConstraintSolver* solver; - btDiscreteDynamicsWorld* dynamics_world; + btSoftRigidDynamicsWorld* dynamics_world; + btSoftBodyWorldInfo* world_info; + btSoftBodySolver* soft_solver; EPhysics_Body *boundaries[4]; EPhysics_Camera *camera; @@ -39,6 +43,7 @@ struct _EPhysics_World { int max_sub_steps; int walking; int cb_walking; + int soft_body_ref; double last_update; double rate; double fixed_time_step; @@ -60,6 +65,12 @@ static Eina_List *_worlds_to_delete = NULL; static Ecore_Animator *_anim_simulate = NULL; static int _worlds_walking = 0; +btSoftBodyWorldInfo * +ephysics_world_info_get(const EPhysics_World *world) +{ + return world->world_info; +} + struct _ephysics_world_ovelap_filter_cb : public btOverlapFilterCallback { virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0, @@ -81,7 +92,11 @@ struct _ephysics_world_ovelap_filter_cb : public btOverlapFilterCallback static inline void _ephysics_world_gravity_set(EPhysics_World *world, double gx, double gy, double rate) { - world->dynamics_world->setGravity(btVector3(gx / rate, -gy / rate, 0)); + btVector3 gravity; + + gravity = btVector3(gx / rate, -gy / rate, 0); + world->dynamics_world->setGravity(gravity); + world->world_info->m_gravity = gravity; } static void @@ -226,6 +241,8 @@ _ephysics_world_free(EPhysics_World *world) delete world->broadphase; delete world->dispatcher; delete world->collision; + delete world->soft_solver; + delete world->world_info; */ free(world); @@ -259,8 +276,15 @@ _simulate_worlds(void *data __UNUSED__) world->last_update = time_now; gDeactivationTime = world->max_sleeping_time; - world->dynamics_world->stepSimulation(delta, world->max_sub_steps, + + if (world->soft_body_ref) + world->dynamics_world->stepSimulation(delta, world->max_sub_steps, world->fixed_time_step); + else + ((btDiscreteDynamicsWorld *)world->dynamics_world)->stepSimulation( + delta, world->max_sub_steps, + world->fixed_time_step); + world->walking--; if (!world->walking) @@ -322,8 +346,9 @@ _ephysics_world_boundary_del_cb(void *data, EPhysics_Body *body, void *event_inf Eina_Bool ephysics_world_body_add(EPhysics_World *world, EPhysics_Body *body) { - world->bodies = eina_inlist_append(world->bodies, - EINA_INLIST_GET(body)); + if (!eina_inlist_find(world->bodies, EINA_INLIST_GET(body))) + world->bodies = eina_inlist_append(world->bodies, EINA_INLIST_GET(body)); + if (eina_error_get()) { ERR("Couldn't add body to bodies list."); @@ -331,13 +356,14 @@ ephysics_world_body_add(EPhysics_World *world, EPhysics_Body *body) } world->dynamics_world->addRigidBody(ephysics_body_rigid_body_get(body)); - return EINA_TRUE; } Eina_Bool ephysics_world_body_del(EPhysics_World *world, EPhysics_Body *body) { + btSoftBody *soft_body; + if (world->walking) { world->to_delete = eina_list_append(world->to_delete, body); @@ -345,13 +371,37 @@ ephysics_world_body_del(EPhysics_World *world, EPhysics_Body *body) } world->dynamics_world->removeRigidBody(ephysics_body_rigid_body_get(body)); - world->bodies = eina_inlist_remove(world->bodies, - EINA_INLIST_GET(body)); + + soft_body = ephysics_body_soft_body_get(body); + if (soft_body) + { + world->dynamics_world->removeSoftBody(soft_body); + --world->soft_body_ref; + } + + world->bodies = eina_inlist_remove(world->bodies, EINA_INLIST_GET(body)); ephysics_orphan_body_del(body); return EINA_TRUE; } +Eina_Bool +ephysics_world_soft_body_add(EPhysics_World *world, EPhysics_Body *body) +{ + if (!eina_inlist_find(world->bodies, EINA_INLIST_GET(body))) + world->bodies = eina_inlist_append(world->bodies, EINA_INLIST_GET(body)); + + if (eina_error_get()) + { + ERR("Couldn't add body to bodies list."); + return EINA_FALSE; + } + + ++world->soft_body_ref; + world->dynamics_world->addSoftBody(ephysics_body_soft_body_get(body)); + return EINA_TRUE; +} + void ephysics_world_constraint_add(EPhysics_World *world, EPhysics_Constraint *constraint, btTypedConstraint *bt_constraint) { @@ -446,7 +496,7 @@ ephysics_world_new(void) goto no_broadphase; } - world->collision = new btDefaultCollisionConfiguration(); + world->collision = new btSoftBodyRigidBodyCollisionConfiguration(); if (!world->collision) { ERR("Couldn't configure collision."); @@ -467,15 +517,34 @@ ephysics_world_new(void) goto no_solver; } - world->dynamics_world = new btDiscreteDynamicsWorld( + world->soft_solver = new btDefaultSoftBodySolver(); + if (!world->soft_solver) + { + ERR("Couldn't create soft body solver."); + goto no_soft_solver; + } + + world->dynamics_world = new btSoftRigidDynamicsWorld( world->dispatcher, world->broadphase, world->solver, - world->collision); + world->collision, world->soft_solver); if (!world->dynamics_world) { ERR("Couldn't create dynamic world."); goto no_world; } + world->world_info = new btSoftBodyWorldInfo(); + if (!world->world_info) + { + ERR("Couldn't create soft body world info."); + goto no_world_info; + } + + world->world_info->m_gravity = DEFAULT_GRAVITY; + world->world_info->m_broadphase = world->broadphase; + world->world_info->m_dispatcher = world->dispatcher; + world->world_info->m_sparsesdf.Initialize(); + _worlds = eina_inlist_append(_worlds, EINA_INLIST_GET(world)); if (eina_error_get()) { @@ -485,7 +554,7 @@ ephysics_world_new(void) world->dynamics_world->getSolverInfo().m_solverMode ^= EPHYSICS_WORLD_SOLVER_SIMD; - world->dynamics_world->setGravity(btVector3(0, -9.8, 0)); + world->dynamics_world->setGravity(DEFAULT_GRAVITY); filter_cb = new _ephysics_world_ovelap_filter_cb(); if (!filter_cb) @@ -493,6 +562,7 @@ ephysics_world_new(void) else world->dynamics_world->getPairCache()->setOverlapFilterCallback(filter_cb); + world->soft_body_ref = 0; world->rate = 30; world->max_sub_steps = 3; world->fixed_time_step = 1/60.f; @@ -510,8 +580,12 @@ ephysics_world_new(void) return world; no_list: + delete world->world_info; +no_world_info: delete world->dynamics_world; no_world: + delete world->soft_solver; +no_soft_solver: delete world->solver; no_solver: delete world->dispatcher;