EPhysics: soft body implementation

Introduces soft body dynamics and calls to create soft circles and boxes.


Patch by: Leandro Dorileo <dorileo@profusion.mobi>



SVN revision: 75564
This commit is contained in:
Leandro Dorileo 2012-08-22 20:04:39 +00:00 committed by Bruno Dilly
parent 0ef94e328e
commit 18743b72ad
8 changed files with 884 additions and 27 deletions

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,160 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#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);
}

View File

@ -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.

View File

@ -4,7 +4,10 @@
#include <Evas.h>
#include <math.h>
#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);

View File

@ -5,6 +5,10 @@
# include <Evil.h>
#endif
#include <BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h>
#include <BulletSoftBody/btDefaultSoftBodySolver.h>
#include <BulletSoftBody/btSoftRigidDynamicsWorld.h>
#include <BulletSoftBody/btSoftBodyHelpers.h>
#include <btBulletDynamicsCommon.h>
#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);

View File

@ -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

View File

@ -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;