2012-06-26 15:36:12 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <Evas.h>
|
2012-10-16 16:12:47 -07:00
|
|
|
#include <Ecore.h>
|
2012-08-22 13:05:19 -07:00
|
|
|
#include <BulletCollision/CollisionShapes/btShapeHull.h>
|
2012-09-12 14:50:01 -07:00
|
|
|
#include <LinearMath/btGeometryUtil.h>
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
#include <math.h>
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
#include "ephysics_private.h"
|
2012-08-22 13:04:39 -07:00
|
|
|
#include "ephysics_trimesh.h"
|
2012-10-04 15:39:42 -07:00
|
|
|
#include "ephysics_body_materials.h"
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct _EPhysics_Body_Callback EPhysics_Body_Callback;
|
2012-10-25 14:54:14 -07:00
|
|
|
typedef struct _EPhysics_Body_Evas_Stacking EPhysics_Body_Evas_Stacking;
|
|
|
|
typedef struct _EPhysics_Body_Soft_Body_Slice EPhysics_Body_Soft_Body_Slice;
|
2012-11-09 10:52:42 -08:00
|
|
|
typedef struct _EPhysics_Body_Face_Obj EPhysics_Body_Face_Obj;
|
2012-11-13 14:18:16 -08:00
|
|
|
typedef struct _EPhysics_Quaternion EPhysics_Quaternion;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
struct _EPhysics_Body_Callback {
|
|
|
|
EINA_INLIST;
|
|
|
|
void (*func) (void *data, EPhysics_Body *body, void *event_info);
|
|
|
|
void *data;
|
2012-07-02 19:09:34 -07:00
|
|
|
EPhysics_Callback_Body_Type type;
|
2012-08-10 14:04:08 -07:00
|
|
|
Eina_Bool deleted:1;
|
2012-06-26 15:36:12 -07:00
|
|
|
};
|
|
|
|
|
2012-07-27 07:49:37 -07:00
|
|
|
struct _EPhysics_Body_Collision {
|
|
|
|
EPhysics_Body *contact_body;
|
|
|
|
Evas_Coord x;
|
|
|
|
Evas_Coord y;
|
2012-10-10 12:17:13 -07:00
|
|
|
Evas_Coord z;
|
2012-07-27 07:49:37 -07:00
|
|
|
};
|
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
struct _EPhysics_Body_Evas_Stacking {
|
2012-10-16 16:12:59 -07:00
|
|
|
Evas_Object *evas;
|
|
|
|
float stacking;
|
2012-10-25 14:54:14 -07:00
|
|
|
};
|
2012-10-16 16:12:59 -07:00
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
struct _EPhysics_Body_Soft_Body_Slice
|
2012-10-04 15:40:07 -07:00
|
|
|
{
|
|
|
|
Evas_Object *evas_obj;
|
2012-10-25 14:53:16 -07:00
|
|
|
int index;
|
2012-10-25 14:54:14 -07:00
|
|
|
struct {
|
|
|
|
double x;
|
|
|
|
double y;
|
|
|
|
} p[3];
|
2012-10-16 16:12:59 -07:00
|
|
|
float stacking;
|
2012-10-25 14:54:14 -07:00
|
|
|
};
|
2012-10-04 15:40:07 -07:00
|
|
|
|
2012-11-09 10:52:42 -08:00
|
|
|
struct _EPhysics_Body_Face_Obj {
|
2012-11-09 10:52:49 -08:00
|
|
|
EPhysics_Body_Face face;
|
2012-11-09 10:52:42 -08:00
|
|
|
Evas_Object *obj;
|
|
|
|
};
|
|
|
|
|
2012-10-04 15:40:07 -07:00
|
|
|
static void
|
2012-11-23 13:51:38 -08:00
|
|
|
_ephysics_body_soft_body_slices_apply(EPhysics_Body *body, Evas_Object *evas_obj, Eina_List *slices)
|
2012-10-04 15:40:07 -07:00
|
|
|
{
|
|
|
|
double rate;
|
2012-10-16 16:12:59 -07:00
|
|
|
void *list_data;
|
2012-10-04 15:40:07 -07:00
|
|
|
Eina_List *l;
|
2012-10-31 14:02:50 -07:00
|
|
|
Evas_Coord wy, wh, y0, y1, y2, x0, x1, x2, z0, z1, z2, w, h;
|
2012-10-04 15:40:07 -07:00
|
|
|
Evas_Map *map;
|
|
|
|
btVector3 p0, p1, p2;
|
|
|
|
btSoftBody::tFaceArray faces;
|
|
|
|
EPhysics_Body_Soft_Body_Slice *slice;
|
2012-10-25 14:53:23 -07:00
|
|
|
int lr, lg, lb, ar, ag, ab;
|
|
|
|
Evas_Coord lx, ly, lz;
|
|
|
|
Eina_Bool light = EINA_FALSE;
|
2012-10-25 14:53:37 -07:00
|
|
|
EPhysics_Camera *camera;
|
|
|
|
int px, py, pz, foc;
|
|
|
|
Eina_Bool perspective = EINA_FALSE;
|
2012-10-04 15:40:07 -07:00
|
|
|
|
2012-10-25 14:53:37 -07:00
|
|
|
camera = ephysics_world_camera_get(body->world);
|
2012-10-04 15:40:07 -07:00
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-10-16 16:12:59 -07:00
|
|
|
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, NULL, &wh,
|
|
|
|
NULL);
|
2012-11-23 13:51:38 -08:00
|
|
|
evas_object_geometry_get(evas_obj, NULL, NULL, &w, &h);
|
2012-10-25 14:53:23 -07:00
|
|
|
|
|
|
|
if ((body->light_apply) ||
|
|
|
|
(ephysics_world_light_all_bodies_get(body->world)))
|
|
|
|
{
|
2012-10-30 11:31:32 -07:00
|
|
|
ephysics_world_point_light_position_get(body->world, &lx, &ly, &lz);
|
|
|
|
ephysics_world_point_light_color_get(body->world, &lr, &lg, &lb);
|
|
|
|
ephysics_world_ambient_light_color_get(body->world, &ar, &ag, &ab);
|
|
|
|
light = EINA_TRUE;
|
2012-10-25 14:53:23 -07:00
|
|
|
}
|
|
|
|
|
2012-10-25 14:53:37 -07:00
|
|
|
if (ephysics_camera_perspective_enabled_get(camera))
|
|
|
|
{
|
|
|
|
ephysics_camera_perspective_get(camera, &px, &py, &pz, &foc);
|
|
|
|
perspective = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:49:51 -08:00
|
|
|
EINA_LIST_FOREACH(slices, l, list_data)
|
2012-10-04 15:40:07 -07:00
|
|
|
{
|
2012-10-16 16:12:59 -07:00
|
|
|
slice = (EPhysics_Body_Soft_Body_Slice *)list_data;
|
2012-10-04 15:40:07 -07:00
|
|
|
|
|
|
|
faces = body->soft_body->m_faces;
|
|
|
|
p0 = faces[slice->index].m_n[0]->m_x;
|
|
|
|
p1 = faces[slice->index].m_n[1]->m_x;
|
|
|
|
p2 = faces[slice->index].m_n[2]->m_x;
|
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
slice->stacking = p0.z() + p1.z() + p2.z();
|
|
|
|
|
|
|
|
map = evas_map_new(4);
|
|
|
|
|
|
|
|
evas_map_point_image_uv_set(map, 0, slice->p[0].x * w,
|
|
|
|
slice->p[0].y * h);
|
|
|
|
evas_map_point_image_uv_set(map, 1, slice->p[1].x * w,
|
|
|
|
slice->p[1].y * h);
|
|
|
|
evas_map_point_image_uv_set(map, 2, slice->p[2].x * w,
|
|
|
|
slice->p[2].y * h);
|
|
|
|
evas_map_point_image_uv_set(map, 3, slice->p[2].x * w,
|
|
|
|
slice->p[2].y * h);
|
2012-10-04 15:40:07 -07:00
|
|
|
|
|
|
|
x0 = p0.x() * rate;
|
|
|
|
x1 = p1.x() * rate;
|
|
|
|
x2 = p2.x() * rate;
|
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
y0 = wh + wy - (p0.y() * rate);
|
|
|
|
y1 = wh + wy - (p1.y() * rate);
|
|
|
|
y2 = wh + wy - (p2.y() * rate);
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
z0 = p0.z() * rate;
|
|
|
|
z1 = p1.z() * rate;
|
|
|
|
z2 = p2.z() * rate;
|
|
|
|
|
|
|
|
evas_map_point_coord_set(map, 0, x0, y0, z0);
|
|
|
|
evas_map_point_coord_set(map, 1, x1, y1, z1);
|
|
|
|
evas_map_point_coord_set(map, 2, x2, y2, z2);
|
|
|
|
evas_map_point_coord_set(map, 3, x2, y2, z2);
|
2012-10-04 15:40:07 -07:00
|
|
|
|
2012-10-25 14:53:37 -07:00
|
|
|
if (perspective)
|
|
|
|
evas_map_util_3d_perspective(map, px, py, pz, foc);
|
|
|
|
|
|
|
|
if (body->back_face_culling)
|
|
|
|
{
|
|
|
|
if (evas_map_util_clockwise_get(map))
|
|
|
|
evas_object_show(slice->evas_obj);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
evas_map_free(map);
|
|
|
|
evas_object_hide(slice->evas_obj);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-25 14:53:23 -07:00
|
|
|
if (light)
|
|
|
|
evas_map_util_3d_lighting(map, lx, ly, lz, lr, lg, lb, ar, ag, ab);
|
|
|
|
|
2012-10-04 15:40:07 -07:00
|
|
|
evas_object_map_set(slice->evas_obj, map);
|
|
|
|
evas_object_map_enable_set(slice->evas_obj, EINA_TRUE);
|
2012-10-25 14:53:16 -07:00
|
|
|
evas_map_free(map);
|
2012-10-04 15:40:07 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
static inline double
|
|
|
|
_ephysics_body_soft_body_slice_calc(double val, double delta, double max)
|
|
|
|
{
|
|
|
|
double ret = val + delta / max;
|
|
|
|
if (ret < 0)
|
|
|
|
ret = 0;
|
|
|
|
else if (ret > 1)
|
|
|
|
ret = 1;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:07 -07:00
|
|
|
static EPhysics_Body_Soft_Body_Slice *
|
2012-10-25 14:54:14 -07:00
|
|
|
_ephysics_body_soft_body_slice_new(EPhysics_Body *body, double delta, double max, int index)
|
2012-10-04 15:40:07 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body_Soft_Body_Slice *slice;
|
2012-10-25 14:54:14 -07:00
|
|
|
btSoftBody::tFaceArray faces;
|
2012-10-04 15:40:07 -07:00
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
slice = (EPhysics_Body_Soft_Body_Slice *)calloc(
|
|
|
|
1, sizeof(EPhysics_Body_Soft_Body_Slice));
|
2012-10-04 15:40:07 -07:00
|
|
|
if (!slice)
|
|
|
|
{
|
|
|
|
ERR("Couldn't allocate EPhysics_Soft_Body_Slice memory.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
faces = body->soft_body->m_faces;
|
|
|
|
|
2012-10-04 15:40:07 -07:00
|
|
|
slice->index = index;
|
2012-10-25 14:54:14 -07:00
|
|
|
slice->p[0].x = _ephysics_body_soft_body_slice_calc(
|
|
|
|
faces[slice->index].m_n[0]->m_x.x(), delta, max);
|
|
|
|
slice->p[0].y = 1 - _ephysics_body_soft_body_slice_calc(
|
|
|
|
faces[slice->index].m_n[0]->m_x.y(), delta, max);
|
|
|
|
slice->p[1].x = _ephysics_body_soft_body_slice_calc(
|
|
|
|
faces[slice->index].m_n[1]->m_x.x(), delta, max);
|
|
|
|
slice->p[1].y = 1 - _ephysics_body_soft_body_slice_calc(
|
|
|
|
faces[slice->index].m_n[1]->m_x.y(), delta, max);
|
|
|
|
slice->p[2].x = _ephysics_body_soft_body_slice_calc(
|
|
|
|
faces[slice->index].m_n[2]->m_x.x(), delta, max);
|
|
|
|
slice->p[2].y = 1 - _ephysics_body_soft_body_slice_calc(
|
|
|
|
faces[slice->index].m_n[2]->m_x.y(), delta, max);
|
|
|
|
|
2012-10-04 15:40:07 -07:00
|
|
|
return slice;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:51:44 -08:00
|
|
|
static Eina_List *
|
|
|
|
_ephysics_body_soft_body_slices_get(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
Eina_List *l, *slices_list, *slices = NULL;
|
|
|
|
void *ldata, *slice_data;
|
|
|
|
EPhysics_Body_Face_Slice *face_slice;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->faces_slices, l, ldata)
|
|
|
|
{
|
|
|
|
face_slice = (EPhysics_Body_Face_Slice *)ldata;
|
|
|
|
EINA_LIST_FOREACH(face_slice->slices, slices_list, slice_data)
|
|
|
|
slices = eina_list_append(slices, slice_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return slices;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
ephysics_body_soft_body_slice_index_get(EPhysics_Body *body, Evas_Object *slice)
|
|
|
|
{
|
|
|
|
Eina_List *slices;
|
|
|
|
void *ldata;
|
|
|
|
EPhysics_Body_Soft_Body_Slice *slice_data;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get soft body slice index, body is null.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Can't get soft body slice index, operation not allowed for rigid"
|
|
|
|
" bodies.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
slices = _ephysics_body_soft_body_slices_get(body);
|
|
|
|
EINA_LIST_FREE(slices, ldata)
|
|
|
|
{
|
|
|
|
slice_data = (EPhysics_Body_Soft_Body_Slice *)ldata;
|
|
|
|
if (slice_data->evas_obj == slice)
|
|
|
|
return slice_data->index;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:51:53 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_slice_del_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
|
|
|
|
{
|
|
|
|
EPhysics_Body_Soft_Body_Slice *slice = (EPhysics_Body_Soft_Body_Slice *)data;
|
|
|
|
slice->evas_obj = NULL;
|
|
|
|
evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_soft_body_slice_del_cb);
|
|
|
|
}
|
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
static void
|
2012-11-23 13:50:02 -08:00
|
|
|
_ephysics_body_soft_body_slices_init(EPhysics_Body *body, Evas_Object *obj, Eina_List *slices)
|
2012-10-04 15:40:07 -07:00
|
|
|
{
|
2012-10-25 14:53:16 -07:00
|
|
|
EPhysics_Body_Soft_Body_Slice *slice = NULL;
|
2012-10-04 15:40:07 -07:00
|
|
|
btVector3 p0, p1, p2;
|
2012-10-25 14:54:14 -07:00
|
|
|
void *slice_data;
|
2012-10-31 14:03:02 -07:00
|
|
|
Evas_Coord w, h;
|
2012-10-25 14:54:14 -07:00
|
|
|
Eina_List *l;
|
2012-10-25 14:53:16 -07:00
|
|
|
Evas *evas;
|
2012-12-10 09:15:05 -08:00
|
|
|
Evas_Object *parent;
|
2012-10-04 15:40:07 -07:00
|
|
|
|
2012-11-23 13:50:02 -08:00
|
|
|
evas = evas_object_evas_get(obj);
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
|
2012-10-04 15:40:07 -07:00
|
|
|
|
2012-12-10 09:15:05 -08:00
|
|
|
parent = evas_object_smart_parent_get(obj);
|
2012-11-23 13:49:51 -08:00
|
|
|
EINA_LIST_FOREACH(slices, l, slice_data)
|
2012-10-04 15:40:07 -07:00
|
|
|
{
|
2012-10-25 14:54:14 -07:00
|
|
|
slice = (EPhysics_Body_Soft_Body_Slice *) slice_data;
|
|
|
|
slice->evas_obj = evas_object_image_filled_add(evas);
|
2012-10-30 11:31:52 -07:00
|
|
|
evas_object_layer_set(slice->evas_obj,
|
2012-11-23 13:50:02 -08:00
|
|
|
evas_object_layer_get(obj));
|
|
|
|
evas_object_image_source_set(slice->evas_obj, obj);
|
2012-10-31 14:02:50 -07:00
|
|
|
evas_object_image_source_events_set(slice->evas_obj, EINA_TRUE);
|
2012-10-31 14:03:02 -07:00
|
|
|
evas_object_resize(slice->evas_obj, w, h);
|
2012-10-04 15:40:07 -07:00
|
|
|
evas_object_show(slice->evas_obj);
|
2012-10-25 14:53:16 -07:00
|
|
|
evas_object_image_smooth_scale_set(slice->evas_obj, EINA_TRUE);
|
2012-11-23 13:51:53 -08:00
|
|
|
evas_object_event_callback_add(slice->evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_soft_body_slice_del_cb,
|
|
|
|
slice);
|
2012-12-10 09:15:05 -08:00
|
|
|
|
|
|
|
if (parent) evas_object_smart_member_add(slice->evas_obj, parent);
|
2012-10-04 15:40:07 -07:00
|
|
|
}
|
|
|
|
|
2012-10-25 14:53:16 -07:00
|
|
|
if (slice)
|
2012-10-31 14:02:50 -07:00
|
|
|
evas_object_image_source_visible_set(slice->evas_obj, EINA_FALSE);
|
2012-10-25 14:53:16 -07:00
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
_ephysics_body_soft_body_slices_apply(body, obj, slices);
|
2012-10-04 15:40:07 -07:00
|
|
|
}
|
|
|
|
|
2012-11-23 13:51:03 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_slices_free(Eina_List *slices)
|
|
|
|
{
|
|
|
|
EPhysics_Body_Soft_Body_Slice *slice;
|
|
|
|
void *slice_data;
|
|
|
|
|
|
|
|
EINA_LIST_FREE(slices, slice_data)
|
|
|
|
{
|
|
|
|
slice = (EPhysics_Body_Soft_Body_Slice *)slice_data;
|
2012-11-23 13:51:53 -08:00
|
|
|
if (slice->evas_obj)
|
|
|
|
evas_object_del(slice->evas_obj);
|
2012-11-23 13:51:03 -08:00
|
|
|
free(slice);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:07 -07:00
|
|
|
static void
|
2012-11-23 13:49:51 -08:00
|
|
|
_ephysics_body_soft_body_slices_clean(Eina_List *slices)
|
2012-10-25 14:54:14 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body_Soft_Body_Slice *slice;
|
|
|
|
void *slice_data;
|
|
|
|
Eina_List *l;
|
|
|
|
|
2012-11-23 13:49:51 -08:00
|
|
|
EINA_LIST_FOREACH(slices, l, slice_data)
|
2012-10-25 14:54:14 -07:00
|
|
|
{
|
|
|
|
slice = (EPhysics_Body_Soft_Body_Slice *)slice_data;
|
2012-11-23 13:51:53 -08:00
|
|
|
if (slice->evas_obj)
|
|
|
|
evas_object_del(slice->evas_obj);
|
2012-10-25 14:54:14 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
static btTransform
|
|
|
|
_ephysics_body_transform_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
btTransform trans;
|
|
|
|
btVector3 center;
|
|
|
|
btScalar radius;
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
body->rigid_body->getMotionState()->getWorldTransform(trans);
|
|
|
|
return trans;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->soft_body->getCollisionShape()->getBoundingSphere(center, radius);
|
|
|
|
trans.setIdentity();
|
|
|
|
trans.setOrigin(center);
|
|
|
|
return trans;
|
|
|
|
}
|
|
|
|
|
2012-10-16 16:12:59 -07:00
|
|
|
static int
|
|
|
|
_ephysics_body_evas_stacking_sort_cb(const void *d1, const void *d2)
|
|
|
|
{
|
|
|
|
const EPhysics_Body_Evas_Stacking *stacking1, *stacking2;
|
|
|
|
|
|
|
|
stacking1 = (const EPhysics_Body_Evas_Stacking *)d1;
|
|
|
|
stacking2 = (const EPhysics_Body_Evas_Stacking *)d2;
|
|
|
|
|
2012-10-30 11:31:58 -07:00
|
|
|
if (!stacking1) return 1;
|
|
|
|
if (!stacking2) return -1;
|
2012-10-16 16:12:59 -07:00
|
|
|
|
2012-10-30 11:31:58 -07:00
|
|
|
if (stacking1->stacking < stacking2->stacking) return -1;
|
|
|
|
if (stacking2->stacking > stacking2->stacking) return 1;
|
2012-10-16 16:12:59 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-10-30 11:31:52 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_evas_objects_restack_free(void *data)
|
|
|
|
{
|
|
|
|
Eina_List *l, *stack_list = (Eina_List *)data;
|
|
|
|
void *ldata;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(stack_list, l, ldata)
|
|
|
|
free(ldata);
|
|
|
|
|
|
|
|
eina_list_free(stack_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static EPhysics_Body_Evas_Stacking *
|
|
|
|
_ephysics_body_evas_stacking_new(Evas_Object *obj, float index)
|
|
|
|
{
|
|
|
|
EPhysics_Body_Evas_Stacking *stacking;
|
|
|
|
|
|
|
|
stacking = (EPhysics_Body_Evas_Stacking *)calloc(
|
|
|
|
1, sizeof(EPhysics_Body_Evas_Stacking));
|
|
|
|
|
|
|
|
if (!stacking)
|
|
|
|
{
|
|
|
|
ERR("Could not allocate ephysics soft body evas stacking data.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
stacking->evas = obj;
|
|
|
|
stacking->stacking = index;
|
|
|
|
return stacking;
|
|
|
|
}
|
|
|
|
|
2012-10-16 16:12:59 -07:00
|
|
|
void
|
|
|
|
ephysics_body_evas_objects_restack(EPhysics_World *world)
|
|
|
|
{
|
2012-10-30 11:31:52 -07:00
|
|
|
void *data, *slice_data, *stack_data;
|
2012-10-16 16:12:59 -07:00
|
|
|
EPhysics_Body *body;
|
|
|
|
btTransform trans;
|
|
|
|
EPhysics_Body_Evas_Stacking *stacking;
|
|
|
|
EPhysics_Body_Soft_Body_Slice *slice;
|
|
|
|
Eina_List *l, *slices, *bodies, *stack_list = NULL;
|
|
|
|
Evas_Object *prev_obj = NULL;
|
2012-10-30 11:31:52 -07:00
|
|
|
Eina_Hash *hash;
|
|
|
|
Eina_Iterator *it;
|
|
|
|
int layer;
|
2012-10-16 16:12:59 -07:00
|
|
|
|
|
|
|
bodies = ephysics_world_bodies_get(world);
|
2012-10-30 11:31:52 -07:00
|
|
|
|
|
|
|
if (!eina_list_count(bodies))
|
|
|
|
return;
|
|
|
|
|
|
|
|
hash = eina_hash_int32_new(_ephysics_body_evas_objects_restack_free);
|
|
|
|
|
2012-11-23 13:51:03 -08:00
|
|
|
EINA_LIST_FREE(bodies, data)
|
2012-10-16 16:12:59 -07:00
|
|
|
{
|
|
|
|
body = (EPhysics_Body *)data;
|
2012-10-25 14:54:22 -07:00
|
|
|
if (body->deleted) continue;
|
|
|
|
|
2012-10-16 16:12:59 -07:00
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
if (!body->evas_obj) continue;
|
|
|
|
trans = _ephysics_body_transform_get(body);
|
2012-10-30 11:31:52 -07:00
|
|
|
stacking = _ephysics_body_evas_stacking_new(body->evas_obj,
|
|
|
|
trans.getOrigin().z());
|
2012-10-16 16:12:59 -07:00
|
|
|
if (!stacking) goto error;
|
2012-10-30 11:31:52 -07:00
|
|
|
|
|
|
|
layer = evas_object_layer_get(stacking->evas);
|
|
|
|
stack_list = (Eina_List *)eina_hash_find(hash, &layer);
|
2012-10-16 16:12:59 -07:00
|
|
|
stack_list = eina_list_append(stack_list, stacking);
|
2012-11-23 13:51:03 -08:00
|
|
|
eina_hash_set(hash, &layer, stack_list);
|
2012-10-30 11:31:52 -07:00
|
|
|
|
2012-10-16 16:12:59 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
slices = _ephysics_body_soft_body_slices_get(body);
|
|
|
|
if (!slices) continue;
|
2012-10-16 16:12:59 -07:00
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
EINA_LIST_FREE(slices, slice_data)
|
2012-10-16 16:12:59 -07:00
|
|
|
{
|
|
|
|
slice = (EPhysics_Body_Soft_Body_Slice *)slice_data;
|
2012-10-30 11:31:52 -07:00
|
|
|
|
|
|
|
stacking = _ephysics_body_evas_stacking_new(slice->evas_obj,
|
|
|
|
slice->stacking);
|
2012-10-16 16:12:59 -07:00
|
|
|
if (!stacking) goto error;
|
2012-10-30 11:31:52 -07:00
|
|
|
|
|
|
|
layer = evas_object_layer_get(stacking->evas);
|
|
|
|
stack_list = (Eina_List *)eina_hash_find(hash, &layer);
|
2012-10-16 16:12:59 -07:00
|
|
|
stack_list = eina_list_append(stack_list, stacking);
|
2012-11-23 13:51:03 -08:00
|
|
|
eina_hash_set(hash, &layer, stack_list);
|
2012-10-16 16:12:59 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-30 11:31:52 -07:00
|
|
|
it = eina_hash_iterator_data_new(hash);
|
|
|
|
while (eina_iterator_next(it, &data))
|
2012-10-16 16:12:59 -07:00
|
|
|
{
|
2012-10-30 11:31:52 -07:00
|
|
|
stack_list = (Eina_List *)data;
|
|
|
|
stack_list = eina_list_sort(stack_list, eina_list_count(stack_list),
|
|
|
|
_ephysics_body_evas_stacking_sort_cb);
|
|
|
|
prev_obj = NULL;
|
2012-10-16 16:12:59 -07:00
|
|
|
|
2012-10-30 11:31:52 -07:00
|
|
|
EINA_LIST_FOREACH(stack_list, l, stack_data)
|
2012-10-18 12:18:00 -07:00
|
|
|
{
|
2012-10-30 11:31:52 -07:00
|
|
|
stacking = (EPhysics_Body_Evas_Stacking *)stack_data;
|
2012-10-18 12:18:00 -07:00
|
|
|
|
2012-10-30 11:31:52 -07:00
|
|
|
if (prev_obj)
|
|
|
|
evas_object_stack_below(stacking->evas, prev_obj);
|
2012-10-16 16:12:59 -07:00
|
|
|
|
2012-10-30 11:31:52 -07:00
|
|
|
prev_obj = stacking->evas;
|
|
|
|
}
|
2012-10-16 16:12:59 -07:00
|
|
|
}
|
|
|
|
|
2012-10-30 11:31:52 -07:00
|
|
|
eina_iterator_free(it);
|
|
|
|
eina_hash_free(hash);
|
2012-10-16 16:12:59 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
error:
|
|
|
|
ERR("Could not allocate evas stacking data memory.");
|
2012-10-30 11:31:52 -07:00
|
|
|
eina_hash_free(hash);
|
2012-10-16 16:12:59 -07:00
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_transform_set(EPhysics_Body *body, btTransform trans)
|
|
|
|
{
|
|
|
|
btTransform origin;
|
|
|
|
|
2012-11-09 10:58:43 -08:00
|
|
|
if (body->type != EPHYSICS_BODY_TYPE_RIGID)
|
2012-10-04 15:40:16 -07:00
|
|
|
{
|
|
|
|
origin = _ephysics_body_transform_get(body);
|
|
|
|
body->soft_body->translate(trans.getOrigin() - origin.getOrigin());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
body->rigid_body->getMotionState()->setWorldTransform(trans);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ephysics_body_activate(const EPhysics_Body *body, Eina_Bool activate)
|
|
|
|
{
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
body->rigid_body->activate(activate);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->soft_body->activate(activate);
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:15:52 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_forces_update(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
body->force.x = body->rigid_body->getTotalForce().getX();
|
|
|
|
body->force.y = body->rigid_body->getTotalForce().getY();
|
2012-10-10 12:17:49 -07:00
|
|
|
body->force.z = body->rigid_body->getTotalForce().getZ();
|
|
|
|
body->force.torque_x = body->rigid_body->getTotalTorque().getX();
|
|
|
|
body->force.torque_y = body->rigid_body->getTotalTorque().getY();
|
|
|
|
body->force.torque_z = body->rigid_body->getTotalTorque().getZ();
|
2012-08-20 15:15:52 -07:00
|
|
|
body->rigid_body->clearForces();
|
|
|
|
}
|
|
|
|
|
2012-08-16 14:35:04 -07:00
|
|
|
static inline void
|
|
|
|
_ephysics_body_sleeping_threshold_set(EPhysics_Body *body, double linear_threshold, double angular_threshold, double rate)
|
|
|
|
{
|
|
|
|
body->rigid_body->setSleepingThresholds(linear_threshold / rate,
|
|
|
|
angular_threshold / RAD_TO_DEG);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2012-10-10 12:17:29 -07:00
|
|
|
_ephysics_body_linear_velocity_set(EPhysics_Body *body, double x, double y, double z, double rate)
|
2012-08-16 14:35:04 -07:00
|
|
|
{
|
2012-12-05 05:50:08 -08:00
|
|
|
btVector3 linear_velocity = btVector3(x / rate, -y / rate, z / rate);
|
|
|
|
|
2012-10-08 11:00:55 -07:00
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
2012-12-05 05:50:08 -08:00
|
|
|
if (body->rigid_body)
|
|
|
|
body->rigid_body->setLinearVelocity(linear_velocity);
|
|
|
|
|
|
|
|
if (body->soft_body)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
|
|
|
|
body->soft_body->m_nodes[i].m_v = linear_velocity;
|
|
|
|
}
|
2012-08-16 14:35:04 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_event_callback_del(EPhysics_Body *body, EPhysics_Body_Callback *cb)
|
|
|
|
{
|
|
|
|
if (cb->deleted) return;
|
|
|
|
|
|
|
|
cb->deleted = EINA_TRUE;
|
|
|
|
|
|
|
|
if (body->walking)
|
|
|
|
{
|
|
|
|
body->to_delete = eina_list_append(body->to_delete, cb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->callbacks = eina_inlist_remove(body->callbacks, EINA_INLIST_GET(cb));
|
|
|
|
free(cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_ephysics_body_event_callback_call(EPhysics_Body *body, EPhysics_Callback_Body_Type type, void *event_info)
|
|
|
|
{
|
|
|
|
Eina_Bool called = EINA_FALSE;
|
|
|
|
EPhysics_Body_Callback *cb;
|
|
|
|
void *clb;
|
|
|
|
|
|
|
|
body->walking++;
|
|
|
|
EINA_INLIST_FOREACH(body->callbacks, cb)
|
|
|
|
{
|
|
|
|
if ((cb->type == type) && (!cb->deleted))
|
|
|
|
{
|
|
|
|
cb->func(cb->data, body, event_info);
|
|
|
|
called = EINA_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
body->walking--;
|
|
|
|
|
|
|
|
if (body->walking > 0) return called;
|
|
|
|
|
|
|
|
EINA_LIST_FREE(body->to_delete, clb)
|
|
|
|
{
|
|
|
|
cb = (EPhysics_Body_Callback *) clb;
|
|
|
|
body->callbacks = eina_inlist_remove(body->callbacks,
|
|
|
|
EINA_INLIST_GET(cb));
|
|
|
|
free(cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return called;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
void
|
|
|
|
ephysics_body_active_set(EPhysics_Body *body, Eina_Bool active)
|
|
|
|
{
|
|
|
|
if (body->active == !!active) return;
|
|
|
|
body->active = !!active;
|
|
|
|
if (active) return;
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
_ephysics_body_event_callback_call(body, EPHYSICS_CALLBACK_BODY_STOPPED,
|
|
|
|
(void *) body->evas_obj);
|
2012-07-27 07:49:53 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
ephysics_body_filter_collision(EPhysics_Body *body0, EPhysics_Body *body1)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
2012-09-04 15:42:28 -07:00
|
|
|
void *grp;
|
2012-07-27 07:49:53 -07:00
|
|
|
|
|
|
|
if ((!body0->collision_groups) || (!body1->collision_groups))
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body0->collision_groups, l, grp)
|
|
|
|
{
|
|
|
|
if (eina_list_data_find(body1->collision_groups, grp))
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
ephysics_body_collision_group_add(EPhysics_Body *body, const char *group)
|
|
|
|
{
|
|
|
|
Eina_Stringshare *group_str;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't add body collision group, body is null.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-07-27 07:49:53 -07:00
|
|
|
group_str = eina_stringshare_add(group);
|
2012-07-27 07:50:25 -07:00
|
|
|
if (eina_list_data_find(body->collision_groups, group_str))
|
2012-07-27 07:49:53 -07:00
|
|
|
{
|
2012-07-27 07:50:25 -07:00
|
|
|
INF("Body already added to group: %s", group);
|
|
|
|
eina_stringshare_del(group_str);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-07-27 07:50:25 -07:00
|
|
|
return EINA_TRUE;
|
2012-07-27 07:49:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
body->collision_groups = eina_list_append(body->collision_groups, group_str);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-07-27 07:49:53 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
ephysics_body_collision_group_del(EPhysics_Body *body, const char *group)
|
|
|
|
{
|
|
|
|
Eina_Stringshare *group_str;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't remove body collision group, body is null.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-07-27 07:49:53 -07:00
|
|
|
group_str = eina_stringshare_add(group);
|
2012-07-27 07:50:25 -07:00
|
|
|
if (!eina_list_data_find(body->collision_groups, group_str))
|
|
|
|
{
|
|
|
|
INF("Body isn't part of group: %s", group);
|
|
|
|
eina_stringshare_del(group_str);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-07-27 07:50:25 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-07-27 07:49:53 -07:00
|
|
|
body->collision_groups = eina_list_remove(body->collision_groups, group_str);
|
|
|
|
eina_stringshare_del(group_str);
|
|
|
|
eina_stringshare_del(group_str);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-07-27 07:49:53 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI const Eina_List *
|
|
|
|
ephysics_body_collision_group_list_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get the body's collision group, body is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->collision_groups;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static EPhysics_Body *
|
2012-10-10 12:17:54 -07:00
|
|
|
_ephysics_body_new(EPhysics_World *world, btScalar mass, double cm_x, double cm_y, double cm_z)
|
2012-10-04 15:40:16 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body *body;
|
2012-11-09 10:52:28 -08:00
|
|
|
double rate;
|
2012-10-04 15:40:16 -07:00
|
|
|
|
|
|
|
body = (EPhysics_Body *) calloc(1, sizeof(EPhysics_Body));
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a new body instance.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:28 -08:00
|
|
|
rate = ephysics_world_rate_get(world);
|
2012-10-25 14:54:06 -07:00
|
|
|
body->scale = btVector3(1, 1, 1);
|
2012-11-09 10:52:28 -08:00
|
|
|
body->size.w = rate;
|
|
|
|
body->size.h = rate;
|
|
|
|
body->size.d = rate;
|
2012-10-04 15:40:16 -07:00
|
|
|
body->mass = mass;
|
|
|
|
body->world = world;
|
|
|
|
body->cm.x = cm_x;
|
|
|
|
body->cm.y = cm_y;
|
2012-10-10 12:17:54 -07:00
|
|
|
body->cm.z = cm_z;
|
2012-10-04 15:40:16 -07:00
|
|
|
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
static EPhysics_Body *
|
2012-10-10 12:17:54 -07:00
|
|
|
_ephysics_body_rigid_body_add(EPhysics_World *world, btCollisionShape *collision_shape, const char *type, double cm_x, double cm_y, double cm_z)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
btRigidBody::btRigidBodyConstructionInfo *rigid_body_ci;
|
|
|
|
btDefaultMotionState *motion_state;
|
|
|
|
btRigidBody *rigid_body;
|
2012-06-26 15:36:12 -07:00
|
|
|
EPhysics_Body *body;
|
|
|
|
btScalar mass = 1;
|
2012-08-10 14:05:05 -07:00
|
|
|
btVector3 inertia;
|
|
|
|
|
|
|
|
if (!collision_shape)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a %s shape.", type);
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-10 12:17:54 -07:00
|
|
|
body = _ephysics_body_new(world, mass, cm_x, cm_y, cm_z);
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a new body instance.");
|
2012-08-10 14:05:05 -07:00
|
|
|
goto err_body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
motion_state = new btDefaultMotionState();
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!motion_state)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a motion state.");
|
2012-08-10 14:05:05 -07:00
|
|
|
goto err_motion_state;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
inertia = btVector3(0, 0, 0);
|
2012-06-26 15:36:12 -07:00
|
|
|
collision_shape->calculateLocalInertia(mass, inertia);
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
rigid_body_ci = new btRigidBody::btRigidBodyConstructionInfo(
|
2012-06-26 15:36:12 -07:00
|
|
|
mass, motion_state, collision_shape, inertia);
|
2012-08-10 14:05:05 -07:00
|
|
|
if (!rigid_body_ci)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a rigid body construction info.");
|
|
|
|
goto err_rigid_body_ci;
|
|
|
|
}
|
|
|
|
|
|
|
|
rigid_body = new btRigidBody(*rigid_body_ci);
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!rigid_body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a rigid body.");
|
2012-08-10 14:05:05 -07:00
|
|
|
goto err_rigid_body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
body->type = EPHYSICS_BODY_TYPE_RIGID;
|
2012-06-26 15:36:12 -07:00
|
|
|
body->collision_shape = collision_shape;
|
|
|
|
body->rigid_body = rigid_body;
|
|
|
|
body->rigid_body->setUserPointer(body);
|
|
|
|
body->rigid_body->setLinearFactor(btVector3(1, 1, 0));
|
|
|
|
body->rigid_body->setAngularFactor(btVector3(0, 0, 1));
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
if (!ephysics_world_body_add(body->world, body))
|
|
|
|
{
|
|
|
|
ERR("Couldn't add body to world's bodies list");
|
|
|
|
goto err_world_add;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete rigid_body_ci;
|
|
|
|
|
|
|
|
INF("Body %p of type %s added.", body, type);
|
2012-06-26 15:36:12 -07:00
|
|
|
return body;
|
2012-08-10 14:05:05 -07:00
|
|
|
|
|
|
|
err_world_add:
|
|
|
|
delete rigid_body;
|
|
|
|
err_rigid_body:
|
|
|
|
delete rigid_body_ci;
|
|
|
|
err_rigid_body_ci:
|
|
|
|
delete motion_state;
|
|
|
|
err_motion_state:
|
|
|
|
free(body);
|
|
|
|
err_body:
|
|
|
|
delete collision_shape;
|
|
|
|
return NULL;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_evas_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body = (EPhysics_Body *) data;
|
2012-11-23 13:49:57 -08:00
|
|
|
|
|
|
|
if (body->default_face)
|
|
|
|
_ephysics_body_soft_body_slices_clean(body->default_face->slices);
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
body->evas_obj = NULL;
|
|
|
|
DBG("Evas object deleted. Updating body: %p", body);
|
|
|
|
}
|
|
|
|
|
2012-09-12 14:49:14 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_anchors_rebuild(int node, btRigidBody *rigid_body, btSoftBody *soft_body)
|
|
|
|
{
|
|
|
|
btTransform world_trans = rigid_body->getWorldTransform();
|
|
|
|
btVector3 local = world_trans.inverse() * soft_body->m_nodes[node].m_x;
|
|
|
|
|
|
|
|
for (int i = 0; i < soft_body->m_anchors.size(); i++)
|
|
|
|
{
|
|
|
|
if (soft_body->m_anchors[i].m_node == &soft_body->m_nodes[node])
|
|
|
|
soft_body->m_anchors[i].m_local = local;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:43:32 -08:00
|
|
|
void
|
|
|
|
ephysics_body_soft_body_bending_constraints_generate(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
btSoftBody *soft_body = body->soft_body;
|
|
|
|
|
|
|
|
for (; body->bending_constraints; body->bending_constraints--)
|
|
|
|
soft_body->generateBendingConstraints(2, soft_body->m_materials
|
|
|
|
[body->material_index]);
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_cloth_constraints_rebuild(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
btRigidBody *rigid_body;
|
|
|
|
btSoftBody *soft_body;
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
btSoftBody::Anchor anchor;
|
|
|
|
int anchors_size = body->soft_body->m_anchors.size();
|
|
|
|
|
|
|
|
soft_body = body->soft_body;
|
|
|
|
|
|
|
|
if (anchors_size)
|
|
|
|
{
|
|
|
|
rigid_body = soft_body->m_anchors[0].m_body;
|
|
|
|
for (int m = 0; m < anchors_size; m++)
|
|
|
|
{
|
|
|
|
anchor = soft_body->m_anchors[m];
|
|
|
|
node = anchor.m_node;
|
|
|
|
for (int n = 0; n < soft_body->m_nodes.size(); n++)
|
|
|
|
{
|
|
|
|
if (node == &soft_body->m_nodes[n])
|
|
|
|
_ephysics_body_soft_body_anchors_rebuild(n, rigid_body,
|
|
|
|
soft_body);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
soft_body->generateClusters(0);
|
2012-11-23 13:43:32 -08:00
|
|
|
ephysics_body_soft_body_bending_constraints_generate(body);
|
2012-10-04 15:40:16 -07:00
|
|
|
}
|
|
|
|
|
2012-09-12 14:49:14 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_constraints_rebuild(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
btSoftBody *soft_body = body->soft_body;
|
|
|
|
btRigidBody *rigid_body = body->rigid_body;
|
|
|
|
|
|
|
|
if (soft_body->m_anchors.size() > 0)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < soft_body->m_nodes.size(); i++)
|
|
|
|
_ephysics_body_soft_body_anchors_rebuild(i, rigid_body, soft_body);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = 0; i < soft_body->m_nodes.size(); i++)
|
|
|
|
soft_body->appendAnchor(i, rigid_body);
|
|
|
|
}
|
|
|
|
|
|
|
|
soft_body->generateClusters(0);
|
2012-11-23 13:43:32 -08:00
|
|
|
ephysics_body_soft_body_bending_constraints_generate(body);
|
2012-09-12 14:49:14 -07:00
|
|
|
}
|
|
|
|
|
2012-10-04 15:39:29 -07:00
|
|
|
inline static double
|
|
|
|
_ephysics_body_volume_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
btVector3 vector = body->collision_shape->getLocalScaling();
|
|
|
|
return vector.x() * vector.y() * vector.z();
|
|
|
|
}
|
|
|
|
|
2012-10-16 16:18:21 -07:00
|
|
|
void
|
|
|
|
_ephysics_body_soft_body_dragging_set(EPhysics_Body *body, int triangle)
|
|
|
|
{
|
|
|
|
btSoftBody::Face face;
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
|
|
|
|
body->dragging_data.triangle = triangle;
|
|
|
|
body->dragging_data.dragging = EINA_TRUE;
|
|
|
|
|
|
|
|
face = body->soft_body->m_faces[triangle];
|
2012-11-23 13:43:19 -08:00
|
|
|
node = face.m_n[0];
|
|
|
|
body->dragging_data.mass = node->m_im;
|
2012-10-16 16:18:21 -07:00
|
|
|
}
|
|
|
|
|
2012-10-25 14:54:55 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_mass_set(EPhysics_Body *body, double mass)
|
|
|
|
{
|
|
|
|
int valid_nodes;
|
|
|
|
btSoftBody::Node node;
|
|
|
|
double inverse_mass;
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_SOFT)
|
|
|
|
body->soft_body->setTotalMass(mass);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
valid_nodes = 0;
|
|
|
|
for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
|
|
|
|
{
|
|
|
|
node = body->soft_body->m_nodes[i];
|
|
|
|
if (node.m_im && !node.m_battach)
|
|
|
|
valid_nodes++;
|
|
|
|
}
|
|
|
|
|
|
|
|
inverse_mass = 1 / (mass / valid_nodes);
|
|
|
|
if (body->dragging_data.dragging)
|
|
|
|
{
|
|
|
|
valid_nodes++;
|
|
|
|
inverse_mass = 1 / (mass / valid_nodes);
|
2012-11-23 13:43:19 -08:00
|
|
|
body->dragging_data.mass = inverse_mass;
|
2012-10-25 14:54:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
|
|
|
|
{
|
|
|
|
node = body->soft_body->m_nodes[i];
|
|
|
|
if (node.m_im && !node.m_battach)
|
|
|
|
node.m_im = inverse_mass;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_mass_set(EPhysics_Body *body, double mass)
|
|
|
|
{
|
|
|
|
btVector3 inertia(0, 0, 0);
|
|
|
|
|
2012-10-04 15:39:29 -07:00
|
|
|
if (body->density)
|
|
|
|
mass = body->density * _ephysics_body_volume_get(body);
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
if (body->soft_body)
|
2012-10-25 14:54:55 -07:00
|
|
|
_ephysics_body_soft_body_mass_set(body, mass);
|
2012-10-04 15:38:06 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:10:52 -07:00
|
|
|
static void
|
2012-10-10 12:17:01 -07:00
|
|
|
_ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h, Evas_Coord d)
|
2012-08-20 15:10:52 -07:00
|
|
|
{
|
2012-10-10 12:17:01 -07:00
|
|
|
double rate, sx, sy, sz;
|
2012-11-23 13:52:02 -08:00
|
|
|
btVector3 body_scale, center;
|
|
|
|
btTransform trans;
|
2012-08-20 15:10:52 -07:00
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
sx = w / rate;
|
|
|
|
sy = h / rate;
|
2012-10-10 12:17:01 -07:00
|
|
|
sz = d / rate;
|
2012-08-20 15:10:52 -07:00
|
|
|
|
2012-11-09 10:58:43 -08:00
|
|
|
body_scale = btVector3(sx, sy, sz);
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_SOFT)
|
2012-08-22 13:04:39 -07:00
|
|
|
{
|
2012-12-10 09:15:05 -08:00
|
|
|
trans = _ephysics_body_transform_get(body);
|
|
|
|
|
2012-11-09 10:58:43 -08:00
|
|
|
body->soft_body->scale(btVector3(1, 1, 1) / body->scale);
|
|
|
|
body->soft_body->scale(body_scale);
|
2012-11-23 13:52:02 -08:00
|
|
|
|
2012-12-10 09:15:05 -08:00
|
|
|
_ephysics_body_transform_set(body, trans);
|
2012-11-23 13:52:02 -08:00
|
|
|
body->rigid_body->proceedToTransform(trans);
|
|
|
|
|
2012-09-12 14:49:14 -07:00
|
|
|
_ephysics_body_soft_body_constraints_rebuild(body);
|
2012-08-22 13:04:39 -07:00
|
|
|
}
|
2012-11-09 10:58:43 -08:00
|
|
|
else if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
{
|
|
|
|
body->soft_body->scale(btVector3(1, 1, 1) / body->scale);
|
|
|
|
body->soft_body->scale(body_scale);
|
|
|
|
_ephysics_body_cloth_constraints_rebuild(body);
|
|
|
|
}
|
2012-08-22 13:04:39 -07:00
|
|
|
else
|
|
|
|
{
|
2012-11-09 10:58:43 -08:00
|
|
|
body->collision_shape->setLocalScaling(body_scale);
|
2012-08-20 15:10:52 -07:00
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
if(!body->rigid_body->isStaticObject())
|
2012-10-04 15:38:06 -07:00
|
|
|
_ephysics_body_mass_set(body, ephysics_body_mass_get(body));
|
2012-08-22 13:04:39 -07:00
|
|
|
}
|
2012-08-20 15:10:52 -07:00
|
|
|
|
2012-11-09 10:52:22 -08:00
|
|
|
body->size.w = w;
|
|
|
|
body->size.h = h;
|
|
|
|
body->size.d = d;
|
2012-11-09 10:58:43 -08:00
|
|
|
body->scale = body_scale;
|
2012-08-20 15:10:52 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
2012-08-20 15:10:52 -07:00
|
|
|
|
2012-10-10 12:17:01 -07:00
|
|
|
DBG("Body %p scale changed to (%lf, %lf, %lf).", body, sx, sy, sz);
|
2012-08-20 15:10:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-10-10 12:17:01 -07:00
|
|
|
_ephysics_body_move(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord z)
|
2012-08-20 15:10:52 -07:00
|
|
|
{
|
2012-10-10 12:17:01 -07:00
|
|
|
double rate, mx, my, mz;
|
2012-08-20 15:10:52 -07:00
|
|
|
btTransform trans;
|
|
|
|
int wy, height;
|
2012-08-22 13:04:39 -07:00
|
|
|
btVector3 body_scale;
|
2012-08-20 15:10:52 -07:00
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL,
|
|
|
|
NULL, &height, NULL);
|
2012-08-20 15:10:52 -07:00
|
|
|
height += wy;
|
|
|
|
|
2012-11-09 10:52:22 -08:00
|
|
|
mx = (x + body->size.w * body->cm.x) / rate;
|
|
|
|
my = (height - (y + body->size.h * body->cm.y)) / rate;
|
|
|
|
mz = (z + body->size.d * body->cm.z) / rate;
|
2012-08-20 15:10:52 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
trans = _ephysics_body_transform_get(body);
|
2012-10-10 12:17:01 -07:00
|
|
|
trans.setOrigin(btVector3(mx, my, mz));
|
2012-10-25 14:53:59 -07:00
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
_ephysics_body_transform_set(body, trans);
|
2012-12-10 09:15:05 -08:00
|
|
|
else if (body->type == EPHYSICS_BODY_TYPE_SOFT)
|
|
|
|
{
|
|
|
|
_ephysics_body_transform_set(body, trans);
|
|
|
|
body->rigid_body->proceedToTransform(trans);
|
|
|
|
body->rigid_body->getMotionState()->setWorldTransform(trans);
|
|
|
|
}
|
2012-10-25 14:53:59 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
body->rigid_body->proceedToTransform(trans);
|
|
|
|
body->rigid_body->getMotionState()->setWorldTransform(trans);
|
|
|
|
}
|
2012-08-20 15:10:52 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
2012-08-20 15:10:52 -07:00
|
|
|
|
2012-10-10 12:17:01 -07:00
|
|
|
DBG("Body %p position changed to (%lf, %lf, %lf).", body, mx, my, mz);
|
2012-08-20 15:10:52 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
static void
|
2012-10-10 12:17:01 -07:00
|
|
|
_ephysics_body_geometry_set(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord z, Evas_Coord w, Evas_Coord h, Evas_Coord d, double rate)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-10-10 12:17:01 -07:00
|
|
|
double mx, my, mz, sx, sy, sz;
|
2012-06-26 15:36:12 -07:00
|
|
|
btTransform trans;
|
|
|
|
int wy, height;
|
2012-08-22 13:04:39 -07:00
|
|
|
btVector3 body_scale;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL,
|
|
|
|
NULL, &height, NULL);
|
2012-06-26 15:36:12 -07:00
|
|
|
height += wy;
|
|
|
|
|
2012-08-22 13:05:25 -07:00
|
|
|
mx = (x + w * body->cm.x) / rate;
|
|
|
|
my = (height - (y + h * body->cm.y)) / rate;
|
2012-10-10 12:18:02 -07:00
|
|
|
mz = (z + d * body->cm.z) / rate;
|
2012-11-28 13:47:30 -08:00
|
|
|
sx = (w <= 0) ? 1 : w / rate;
|
|
|
|
sy = (h <= 0) ? 1 : h / rate;
|
|
|
|
sz = (d <= 0) ? 1 : d / rate;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
trans = _ephysics_body_transform_get(body);
|
2012-10-10 12:17:01 -07:00
|
|
|
trans.setOrigin(btVector3(mx, my, mz));
|
|
|
|
body_scale = btVector3(sx, sy, sz);
|
2012-10-04 15:40:16 -07:00
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_SOFT)
|
2012-08-22 13:04:39 -07:00
|
|
|
{
|
2012-11-09 10:58:43 -08:00
|
|
|
body->soft_body->scale(btVector3(1, 1, 1) / body->scale);
|
2012-10-04 15:40:16 -07:00
|
|
|
body->soft_body->scale(body_scale);
|
2012-08-22 13:04:39 -07:00
|
|
|
body->rigid_body->proceedToTransform(trans);
|
2012-11-09 10:58:43 -08:00
|
|
|
_ephysics_body_transform_set(body, trans);
|
2012-09-12 14:49:14 -07:00
|
|
|
_ephysics_body_soft_body_constraints_rebuild(body);
|
2012-08-22 13:04:39 -07:00
|
|
|
}
|
2012-10-04 15:40:16 -07:00
|
|
|
else if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
{
|
2012-11-09 10:58:43 -08:00
|
|
|
body->soft_body->scale(btVector3(1, 1, 1) / body->scale);
|
2012-10-04 15:40:16 -07:00
|
|
|
body->soft_body->scale(body_scale);
|
|
|
|
_ephysics_body_transform_set(body, trans);
|
|
|
|
_ephysics_body_cloth_constraints_rebuild(body);
|
|
|
|
}
|
2012-08-22 13:04:39 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
body->collision_shape->setLocalScaling(body_scale);
|
|
|
|
body->rigid_body->proceedToTransform(trans);
|
|
|
|
|
|
|
|
if (!body->rigid_body->isStaticObject())
|
2012-10-04 15:38:06 -07:00
|
|
|
_ephysics_body_mass_set(body, ephysics_body_mass_get(body));
|
2012-08-22 13:04:39 -07:00
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
_ephysics_body_transform_set(body, trans);
|
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-11-09 10:52:22 -08:00
|
|
|
body->size.w = w;
|
|
|
|
body->size.h = h;
|
|
|
|
body->size.d = d;
|
2012-10-25 14:54:06 -07:00
|
|
|
body->scale = body_scale;
|
2012-08-13 15:24:47 -07:00
|
|
|
|
2012-10-10 12:17:01 -07:00
|
|
|
DBG("Body %p position changed to (%lf, %lf, %lf).", body, mx, my, mz);
|
|
|
|
DBG("Body %p scale changed to (%lf, %lf, %lf).", body, sx, sy, sz);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-13 15:24:47 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_evas_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body = (EPhysics_Body *) data;
|
2012-08-20 15:10:52 -07:00
|
|
|
int w, h;
|
2012-08-13 15:24:47 -07:00
|
|
|
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
|
2012-11-09 10:52:22 -08:00
|
|
|
if ((w == body->size.w) && (h == body->size.h))
|
2012-08-13 15:24:47 -07:00
|
|
|
return;
|
|
|
|
|
2012-11-09 10:52:22 -08:00
|
|
|
DBG("Resizing body %p to w=%i, h=%i, d=%i", body, w, h, body->size.d);
|
2012-12-10 09:15:05 -08:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-11-09 10:52:22 -08:00
|
|
|
_ephysics_body_resize(body, w, h, body->size.d);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-08-13 15:24:47 -07:00
|
|
|
}
|
|
|
|
|
2012-11-23 13:49:44 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_evas_restack_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body = (EPhysics_Body *)data;
|
2012-11-23 13:49:57 -08:00
|
|
|
Eina_List *slices;
|
2012-11-23 13:49:44 -08:00
|
|
|
void *ldata;
|
|
|
|
EPhysics_Body_Soft_Body_Slice *slice;
|
|
|
|
short layer = evas_object_layer_get(obj);
|
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
slices = _ephysics_body_soft_body_slices_get(body);
|
|
|
|
EINA_LIST_FREE(slices, ldata)
|
2012-11-23 13:49:44 -08:00
|
|
|
{
|
|
|
|
slice = (EPhysics_Body_Soft_Body_Slice *)ldata;
|
|
|
|
evas_object_layer_set(slice->evas_obj, layer);
|
|
|
|
}
|
|
|
|
DBG("Body's slices layer reset to: %d", layer);
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_face_slice_del(EPhysics_Body_Face_Slice *face_slice)
|
|
|
|
{
|
2012-11-23 13:51:03 -08:00
|
|
|
_ephysics_body_soft_body_slices_free(face_slice->slices);
|
2012-11-23 13:49:57 -08:00
|
|
|
free(face_slice->points_deform);
|
|
|
|
free(face_slice);
|
|
|
|
}
|
|
|
|
|
|
|
|
static EPhysics_Body_Face_Slice *
|
|
|
|
_ephysics_body_face_slice_add(EPhysics_Body *body, EPhysics_Body_Face face)
|
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Slice *face_slice;
|
|
|
|
|
|
|
|
face_slice = (EPhysics_Body_Face_Slice *)calloc(1,
|
|
|
|
sizeof(EPhysics_Body_Face_Slice));
|
|
|
|
if (!face_slice)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
face_slice->face = face;
|
|
|
|
body->faces_slices = eina_list_append(body->faces_slices, face_slice);
|
2012-11-23 13:51:38 -08:00
|
|
|
face_slice->body = body;
|
2012-11-23 13:49:57 -08:00
|
|
|
return face_slice;
|
|
|
|
DBG("New face slice added to body %p", body);
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
static EPhysics_Body_Face_Slice *
|
|
|
|
_ephysics_body_face_slice_get(EPhysics_Body *body, EPhysics_Body_Face face)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
EPhysics_Body_Face_Slice *face_slice = NULL;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->faces_slices, l, ldata)
|
|
|
|
{
|
|
|
|
if (((EPhysics_Body_Face_Slice *)ldata)->face == face)
|
|
|
|
{
|
|
|
|
face_slice = (EPhysics_Body_Face_Slice *)ldata;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return face_slice;
|
|
|
|
}
|
|
|
|
|
|
|
|
static EPhysics_Body_Face_Obj *
|
|
|
|
_ephysics_body_face_evas_object_get(EPhysics_Body *body, EPhysics_Body_Face face)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->face == face)
|
|
|
|
return face_obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Could not find requested face");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-13 15:24:47 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_del(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
EPhysics_Body_Callback *cb;
|
2012-11-23 13:51:38 -08:00
|
|
|
void *ldata;
|
2012-08-13 15:24:47 -07:00
|
|
|
void *group;
|
2012-11-23 13:51:38 -08:00
|
|
|
EPhysics_Body_Face_Slice *face_slice;
|
2012-08-13 15:24:47 -07:00
|
|
|
|
|
|
|
if (body->evas_obj)
|
|
|
|
{
|
|
|
|
evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_evas_obj_del_cb);
|
|
|
|
evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb);
|
2012-11-23 13:49:44 -08:00
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
if (body->faces_slices)
|
2012-11-23 13:49:44 -08:00
|
|
|
evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_RESTACK,
|
|
|
|
_ephysics_body_soft_body_evas_restack_cb);
|
2012-08-13 15:24:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
while (body->callbacks)
|
|
|
|
{
|
|
|
|
cb = EINA_INLIST_CONTAINER_GET(body->callbacks,
|
|
|
|
EPhysics_Body_Callback);
|
|
|
|
body->callbacks = eina_inlist_remove(body->callbacks, body->callbacks);
|
|
|
|
free(cb);
|
|
|
|
}
|
|
|
|
|
2012-11-29 10:54:36 -08:00
|
|
|
ephysics_constraint_body_del(body);
|
|
|
|
|
2012-08-13 15:24:47 -07:00
|
|
|
EINA_LIST_FREE(body->collision_groups, group)
|
|
|
|
eina_stringshare_del((Eina_Stringshare *)group);
|
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
EINA_LIST_FREE(body->faces_slices, ldata)
|
|
|
|
{
|
|
|
|
face_slice = (EPhysics_Body_Face_Slice *)ldata;
|
|
|
|
if (_ephysics_body_face_evas_object_get(body, face_slice->face))
|
|
|
|
ephysics_body_face_evas_object_unset(body, face_slice->face);
|
|
|
|
_ephysics_body_face_slice_del(face_slice);
|
|
|
|
}
|
2012-10-04 15:40:07 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
if (body->rigid_body)
|
|
|
|
{
|
|
|
|
delete body->rigid_body->getMotionState();
|
|
|
|
delete body->collision_shape;
|
|
|
|
delete body->rigid_body;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
delete body->soft_body;
|
2012-08-13 15:24:47 -07:00
|
|
|
|
|
|
|
free(body);
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:53:11 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_evas_obj_map_apply(EPhysics_Body *body, Evas_Map *map, Evas_Object *obj, Eina_Bool bfc, Eina_Bool update_cw)
|
|
|
|
{
|
|
|
|
EPhysics_Camera *camera = ephysics_world_camera_get(body->world);
|
|
|
|
|
|
|
|
if (ephysics_camera_perspective_enabled_get(camera))
|
|
|
|
{
|
|
|
|
int px, py, z0, foc;
|
|
|
|
ephysics_camera_perspective_get(camera, &px, &py, &z0, &foc);
|
|
|
|
evas_map_util_3d_perspective(map, px, py, z0, foc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bfc)
|
|
|
|
{
|
|
|
|
if (evas_map_util_clockwise_get(map))
|
|
|
|
{
|
|
|
|
if (update_cw)
|
|
|
|
body->clockwise = EINA_TRUE;
|
|
|
|
evas_object_show(obj);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (update_cw)
|
|
|
|
body->clockwise = EINA_FALSE;
|
|
|
|
evas_map_free(map);
|
|
|
|
evas_object_hide(obj);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((body->light_apply) ||
|
|
|
|
(ephysics_world_light_all_bodies_get(body->world)))
|
|
|
|
{
|
|
|
|
int lr, lg, lb, ar, ag, ab;
|
|
|
|
Evas_Coord lx, ly, lz;
|
|
|
|
|
|
|
|
ephysics_world_point_light_position_get(body->world, &lx, &ly, &lz);
|
|
|
|
ephysics_world_point_light_color_get(body->world, &lr, &lg, &lb);
|
|
|
|
ephysics_world_ambient_light_color_get(body->world, &ar, &ag, &ab);
|
|
|
|
evas_map_util_3d_lighting(map, lx, ly, lz, lr, lg, lb, ar, ag, ab);
|
|
|
|
}
|
|
|
|
|
|
|
|
evas_object_map_set(obj, map);
|
|
|
|
evas_object_map_enable_set(obj, EINA_TRUE);
|
|
|
|
evas_map_free(map);
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:42 -08:00
|
|
|
static void
|
|
|
|
_ephysics_cloth_face_objs_update(EPhysics_Body *body __UNUSED__)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-11-09 10:57:51 -08:00
|
|
|
_ephysics_cylinder_face_objs_update(EPhysics_Body *body)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
2012-11-09 10:57:51 -08:00
|
|
|
int bx, by, x, y, z, wx, wy, wh, cx, cy;
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
EPhysics_Camera *camera;
|
|
|
|
btQuaternion quat;
|
|
|
|
btTransform trans;
|
|
|
|
Evas_Map *map;
|
|
|
|
Eina_List *l;
|
|
|
|
double rate;
|
|
|
|
void *ldata;
|
|
|
|
|
|
|
|
ephysics_world_render_geometry_get(body->world, &wx, &wy, NULL,
|
|
|
|
NULL, &wh, NULL);
|
|
|
|
camera = ephysics_world_camera_get(body->world);
|
|
|
|
ephysics_camera_position_get(camera, &cx, &cy);
|
|
|
|
cx -= wx;
|
|
|
|
cy -= wy;
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
trans = _ephysics_body_transform_get(body);
|
|
|
|
|
|
|
|
bx = (int) (trans.getOrigin().getX() * rate) - cx;
|
|
|
|
by = wh + wy - (int) (trans.getOrigin().getY() * rate) - cy;
|
|
|
|
x = bx - body->size.w / 2;
|
|
|
|
y = by - body->size.h / 2;
|
|
|
|
z = (int) (trans.getOrigin().getZ() * rate);
|
|
|
|
|
|
|
|
quat = trans.getRotation();
|
|
|
|
quat.normalize();
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
Evas_Object *obj;
|
|
|
|
Evas_Coord w, h;
|
2012-11-09 10:52:42 -08:00
|
|
|
|
2012-11-09 10:57:51 -08:00
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
obj = face_obj->obj;
|
|
|
|
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
|
|
|
|
evas_object_move(obj, x, y);
|
|
|
|
if ((!w) || (!h))
|
|
|
|
{
|
|
|
|
DBG("Evas object with no geometry: %p, w=%i h=%i", obj, w, h);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
map = evas_map_new(4);
|
|
|
|
|
|
|
|
switch(face_obj->face)
|
|
|
|
{
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT:
|
|
|
|
evas_map_util_points_populate_from_object_full(map, obj, z);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_BACK:
|
|
|
|
evas_map_util_points_populate_from_object_full(map, obj, z + 1);
|
|
|
|
evas_map_util_3d_rotate(map, 0, 180, 0, bx, by, z + 1);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_FRONT:
|
|
|
|
evas_map_util_points_populate_from_object_full(
|
|
|
|
map, obj, z - body->size.d / 2);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_BACK:
|
|
|
|
evas_map_util_points_populate_from_object_full(
|
|
|
|
map, obj, z + body->size.d / 2);
|
|
|
|
evas_map_util_3d_rotate(map, 0, 180, 0, bx, by,
|
|
|
|
z + body->size.d / 2);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRN("Face %i not updated", face_obj->face);
|
|
|
|
evas_map_free(map);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
evas_map_util_quat_rotate(map, quat.x(), -quat.y(), quat.z(), -quat.w(),
|
|
|
|
bx, by, z);
|
|
|
|
|
|
|
|
_ephysics_body_evas_obj_map_apply(body, map, obj, EINA_TRUE,
|
|
|
|
EINA_FALSE);
|
|
|
|
}
|
2012-11-09 10:52:42 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_box_face_objs_update(EPhysics_Body *body)
|
|
|
|
{
|
2012-11-09 10:53:11 -08:00
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
int i, x, y, z, wx, wy, wh, cx, cy;
|
|
|
|
EPhysics_Camera *camera;
|
|
|
|
Evas_Coord v[8][3];
|
|
|
|
btQuaternion quat;
|
|
|
|
btTransform trans;
|
|
|
|
btBoxShape *shape;
|
|
|
|
Evas_Map *map;
|
|
|
|
Eina_List *l;
|
|
|
|
double rate;
|
|
|
|
void *ldata;
|
|
|
|
|
|
|
|
ephysics_world_render_geometry_get(body->world, &wx, &wy, NULL,
|
|
|
|
NULL, &wh, NULL);
|
|
|
|
camera = ephysics_world_camera_get(body->world);
|
|
|
|
ephysics_camera_position_get(camera, &cx, &cy);
|
|
|
|
cx -= wx;
|
|
|
|
cy -= wy;
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
trans = _ephysics_body_transform_get(body);
|
|
|
|
|
|
|
|
x = (int) (trans.getOrigin().getX() * rate) - cx;
|
|
|
|
y = wh + wy - (int) (trans.getOrigin().getY() * rate) - cy;
|
|
|
|
z = (int) (trans.getOrigin().getZ() * rate);
|
|
|
|
|
|
|
|
shape = (btBoxShape *) body->collision_shape;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
btVector3 vertice;
|
|
|
|
shape->getVertex(i, vertice);
|
|
|
|
v[i][0] = vertice.getX() * rate + x;
|
|
|
|
v[i][1] = - vertice.getY() * rate + y;
|
|
|
|
v[i][2] = vertice.getZ() * rate + z;
|
|
|
|
}
|
|
|
|
|
|
|
|
quat = trans.getRotation();
|
|
|
|
quat.normalize();
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
Evas_Object *obj;
|
|
|
|
Evas_Coord w, h;
|
|
|
|
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
obj = face_obj->obj;
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
|
|
|
|
|
|
|
|
map = evas_map_new(4);
|
|
|
|
evas_map_point_image_uv_set(map, 0, 0, 0);
|
|
|
|
evas_map_point_image_uv_set(map, 1, w, 0);
|
|
|
|
evas_map_point_image_uv_set(map, 2, w, h);
|
|
|
|
evas_map_point_image_uv_set(map, 3, 0, h);
|
|
|
|
|
|
|
|
switch(face_obj->face)
|
|
|
|
{
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT:
|
|
|
|
evas_map_point_coord_set(map, 0, v[5][0], v[5][1], z);
|
|
|
|
evas_map_point_coord_set(map, 1, v[4][0], v[4][1], z);
|
|
|
|
evas_map_point_coord_set(map, 2, v[6][0], v[6][1], z);
|
|
|
|
evas_map_point_coord_set(map, 3, v[7][0], v[7][1], z);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_MIDDLE_BACK:
|
|
|
|
evas_map_point_coord_set(map, 0, v[0][0], v[0][1], z);
|
|
|
|
evas_map_point_coord_set(map, 1, v[1][0], v[1][1], z);
|
|
|
|
evas_map_point_coord_set(map, 2, v[3][0], v[3][1], z);
|
|
|
|
evas_map_point_coord_set(map, 3, v[2][0], v[2][1], z);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_FRONT:
|
|
|
|
evas_map_point_coord_set(map, 0, v[5][0], v[5][1], v[5][2]);
|
|
|
|
evas_map_point_coord_set(map, 1, v[4][0], v[4][1], v[4][2]);
|
|
|
|
evas_map_point_coord_set(map, 2, v[6][0], v[6][1], v[6][2]);
|
|
|
|
evas_map_point_coord_set(map, 3, v[7][0], v[7][1], v[7][2]);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_BACK:
|
|
|
|
evas_map_point_coord_set(map, 0, v[0][0], v[0][1], v[0][2]);
|
|
|
|
evas_map_point_coord_set(map, 1, v[1][0], v[1][1], v[1][2]);
|
|
|
|
evas_map_point_coord_set(map, 2, v[3][0], v[3][1], v[3][2]);
|
|
|
|
evas_map_point_coord_set(map, 3, v[2][0], v[2][1], v[2][2]);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_RIGHT:
|
|
|
|
evas_map_point_coord_set(map, 0, v[4][0], v[4][1], v[4][2]);
|
|
|
|
evas_map_point_coord_set(map, 1, v[0][0], v[0][1], v[0][2]);
|
|
|
|
evas_map_point_coord_set(map, 2, v[2][0], v[2][1], v[2][2]);
|
|
|
|
evas_map_point_coord_set(map, 3, v[6][0], v[6][1], v[6][2]);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_LEFT:
|
|
|
|
evas_map_point_coord_set(map, 0, v[1][0], v[1][1], v[1][2]);
|
|
|
|
evas_map_point_coord_set(map, 1, v[5][0], v[5][1], v[5][2]);
|
|
|
|
evas_map_point_coord_set(map, 2, v[7][0], v[7][1], v[7][2]);
|
|
|
|
evas_map_point_coord_set(map, 3, v[3][0], v[3][1], v[3][2]);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_TOP:
|
|
|
|
evas_map_point_coord_set(map, 0, v[1][0], v[1][1], v[1][2]);
|
|
|
|
evas_map_point_coord_set(map, 1, v[0][0], v[0][1], v[0][2]);
|
|
|
|
evas_map_point_coord_set(map, 2, v[4][0], v[4][1], v[4][2]);
|
|
|
|
evas_map_point_coord_set(map, 3, v[5][0], v[5][1], v[5][2]);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_BOTTOM:
|
|
|
|
evas_map_point_coord_set(map, 0, v[7][0], v[7][1], v[7][2]);
|
|
|
|
evas_map_point_coord_set(map, 1, v[6][0], v[6][1], v[6][2]);
|
|
|
|
evas_map_point_coord_set(map, 2, v[2][0], v[2][1], v[2][2]);
|
|
|
|
evas_map_point_coord_set(map, 3, v[3][0], v[3][1], v[3][2]);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRN("Face %i not updated", face_obj->face);
|
|
|
|
evas_map_free(map);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
evas_map_util_quat_rotate(map, quat.x(), -quat.y(), quat.z(), -quat.w(),
|
|
|
|
x, y, z);
|
|
|
|
_ephysics_body_evas_obj_map_apply(body, map, obj, EINA_TRUE,
|
|
|
|
EINA_FALSE);
|
|
|
|
}
|
2012-11-09 10:52:42 -08:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
static void
|
2012-11-23 13:51:38 -08:00
|
|
|
_ephysics_body_evas_object_update(EPhysics_Body *body, Evas_Object *evas_obj)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-11-09 10:53:38 -08:00
|
|
|
int bx, by, x, y, z, w, h, wx, wy, wh, cx, cy;
|
2012-07-27 07:50:03 -07:00
|
|
|
EPhysics_Camera *camera;
|
2012-06-26 15:36:12 -07:00
|
|
|
btTransform trans;
|
2012-10-15 14:53:51 -07:00
|
|
|
btQuaternion quat;
|
2012-06-26 15:36:12 -07:00
|
|
|
Evas_Map *map;
|
2012-10-15 14:53:51 -07:00
|
|
|
double rate;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
trans = _ephysics_body_transform_get(body);
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(body->world, &wx, &wy, NULL,
|
|
|
|
NULL, &wh, NULL);
|
2012-07-27 07:50:03 -07:00
|
|
|
camera = ephysics_world_camera_get(body->world);
|
|
|
|
ephysics_camera_position_get(camera, &cx, &cy);
|
|
|
|
cx -= wx;
|
|
|
|
cy -= wy;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
evas_object_geometry_get(evas_obj, NULL, NULL, &w, &h);
|
2012-06-26 15:36:12 -07:00
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-11-09 10:53:38 -08:00
|
|
|
bx = (int) (trans.getOrigin().getX() * rate) - cx;
|
|
|
|
by = wh + wy - (int) (trans.getOrigin().getY() * rate) - cy;
|
|
|
|
x = bx - w * body->cm.x;
|
|
|
|
y = by - h * body->cm.y;
|
2012-10-15 14:53:51 -07:00
|
|
|
z = (int) (trans.getOrigin().getZ() * rate);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
evas_object_move(evas_obj, x, y);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-13 15:24:36 -07:00
|
|
|
if ((!w) || (!h))
|
|
|
|
{
|
2012-11-23 13:51:38 -08:00
|
|
|
DBG("Evas object with no geometry: %p, w=%i h=%i", evas_obj, w, h);
|
2012-08-13 15:24:36 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
if (body->type != EPHYSICS_BODY_TYPE_RIGID)
|
2012-10-31 14:02:55 -07:00
|
|
|
{
|
2012-11-23 13:51:38 -08:00
|
|
|
_ephysics_body_soft_body_slices_apply(body, body->evas_obj,
|
|
|
|
body->default_face->slices);
|
2012-10-31 14:02:55 -07:00
|
|
|
return;
|
|
|
|
}
|
2012-10-04 15:40:07 -07:00
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
map = evas_map_new(4);
|
|
|
|
evas_map_util_points_populate_from_object(map, body->evas_obj);
|
2012-08-22 13:04:39 -07:00
|
|
|
|
2012-10-15 14:53:51 -07:00
|
|
|
quat = trans.getRotation();
|
|
|
|
quat.normalize();
|
2012-11-09 10:53:38 -08:00
|
|
|
evas_map_util_quat_rotate(map, quat.x(), -quat.y(), quat.z(), -quat.w(),
|
|
|
|
bx, by, z);
|
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
_ephysics_body_evas_obj_map_apply(body, map, evas_obj,
|
2012-11-09 10:53:11 -08:00
|
|
|
body->back_face_culling, EINA_TRUE);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_update(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
EPhysics_Body_Face_Slice *face_slice;
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->faces_slices, l, ldata)
|
|
|
|
{
|
|
|
|
face_slice = (EPhysics_Body_Face_Slice *)ldata;
|
|
|
|
face_obj = _ephysics_body_face_evas_object_get(body,
|
|
|
|
face_slice->face);
|
|
|
|
if (!face_obj) continue;
|
|
|
|
_ephysics_body_soft_body_slices_apply(body, face_obj->obj,
|
|
|
|
face_slice->slices);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_evas_object_default_update(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (body->face_objs)
|
|
|
|
{
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
_ephysics_cloth_face_objs_update(body);
|
|
|
|
else if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_CYLINDER)
|
|
|
|
_ephysics_cylinder_face_objs_update(body);
|
|
|
|
else if (body->shape == EPHYSICS_BODY_SHAPE_BOX)
|
|
|
|
_ephysics_box_face_objs_update(body);
|
|
|
|
}
|
|
|
|
else if (body->type == EPHYSICS_BODY_TYPE_SOFT)
|
|
|
|
_ephysics_body_soft_body_update(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!body->evas_obj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_ephysics_body_evas_object_update(body, body->evas_obj);
|
|
|
|
}
|
|
|
|
|
2012-07-03 16:20:49 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_outside_render_area_check(EPhysics_Body *body)
|
|
|
|
{
|
2012-10-15 14:54:35 -07:00
|
|
|
int wx, wy, wz, ww, wh, wd, bx, by, bz, bw, bh, bd;
|
2012-07-03 16:20:49 -07:00
|
|
|
|
2012-10-15 14:54:35 -07:00
|
|
|
ephysics_world_render_geometry_get(body->world, &wx, &wy, &wz,
|
|
|
|
&ww, &wh, &wd);
|
|
|
|
ephysics_body_geometry_get(body, &bx, &by, &bz, &bw, &bh, &bd);
|
2012-07-03 16:20:49 -07:00
|
|
|
|
|
|
|
// FIXME: check what should be done regarding rotated bodies
|
|
|
|
if (((ephysics_world_bodies_outside_top_autodel_get(body->world)) &&
|
|
|
|
(by + bh < wy)) ||
|
|
|
|
((ephysics_world_bodies_outside_bottom_autodel_get(body->world)) &&
|
|
|
|
(by > wy + wh)) ||
|
|
|
|
((ephysics_world_bodies_outside_left_autodel_get(body->world)) &&
|
|
|
|
(bx + bh < wx)) ||
|
|
|
|
((ephysics_world_bodies_outside_right_autodel_get(body->world)) &&
|
2012-10-15 14:54:35 -07:00
|
|
|
(bx > wx + ww)) ||
|
|
|
|
((ephysics_world_bodies_outside_front_autodel_get(body->world)) &&
|
|
|
|
(bz + bd < wz)) ||
|
|
|
|
((ephysics_world_bodies_outside_back_autodel_get(body->world)) &&
|
|
|
|
(bz > wz + wd)))
|
2012-07-03 16:20:49 -07:00
|
|
|
{
|
2012-08-10 14:03:39 -07:00
|
|
|
DBG("Body %p out of render area", body);
|
|
|
|
ephysics_body_del(body);
|
2012-07-03 16:20:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:15:52 -07:00
|
|
|
void
|
|
|
|
ephysics_body_forces_apply(EPhysics_Body *body)
|
|
|
|
{
|
2012-08-21 10:47:18 -07:00
|
|
|
double rate;
|
|
|
|
|
2012-10-10 12:17:49 -07:00
|
|
|
if (!((body->force.x) || (body->force.y) || (body->force.z) ||
|
|
|
|
(body->force.torque_x) || (body->force.torque_y) ||
|
|
|
|
(body->force.torque_z)))
|
2012-08-21 10:47:18 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-10-04 15:40:16 -07:00
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
2012-08-20 15:15:52 -07:00
|
|
|
body->rigid_body->applyCentralForce(btVector3(body->force.x / rate,
|
2012-10-10 12:17:49 -07:00
|
|
|
body->force.y / rate,
|
|
|
|
body->force.z / rate));
|
|
|
|
body->rigid_body->applyTorque(btVector3(body->force.torque_x,
|
|
|
|
body->force.torque_y,
|
|
|
|
body->force.torque_z));
|
2012-08-20 15:15:52 -07:00
|
|
|
}
|
|
|
|
|
2012-08-16 14:35:04 -07:00
|
|
|
void
|
|
|
|
ephysics_body_recalc(EPhysics_Body *body, double rate)
|
|
|
|
{
|
2012-10-10 12:17:01 -07:00
|
|
|
Evas_Coord x, y, z, w, h, d;
|
2012-10-10 12:17:29 -07:00
|
|
|
double vx, vy, vz, lt, at;
|
2012-08-16 14:35:04 -07:00
|
|
|
|
2012-10-10 12:17:01 -07:00
|
|
|
ephysics_body_geometry_get(body, &x, &y, &z, &w, &h, &d);
|
2012-10-10 12:17:29 -07:00
|
|
|
ephysics_body_linear_velocity_get(body, &vx, &vy, &vz);
|
2012-08-16 14:35:04 -07:00
|
|
|
ephysics_body_sleeping_threshold_get(body, <, &at);
|
|
|
|
|
2012-10-10 12:17:01 -07:00
|
|
|
_ephysics_body_geometry_set(body, x, y, z, w, h, d, rate);
|
2012-10-10 12:17:29 -07:00
|
|
|
_ephysics_body_linear_velocity_set(body, vx, vy, vz, rate);
|
2012-08-16 14:35:04 -07:00
|
|
|
_ephysics_body_sleeping_threshold_set(body, lt, at, rate);
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
void
|
|
|
|
ephysics_body_evas_object_update_select(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
Eina_Bool callback_called = EINA_FALSE;
|
|
|
|
|
2012-10-25 14:53:08 -07:00
|
|
|
if (!body || body->deleted)
|
2012-06-26 15:36:12 -07:00
|
|
|
return;
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
callback_called = _ephysics_body_event_callback_call(
|
|
|
|
body, EPHYSICS_CALLBACK_BODY_UPDATE, (void *) body->evas_obj);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
if (!callback_called)
|
|
|
|
_ephysics_body_evas_object_default_update(body);
|
2012-07-03 16:20:49 -07:00
|
|
|
|
|
|
|
if (ephysics_world_bodies_outside_autodel_get(body->world))
|
|
|
|
_ephysics_body_outside_render_area_check(body);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-27 07:49:37 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:13 -07:00
|
|
|
ephysics_body_collision_position_get(const EPhysics_Body_Collision *collision, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
|
2012-07-27 07:49:37 -07:00
|
|
|
{
|
|
|
|
if (!collision)
|
|
|
|
{
|
|
|
|
ERR("Can't get body's collision data, collision is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x) *x = collision->x;
|
|
|
|
if (y) *y = collision->y;
|
2012-10-10 12:17:13 -07:00
|
|
|
if (z) *z = collision->z;
|
2012-07-27 07:49:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_collision_contact_body_get(const EPhysics_Body_Collision *collision)
|
|
|
|
{
|
|
|
|
if (!collision)
|
|
|
|
{
|
|
|
|
ERR("Can't get body's collision contact body, collision is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return collision->contact_body;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
void
|
2012-07-27 07:49:37 -07:00
|
|
|
ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body, btVector3 position)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:04:08 -07:00
|
|
|
EPhysics_Body_Collision *collision;
|
|
|
|
EPhysics_World *world;;
|
|
|
|
double rate;
|
|
|
|
int wy, wh;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-31 14:02:43 -07:00
|
|
|
if ((!body) || (!contact_body) || (body->collision_cb < 1))
|
2012-06-26 15:36:12 -07:00
|
|
|
return;
|
|
|
|
|
2012-08-10 14:04:42 -07:00
|
|
|
collision = (EPhysics_Body_Collision *)calloc(
|
|
|
|
1, sizeof(EPhysics_Body_Collision));
|
2012-08-10 14:04:08 -07:00
|
|
|
|
|
|
|
if (!collision)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:04:08 -07:00
|
|
|
ERR("Can't allocate collision data structure.");
|
|
|
|
return;
|
|
|
|
}
|
2012-07-27 07:50:25 -07:00
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
world = contact_body->world;
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(world, NULL, &wy, NULL, NULL, &wh, NULL);
|
2012-08-10 14:04:08 -07:00
|
|
|
rate = ephysics_world_rate_get(world);
|
2012-07-27 07:50:25 -07:00
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
collision->contact_body = contact_body;
|
|
|
|
collision->x = position.getX() * rate;
|
|
|
|
collision->y = wh + wy - (position.getY() * rate);
|
2012-10-10 12:17:13 -07:00
|
|
|
collision->z = position.getZ() * rate;
|
2012-07-27 07:50:25 -07:00
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
_ephysics_body_event_callback_call(body, EPHYSICS_CALLBACK_BODY_COLLISION,
|
|
|
|
(void *) collision);
|
|
|
|
|
|
|
|
free(collision);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
btRigidBody *
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_body_rigid_body_get(const EPhysics_Body *body)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
return body->rigid_body;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
btSoftBody *
|
|
|
|
ephysics_body_soft_body_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
return body->soft_body;
|
|
|
|
}
|
|
|
|
|
2012-12-03 13:29:30 -08:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_anchor_hardness_set(EPhysics_Body *body, double hardness)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set soft body's anchor hardness, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!body->soft_body)
|
|
|
|
{
|
|
|
|
ERR("Can't set soft body's anchor hardness, body seems not to be a soft"
|
|
|
|
" body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hardness < 0 || hardness > 100)
|
|
|
|
{
|
|
|
|
ERR("Can't set soft body's anchor hardness, it must be between 0 and"
|
|
|
|
" 100.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
body->anchor_hardness = EINA_TRUE;
|
|
|
|
body->soft_body->m_cfg.kAHR = 1 - (hardness / 100);
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
DBG("Soft body anchor hardness set to: %lf", hardness);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_body_soft_body_anchor_hardness_get(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get soft body's anchor hardness, body is null.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!body->soft_body)
|
|
|
|
{
|
|
|
|
ERR("Can't get soft body's anchor hardness, body seems not to be a soft"
|
|
|
|
" body.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->soft_body->m_cfg.kAHR * 100;
|
|
|
|
}
|
|
|
|
|
2012-12-05 05:50:20 -08:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_drag_coefficient_set(EPhysics_Body *body, double coefficient)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set soft body's drag coefficient, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!body->soft_body)
|
|
|
|
{
|
|
|
|
ERR("Can't set soft body's drag coefficient, body seems not to be a soft"
|
|
|
|
" body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->soft_body->m_cfg.kDG = coefficient;
|
|
|
|
DBG("Soft body drag coefficient set to: %lf", coefficient);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_body_soft_body_drag_coefficient_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get soft body's drag coefficient, body is null.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!body->soft_body)
|
|
|
|
{
|
|
|
|
ERR("Can't get soft body's drag coefficient, body seems not to be a soft"
|
|
|
|
" body.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->soft_body->m_cfg.kDG;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_hardness_set(EPhysics_Body *body, double hardness)
|
|
|
|
{
|
2012-10-16 16:12:47 -07:00
|
|
|
int m = body->material_index;
|
2012-10-04 15:38:06 -07:00
|
|
|
btSoftBody *soft_body = body->soft_body;
|
2012-10-25 14:53:44 -07:00
|
|
|
|
2012-12-03 13:29:30 -08:00
|
|
|
if (!body->anchor_hardness)
|
|
|
|
{
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
soft_body->m_cfg.kAHR = 0.8;
|
|
|
|
else
|
|
|
|
soft_body->m_cfg.kAHR = (hardness / 1000) * 0.6;
|
|
|
|
}
|
2012-10-25 14:53:44 -07:00
|
|
|
|
2012-10-16 16:12:47 -07:00
|
|
|
soft_body->m_materials[m]->m_kVST = (hardness / 1000);
|
|
|
|
soft_body->m_materials[m]->m_kLST = (hardness / 1000);
|
|
|
|
soft_body->m_materials[m]->m_kAST = (hardness / 1000);
|
2012-12-03 13:29:30 -08:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
DBG("Soft body %p hardness set to %lf.", body, hardness);
|
|
|
|
}
|
|
|
|
|
2012-09-12 14:49:14 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_hardness_set(EPhysics_Body *body, double hardness)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set soft body's hardness, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!body->soft_body)
|
|
|
|
{
|
|
|
|
ERR("Can't set soft body's hardness, body seems not to be a soft body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hardness < 0 || hardness > 100)
|
|
|
|
{
|
|
|
|
ERR("Can't set soft body's hardness, it must be between 0 and 100.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
_ephysics_body_soft_body_hardness_set(body, hardness);
|
|
|
|
ephysics_world_lock_release(body->world);
|
2012-09-12 14:49:14 -07:00
|
|
|
}
|
|
|
|
|
2012-10-16 16:18:21 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_dragging_set(EPhysics_Body *body, int triangle)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set soft body dragging status, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Can set soft body dragging status, body must not be a rigid body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (triangle < 0 || triangle >= body->soft_body->m_faces.size())
|
|
|
|
{
|
|
|
|
ERR("Could not move soft body triangle, provided body triangle index "
|
|
|
|
"ranges from 0 to %d", body->soft_body->m_faces.size());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
_ephysics_body_soft_body_dragging_set(body, triangle);
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
|
|
|
|
DBG("Body %p appended to world's dragging bodies list.", body);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_dragging_unset(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
btSoftBody::Face face;
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't unset soft body dragging status, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Can unset soft body dragging status, body must not be a rigid"
|
|
|
|
" body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-16 16:18:48 -07:00
|
|
|
if (!body->dragging_data.dragging)
|
|
|
|
{
|
|
|
|
INF("Dragging isn't set");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-16 16:18:21 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
face = body->soft_body->m_faces[body->dragging_data.triangle];
|
2012-11-23 13:43:19 -08:00
|
|
|
node = face.m_n[0];
|
|
|
|
node->m_im = body->dragging_data.mass;
|
2012-10-16 16:18:21 -07:00
|
|
|
|
2012-11-23 13:43:19 -08:00
|
|
|
body->dragging_data.mass = 0;
|
2012-10-16 16:18:21 -07:00
|
|
|
body->dragging_data.dragging = EINA_FALSE;
|
|
|
|
body->dragging_data.triangle = 0;
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
}
|
|
|
|
|
2012-09-12 14:49:14 -07:00
|
|
|
EAPI double
|
|
|
|
ephysics_body_soft_body_hardness_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get soft body's hardness, body is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!body->soft_body)
|
|
|
|
{
|
|
|
|
ERR("Can't get soft body's hardness, body seems not to be a soft body.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-10-16 16:12:47 -07:00
|
|
|
return (body->soft_body->m_materials[body->material_index]->m_kVST * 100);
|
2012-09-12 14:49:14 -07:00
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_default_config(EPhysics_Body *body, btSoftBody *soft_body)
|
|
|
|
{
|
2012-11-23 13:43:32 -08:00
|
|
|
body->bending_constraints = 1;
|
2012-10-04 15:40:16 -07:00
|
|
|
body->soft_body = soft_body;
|
|
|
|
body->soft_body->getCollisionShape()->setMargin(btScalar(0.02));
|
|
|
|
body->soft_body->setUserPointer(body);
|
|
|
|
body->soft_body->setTotalMass(body->mass);
|
|
|
|
|
|
|
|
body->soft_body->m_cfg.collisions += btSoftBody::fCollision::SDF_RS;
|
|
|
|
body->soft_body->m_cfg.collisions += btSoftBody::fCollision::VF_SS;
|
|
|
|
_ephysics_body_soft_body_hardness_set(body, 100);
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
static EPhysics_Body *
|
2012-10-04 15:40:07 -07:00
|
|
|
_ephysics_body_soft_body_add(EPhysics_World *world, btCollisionShape *collision_shape, btSoftBody *soft_body)
|
2012-08-22 13:04:39 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body *body;
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
body = _ephysics_body_rigid_body_add(world, collision_shape, "soft box", 0.5,
|
2012-10-10 12:17:54 -07:00
|
|
|
0.5, 0.5);
|
2012-08-22 13:04:39 -07:00
|
|
|
if (!body)
|
|
|
|
{
|
2012-10-04 15:39:53 -07:00
|
|
|
if (body->deleted) return NULL;
|
|
|
|
body->deleted = EINA_TRUE;
|
|
|
|
ephysics_world_body_del(body->world, body);
|
2012-08-22 13:04:39 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-10-04 15:40:07 -07:00
|
|
|
|
2012-10-16 16:12:47 -07:00
|
|
|
body->material_index = 0;
|
2012-10-04 15:40:16 -07:00
|
|
|
body->type = EPHYSICS_BODY_TYPE_SOFT;
|
|
|
|
_ephysics_body_soft_body_default_config(body, soft_body);
|
2012-08-22 13:04:39 -07:00
|
|
|
|
2012-09-12 14:49:14 -07:00
|
|
|
body->rigid_body->setCollisionFlags(
|
2012-10-25 14:54:14 -07:00
|
|
|
btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
2012-08-22 13:04:39 -07:00
|
|
|
|
2012-09-12 14:49:14 -07:00
|
|
|
_ephysics_body_soft_body_constraints_rebuild(body);
|
2012-08-22 13:04:39 -07:00
|
|
|
ephysics_world_soft_body_add(world, body);
|
2012-10-25 14:54:14 -07:00
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_cloth_anchor_full_add(EPhysics_Body *body1, EPhysics_Body *body2, EPhysics_Body_Cloth_Anchor_Side side)
|
|
|
|
{
|
|
|
|
int rows;
|
|
|
|
int columns;
|
2012-10-25 14:54:55 -07:00
|
|
|
double anchor_mass;
|
2012-10-04 15:40:16 -07:00
|
|
|
|
|
|
|
if (!body1 || !body2)
|
|
|
|
{
|
|
|
|
ERR("Could not add anchors, body1 or body2 is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body1->type != EPHYSICS_BODY_TYPE_CLOTH ||
|
|
|
|
body2->type != EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Cloth anchors are allowed only between cloth and rigid body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:16 -08:00
|
|
|
if ((side < 0) || (side >= EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_LAST))
|
|
|
|
{
|
|
|
|
ERR("Could not add anchors, side is invalid.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-31 14:03:09 -07:00
|
|
|
rows = body1->cloth_rows + 1;
|
|
|
|
columns = body1->cloth_columns + 1;
|
2012-10-25 14:54:55 -07:00
|
|
|
anchor_mass = body1->soft_body->m_nodes.size() * 0.025;
|
2012-10-04 15:40:16 -07:00
|
|
|
|
2012-10-25 14:53:30 -07:00
|
|
|
if (side == EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_RIGHT)
|
2012-10-04 15:40:16 -07:00
|
|
|
{
|
|
|
|
for (int i = 0; i < rows; i++)
|
2012-10-25 14:54:55 -07:00
|
|
|
{
|
|
|
|
body1->soft_body->setMass(i, anchor_mass);
|
|
|
|
body1->soft_body->appendAnchor(i, body2->rigid_body);
|
|
|
|
}
|
2012-10-04 15:40:16 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-25 14:53:30 -07:00
|
|
|
if (side == EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_LEFT)
|
2012-10-04 15:40:16 -07:00
|
|
|
{
|
|
|
|
for (int i = 1; i <= rows; i++)
|
2012-10-25 14:54:55 -07:00
|
|
|
{
|
|
|
|
body1->soft_body->setMass((rows * columns) - i, anchor_mass);
|
|
|
|
body1->soft_body->appendAnchor((rows * columns) - i,
|
|
|
|
body2->rigid_body);
|
|
|
|
}
|
2012-10-04 15:40:16 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-25 14:53:30 -07:00
|
|
|
if (side == EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_BOTTOM)
|
2012-10-04 15:40:16 -07:00
|
|
|
{
|
|
|
|
for (int i = 0; i <= rows; i++)
|
2012-10-25 14:54:55 -07:00
|
|
|
{
|
|
|
|
body1->soft_body->setMass((i * rows), anchor_mass);
|
|
|
|
body1->soft_body->appendAnchor(i * rows, body2->rigid_body);
|
|
|
|
}
|
2012-10-04 15:40:16 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-25 14:53:30 -07:00
|
|
|
if (side == EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_TOP)
|
2012-10-04 15:40:16 -07:00
|
|
|
{
|
|
|
|
for (int i = 0; i < columns; i++)
|
2012-10-25 14:54:55 -07:00
|
|
|
{
|
|
|
|
body1->soft_body->setMass((rows - 1) + rows * i, anchor_mass);
|
2012-10-04 15:40:16 -07:00
|
|
|
body1->soft_body->appendAnchor((rows - 1) + rows * i,
|
|
|
|
body2->rigid_body);
|
2012-10-25 14:54:55 -07:00
|
|
|
}
|
2012-10-04 15:40:16 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_cloth_anchor_add(EPhysics_Body *body1, EPhysics_Body *body2, int node)
|
|
|
|
{
|
|
|
|
if (!body1 || !body2)
|
|
|
|
{
|
|
|
|
ERR("Could not add anchors, body1 or body2 is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body1->type != EPHYSICS_BODY_TYPE_CLOTH ||
|
|
|
|
body2->type != EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Cloth anchors are allowed only between cloth and rigid body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body1->soft_body->appendAnchor(node, body2->rigid_body);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_cloth_anchor_del(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Could not delete anchor, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->type != EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
{
|
|
|
|
ERR("Could not delete anchors, body is not a cloth.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->soft_body->m_anchors.resize(0);
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:49:51 -08:00
|
|
|
static Eina_List *
|
|
|
|
_ephysics_body_slices_add(EPhysics_Body *body, int slices_cnt, int *points, double delta, double max)
|
2012-10-25 14:54:14 -07:00
|
|
|
{
|
2012-11-23 13:49:51 -08:00
|
|
|
Eina_List *slices = NULL;
|
2012-10-25 14:54:14 -07:00
|
|
|
EPhysics_Body_Soft_Body_Slice *slice;
|
|
|
|
btSoftBody::tFaceArray faces;
|
|
|
|
|
2012-11-23 13:49:51 -08:00
|
|
|
for (int i = 0; i < slices_cnt; i++)
|
2012-10-25 14:54:14 -07:00
|
|
|
{
|
|
|
|
faces = body->soft_body->m_faces;
|
|
|
|
|
|
|
|
slice = _ephysics_body_soft_body_slice_new(body, delta, max,
|
2012-11-23 13:49:51 -08:00
|
|
|
points[i]);
|
|
|
|
if (!slice) goto no_slices;
|
2012-10-25 14:54:14 -07:00
|
|
|
|
2012-11-23 13:49:51 -08:00
|
|
|
slices = eina_list_append(slices, slice);
|
2012-10-25 14:54:14 -07:00
|
|
|
}
|
2012-11-23 13:49:51 -08:00
|
|
|
return slices;
|
|
|
|
|
|
|
|
no_slices:
|
|
|
|
_ephysics_body_soft_body_slices_clean(slices);
|
|
|
|
return NULL;
|
2012-10-25 14:54:14 -07:00
|
|
|
}
|
|
|
|
|
2012-10-25 14:54:37 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_position_iterations_set(EPhysics_Body *body, int iterations)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Could not set the number of iterations for position solver, body "
|
|
|
|
"is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Could not set the number of iterations for position solver, body "
|
|
|
|
"must be a soft body or a cloth");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->soft_body->m_cfg.piterations = iterations;
|
|
|
|
DBG("Soft body position solver iterations set to: %d", iterations);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
ephysics_body_soft_body_position_iterations_get(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Could not get the number of iterations for position solver, body "
|
|
|
|
"is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Could not get the number of iterations for position solver, body "
|
|
|
|
"must be a soft body or a cloth");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->soft_body->m_cfg.piterations;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:43:32 -08:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_bending_constraints_add(EPhysics_Body *body, int number)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Could add new bending constraint, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (number <= 0)
|
|
|
|
{
|
|
|
|
ERR("Could not add new bending constraints, number must be greater"
|
|
|
|
" than 0");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->bending_constraints += number;
|
|
|
|
DBG("Added new bending constraints to body: %p", body);
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
EAPI EPhysics_Body *
|
2012-10-25 14:54:48 -07:00
|
|
|
ephysics_body_cloth_add(EPhysics_World *world, unsigned short rows, unsigned short columns)
|
2012-10-04 15:40:16 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body *body;
|
2012-11-23 13:49:57 -08:00
|
|
|
EPhysics_Body_Face_Slice *face_slice;
|
2012-10-04 15:40:16 -07:00
|
|
|
btSoftBodyWorldInfo *world_info;
|
|
|
|
btSoftBody *soft_body;
|
2012-10-25 14:54:48 -07:00
|
|
|
const int body_rows = (!rows) ? 15 : rows;
|
|
|
|
const int body_columns = (!columns) ? 15 : columns;
|
2012-10-04 15:40:16 -07:00
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't add circle, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
world_info = ephysics_world_info_get(world);
|
|
|
|
soft_body = btSoftBodyHelpers::CreatePatch(*world_info,
|
2012-10-16 16:12:47 -07:00
|
|
|
btVector3(2, 2, 0),
|
|
|
|
btVector3(2, 1, 0),
|
2012-10-25 14:53:30 -07:00
|
|
|
btVector3(1, 2, 0),
|
|
|
|
btVector3(1, 1, 0),
|
2012-10-31 14:03:09 -07:00
|
|
|
body_rows + 1, body_columns + 1,
|
|
|
|
0, false);
|
2012-10-25 14:54:48 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
if (!soft_body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a new soft body.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-10-10 12:17:54 -07:00
|
|
|
body = _ephysics_body_new(world, 1, 0.5, 0.5, 0.5);
|
2012-10-04 15:40:16 -07:00
|
|
|
if (!body)
|
|
|
|
goto no_body;
|
|
|
|
|
2012-10-16 16:12:47 -07:00
|
|
|
soft_body->setPose(false, true);
|
|
|
|
|
|
|
|
soft_body->appendMaterial();
|
|
|
|
body->material_index = 1;
|
2012-10-25 14:54:48 -07:00
|
|
|
soft_body->m_cfg.piterations = body_rows / 5;
|
2012-10-16 16:12:47 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
_ephysics_body_soft_body_default_config(body, soft_body);
|
|
|
|
_ephysics_body_cloth_constraints_rebuild(body);
|
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
face_slice = _ephysics_body_face_slice_add(body,
|
|
|
|
EPHYSICS_BODY_CLOTH_FACE_FRONT);
|
|
|
|
if (!face_slice)
|
|
|
|
{
|
|
|
|
ERR("Could not allocate face slice data structure.");
|
|
|
|
goto no_face_slice;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_slice->slices_cnt = soft_body->m_faces.size();
|
|
|
|
face_slice->points_deform = (int *)malloc(face_slice->slices_cnt *
|
|
|
|
sizeof(int));
|
|
|
|
if (!face_slice->points_deform)
|
2012-10-04 15:40:16 -07:00
|
|
|
{
|
|
|
|
ERR("Couldn't create points of deformation.");
|
|
|
|
goto no_deform;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
for (int i = 0; i < face_slice->slices_cnt; i++)
|
|
|
|
face_slice->points_deform[i] = i;
|
2012-11-23 13:49:51 -08:00
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
face_slice->slices = _ephysics_body_slices_add(body, face_slice->slices_cnt,
|
|
|
|
face_slice->points_deform, -1,
|
|
|
|
1);
|
|
|
|
if (!face_slice->slices)
|
2012-10-25 14:54:14 -07:00
|
|
|
{
|
|
|
|
ERR("Couldn't create slices.");
|
|
|
|
goto no_slices;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
body->default_face = face_slice;
|
|
|
|
|
2012-10-25 14:54:48 -07:00
|
|
|
body->cloth_columns = body_columns;
|
|
|
|
body->cloth_rows = body_rows;
|
2012-10-04 15:40:16 -07:00
|
|
|
body->type = EPHYSICS_BODY_TYPE_CLOTH;
|
|
|
|
|
|
|
|
ephysics_world_soft_body_add(world, body);
|
2012-10-25 14:54:14 -07:00
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
return body;
|
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
no_slices:
|
2012-10-04 15:40:16 -07:00
|
|
|
no_deform:
|
2012-11-23 13:49:57 -08:00
|
|
|
_ephysics_body_face_slice_del(face_slice);
|
|
|
|
no_face_slice:
|
2012-10-04 15:40:16 -07:00
|
|
|
free(body);
|
|
|
|
no_body:
|
|
|
|
delete soft_body;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-10-16 16:12:47 -07:00
|
|
|
static void
|
2012-10-16 16:18:21 -07:00
|
|
|
_ephysics_body_soft_body_single_face_transform(btSoftBody *soft_body, int face_idx, int node_idx, btTransform trans)
|
2012-10-16 16:12:47 -07:00
|
|
|
{
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
|
|
|
|
const btScalar margin = soft_body->getCollisionShape()->getMargin();
|
|
|
|
|
|
|
|
node = soft_body->m_faces[face_idx].m_n[node_idx];
|
2012-10-25 14:54:55 -07:00
|
|
|
|
|
|
|
if (node->m_battach)
|
|
|
|
return;
|
|
|
|
|
2012-10-16 16:12:47 -07:00
|
|
|
node->m_x = trans * node->m_x;
|
|
|
|
node->m_q = trans * node->m_q;
|
|
|
|
node->m_n = trans.getBasis() * node->m_n;
|
|
|
|
vol = btDbvtVolume::FromCR(node->m_x, margin);
|
|
|
|
soft_body->m_ndbvt.update(node->m_leaf, vol);
|
|
|
|
}
|
|
|
|
|
2012-10-16 16:18:21 -07:00
|
|
|
void
|
|
|
|
ephysics_body_soft_body_dragging_apply(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
btSoftBody::Face face;
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
|
|
|
|
face = body->soft_body->m_faces[body->dragging_data.triangle];
|
2012-11-23 13:43:19 -08:00
|
|
|
node = face.m_n[0];
|
|
|
|
node->m_v *= 0;
|
|
|
|
node->m_im *= 0;
|
2012-10-16 16:18:21 -07:00
|
|
|
}
|
|
|
|
|
2012-10-16 16:12:47 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_triangle_move(EPhysics_Body *body, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
|
|
|
|
{
|
|
|
|
btScalar xx, yy, zz;
|
2012-11-23 13:43:19 -08:00
|
|
|
Evas_Coord wh, wy;
|
2012-10-16 16:12:47 -07:00
|
|
|
double rate;
|
|
|
|
btVector3 new_pos;
|
|
|
|
btTransform diff;
|
|
|
|
btSoftBody::Face face;
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Could not move soft body triangle, body must be soft or cloth.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idx < 0 || idx >= body->soft_body->m_faces.size())
|
|
|
|
{
|
|
|
|
ERR("Could not move soft body triangle, provided body triangle index "
|
|
|
|
"ranges from 0 to %d", body->soft_body->m_faces.size());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-11-23 13:43:19 -08:00
|
|
|
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, NULL, &wh,
|
2012-10-16 16:12:59 -07:00
|
|
|
NULL);
|
2012-10-16 16:12:47 -07:00
|
|
|
|
|
|
|
xx = x / rate;
|
2012-11-23 13:43:19 -08:00
|
|
|
yy = ((wh + wy) - y) / rate;
|
2012-10-16 16:12:47 -07:00
|
|
|
zz = z / rate;
|
|
|
|
|
|
|
|
new_pos = btVector3(xx, yy, zz);
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
|
|
|
|
face = body->soft_body->m_faces[idx];
|
|
|
|
|
2012-11-23 13:43:19 -08:00
|
|
|
node = face.m_n[0];
|
|
|
|
diff.setIdentity();
|
|
|
|
diff.setOrigin(new_pos - node->m_x);
|
|
|
|
_ephysics_body_soft_body_single_face_transform(body->soft_body, idx, 0, diff);
|
2012-10-16 16:12:47 -07:00
|
|
|
|
2012-11-23 13:43:19 -08:00
|
|
|
diff.setOrigin(diff.getOrigin() * 0.1);
|
|
|
|
for (int m = 0; m < body->soft_body->m_faces.size(); m++)
|
|
|
|
{
|
|
|
|
if (m == idx) continue;
|
|
|
|
_ephysics_body_soft_body_single_face_transform(body->soft_body, m, 0,
|
|
|
|
diff);
|
2012-10-16 16:12:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
body->soft_body->updateClusters();
|
|
|
|
body->soft_body->updateBounds();
|
|
|
|
body->soft_body->updateNormals();
|
|
|
|
body->soft_body->updatePose();
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:52:08 -08:00
|
|
|
EAPI Eina_List *
|
|
|
|
ephysics_body_soft_body_triangles_inside_get(const EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord z, Evas_Coord w, Evas_Coord h, Evas_Coord d)
|
|
|
|
{
|
|
|
|
Eina_List *face_list = NULL;
|
|
|
|
btSoftBody::Face *bt_face;
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
int out, *idx;
|
|
|
|
btScalar nx, ny, nz, xx, yy, zz, dd, ww, hh;
|
|
|
|
Evas_Coord wy, wh;
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Can't get triangle indexes, operation not permited to rigid"
|
|
|
|
" bodies.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, NULL, &wh,
|
|
|
|
NULL);
|
|
|
|
xx = x / rate;
|
2012-12-03 13:29:21 -08:00
|
|
|
yy = (wy + (wh - y)) / rate;
|
2012-11-23 13:52:08 -08:00
|
|
|
zz = z / rate;
|
|
|
|
dd = d / rate;
|
|
|
|
ww = w / rate;
|
|
|
|
hh = h / rate;
|
|
|
|
|
|
|
|
for (int m = 0; m < body->soft_body->m_faces.size(); m++)
|
|
|
|
{
|
|
|
|
out = 0;
|
|
|
|
bt_face = &body->soft_body->m_faces[m];
|
|
|
|
for (int n = 0; n < 3; n++)
|
|
|
|
{
|
|
|
|
node = bt_face->m_n[n];
|
|
|
|
nx = node->m_x.x();
|
|
|
|
ny = node->m_x.y();
|
|
|
|
nz = node->m_x.z();
|
|
|
|
|
2012-12-10 09:15:05 -08:00
|
|
|
if ((nz < zz || nz > zz + dd) || (nx < xx || nx > xx + ww) ||
|
2012-12-03 13:29:21 -08:00
|
|
|
(ny > yy || ny < yy - hh))
|
2012-11-23 13:52:08 -08:00
|
|
|
out++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!out)
|
|
|
|
{
|
|
|
|
idx = (int *)malloc(sizeof(int));
|
|
|
|
*idx = m;
|
|
|
|
face_list = eina_list_append(face_list, idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
|
|
|
|
return face_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_triangle_impulse_apply(EPhysics_Body *body, int idx, double x, double y, double z)
|
2012-11-23 13:43:49 -08:00
|
|
|
{
|
|
|
|
btSoftBody::Face face;
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
double rate;
|
|
|
|
btVector3 impulse;
|
|
|
|
|
2012-11-23 13:52:08 -08:00
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-12-03 13:29:21 -08:00
|
|
|
impulse = btVector3(x / rate, - y / rate, z / rate);
|
2012-11-23 13:52:08 -08:00
|
|
|
|
|
|
|
face = body->soft_body->m_faces[idx];
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
node = face.m_n[i];
|
2012-12-03 13:29:30 -08:00
|
|
|
node->m_v = impulse * node->m_im;
|
2012-11-23 13:52:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Impulse applied to soft body node(%d): %lf, %lf, %lf", idx, impulse.x(),
|
|
|
|
impulse.y(), impulse.z());
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_triangle_impulse_apply(EPhysics_Body * body, int idx, double x, double y, double z)
|
|
|
|
{
|
|
|
|
|
2012-11-23 13:43:49 -08:00
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Can't apply impulse, operation not permited to rigid bodies.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idx < 0 || idx >= body->soft_body->m_faces.size())
|
|
|
|
{
|
|
|
|
ERR("Could not apply impulse, provided body triangle index ranges from"
|
|
|
|
" 0 to %d", body->soft_body->m_faces.size());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ephysics_world_lock_take(body->world);
|
2012-11-23 13:52:08 -08:00
|
|
|
_ephysics_body_soft_body_triangle_impulse_apply(body, idx, x, y, z);
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
}
|
2012-11-23 13:43:49 -08:00
|
|
|
|
2012-11-23 13:52:08 -08:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_soft_body_triangle_list_impulse_apply(EPhysics_Body *body, Eina_List *triangles, double x, double y, double z)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
int idx, faces_cnt;
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Can't apply impulse, operation not permited to rigid bodies.");
|
|
|
|
return;
|
|
|
|
}
|
2012-11-23 13:43:49 -08:00
|
|
|
|
2012-11-23 13:52:08 -08:00
|
|
|
faces_cnt = body->soft_body->m_faces.size();
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
EINA_LIST_FOREACH(triangles, l, ldata)
|
|
|
|
{
|
|
|
|
idx = *(int *)ldata;
|
|
|
|
if (idx < 0 || idx >= faces_cnt)
|
|
|
|
{
|
|
|
|
INF("Could not apply impulse to triangle %d, provided body"
|
|
|
|
" triangle index ranges from 0 to %d", idx, faces_cnt);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_body_soft_body_triangle_impulse_apply(body, idx, x, y, z);
|
|
|
|
DBG("Applied impulse on body %p, triangle: %d", body, idx);
|
|
|
|
}
|
2012-11-23 13:43:49 -08:00
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
}
|
|
|
|
|
2012-10-16 16:12:47 -07:00
|
|
|
EAPI int
|
|
|
|
ephysics_body_soft_body_triangle_index_get(EPhysics_Body *body, Evas_Coord x, Evas_Coord y)
|
|
|
|
{
|
2012-10-31 14:03:17 -07:00
|
|
|
int w, h, r, c, index = -1;
|
|
|
|
|
|
|
|
if (!body->evas_obj)
|
|
|
|
{
|
|
|
|
ERR("No evas object associated to body");
|
|
|
|
return -1;
|
|
|
|
}
|
2012-10-16 16:12:47 -07:00
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
ERR("Can't get node index, operation not permited to rigid bodies");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-10-31 14:03:17 -07:00
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_SOFT)
|
|
|
|
{
|
|
|
|
ERR("Can't get node index, not implemented for soft bodies yet.");
|
|
|
|
return -1;
|
|
|
|
}
|
2012-10-16 16:12:47 -07:00
|
|
|
|
2012-10-31 14:03:17 -07:00
|
|
|
evas_object_geometry_get(body->evas_obj, NULL, NULL, &w, &h);
|
|
|
|
r = y * body->cloth_rows / h;
|
|
|
|
c = (w - x) * body->cloth_columns / w;
|
2012-10-16 16:12:47 -07:00
|
|
|
|
2012-10-31 14:03:17 -07:00
|
|
|
index = 2 * r + c * body->cloth_rows * 2;
|
2012-10-16 16:12:47 -07:00
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
static EPhysics_Body_Face_Slice *
|
|
|
|
_ephysics_body_soft_ellipsoid_face_slices_add(EPhysics_Body *body, EPhysics_Body_Face face, btVector3 center)
|
|
|
|
{
|
|
|
|
btSoftBody::Face *bt_face;
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
int out;
|
|
|
|
btScalar depth_limit;
|
|
|
|
Eina_List *face_list = NULL;
|
|
|
|
void *data;
|
|
|
|
int *idx, i = 0;
|
|
|
|
EPhysics_Body_Face_Slice *face_slice;
|
|
|
|
|
|
|
|
depth_limit = center.z();
|
|
|
|
|
|
|
|
for (int m = 0; m < body->soft_body->m_faces.size(); m++)
|
|
|
|
{
|
|
|
|
out = 0;
|
|
|
|
bt_face = &body->soft_body->m_faces[m];
|
|
|
|
for (int n = 0; n < 3; n++)
|
|
|
|
{
|
|
|
|
node = bt_face->m_n[n];
|
|
|
|
if ((face == EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_FRONT &&
|
|
|
|
node->m_x.z() > depth_limit) ||
|
|
|
|
(face == EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_BACK &&
|
|
|
|
node->m_x.z() < depth_limit))
|
|
|
|
out++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (out < 2)
|
|
|
|
{
|
|
|
|
idx = (int *)malloc(sizeof(int));
|
|
|
|
if (!idx)
|
|
|
|
goto no_deform;
|
|
|
|
*idx = m;
|
|
|
|
face_list = eina_list_append(face_list, idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
face_slice = _ephysics_body_face_slice_add(body, face);
|
|
|
|
if (!face_slice)
|
|
|
|
{
|
|
|
|
ERR("Could not allocate face slice data structure.");
|
|
|
|
goto no_deform;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_slice->slices_cnt = eina_list_count(face_list);
|
|
|
|
face_slice->points_deform = (int *)malloc(face_slice->slices_cnt *
|
|
|
|
sizeof(int));
|
|
|
|
if (!face_slice->points_deform)
|
|
|
|
goto no_points_deform;
|
|
|
|
|
|
|
|
EINA_LIST_FREE(face_list, data)
|
|
|
|
{
|
|
|
|
face_slice->points_deform[i] = *((int *)data);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_slice->slices = _ephysics_body_slices_add(body, face_slice->slices_cnt,
|
|
|
|
face_slice->points_deform, -0.5, 1);
|
|
|
|
if (!face_slice->slices)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create slices.");
|
|
|
|
goto no_points_deform;
|
|
|
|
}
|
|
|
|
return face_slice;
|
|
|
|
|
|
|
|
no_points_deform:
|
|
|
|
_ephysics_body_face_slice_del(face_slice);
|
|
|
|
no_deform:
|
|
|
|
EINA_LIST_FREE(face_list, data)
|
|
|
|
free(data);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_soft_ellipsoid_add(EPhysics_World *world, int granularity)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body;
|
|
|
|
EPhysics_Body_Face_Slice *front_face, *back_face;
|
|
|
|
btCollisionShape *shape;
|
|
|
|
btSoftBodyWorldInfo *world_info;
|
|
|
|
btSoftBody *soft_body;
|
|
|
|
btVector3 center, radius;
|
|
|
|
int body_granularity = (!granularity) ? 100 : granularity;
|
|
|
|
|
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't add circle, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ephysics_world_lock_take(world);
|
|
|
|
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);
|
|
|
|
center = btVector3(1, 1, 1);
|
|
|
|
radius = btVector3(0.5, 0.5, 0.5);
|
|
|
|
soft_body = btSoftBodyHelpers::CreateEllipsoid(*world_info, center, radius,
|
|
|
|
body_granularity);
|
|
|
|
|
|
|
|
if (!soft_body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a new soft body.");
|
|
|
|
goto no_soft_body;
|
|
|
|
}
|
|
|
|
|
|
|
|
body = _ephysics_body_soft_body_add(world, shape, soft_body);
|
|
|
|
if (!body)
|
|
|
|
goto no_body;
|
|
|
|
|
2012-12-03 13:29:30 -08:00
|
|
|
body->soft_body->setPose(false, true);
|
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
front_face = _ephysics_body_soft_ellipsoid_face_slices_add(body,
|
|
|
|
EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_FRONT, center);
|
|
|
|
if (!front_face)
|
|
|
|
{
|
|
|
|
ERR("Could not create points of deformation mapping for front face.");
|
|
|
|
goto no_front_face;
|
|
|
|
}
|
|
|
|
body->default_face = front_face;
|
|
|
|
|
|
|
|
back_face = _ephysics_body_soft_ellipsoid_face_slices_add(body,
|
|
|
|
EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_BACK, center);
|
|
|
|
if (!back_face)
|
|
|
|
{
|
|
|
|
ERR("Could not create points of deformation mapping for back face.");
|
|
|
|
goto no_back_face;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->shape = EPHYSICS_BODY_SHAPE_ELLIPSOID;
|
|
|
|
ephysics_world_lock_release(world);
|
|
|
|
return body;
|
|
|
|
|
|
|
|
no_back_face:
|
|
|
|
_ephysics_body_face_slice_del(front_face);
|
|
|
|
no_front_face:
|
|
|
|
ephysics_world_body_del(world, body);
|
|
|
|
no_body:
|
|
|
|
delete soft_body;
|
|
|
|
no_soft_body:
|
|
|
|
delete shape;
|
|
|
|
no_collision_shape:
|
|
|
|
ephysics_world_lock_release(world);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_soft_circle_add(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body;
|
2012-11-23 13:49:57 -08:00
|
|
|
EPhysics_Body_Face_Slice *face_slice;
|
2012-08-22 13:04:39 -07:00
|
|
|
btCollisionShape *shape;
|
|
|
|
btSoftBodyWorldInfo *world_info;
|
|
|
|
btSoftBody *soft_body;
|
2012-10-04 15:40:07 -07:00
|
|
|
int points[19] = {16, 58, 44, 79, 97, 35, 6, 27, 45, 1, 38, 18, 21, 10, 26,
|
|
|
|
7, 86, 37, 55};
|
2012-08-22 13:04:39 -07:00
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't add circle, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(world);
|
2012-10-04 15:40:07 -07:00
|
|
|
shape = new btCylinderShapeZ(btVector3(0.5, 0.5, 0.5));
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
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],
|
2012-09-12 14:49:14 -07:00
|
|
|
CYLINDER_NUM_TRIANGLES);
|
2012-08-22 13:04:39 -07:00
|
|
|
if (!soft_body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a new soft body.");
|
|
|
|
goto no_soft_body;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:07 -07:00
|
|
|
body = _ephysics_body_soft_body_add(world, shape, soft_body);
|
2012-08-22 13:04:39 -07:00
|
|
|
if (!body)
|
|
|
|
goto no_body;
|
|
|
|
|
2012-11-09 10:53:04 -08:00
|
|
|
body->shape = EPHYSICS_BODY_SHAPE_CYLINDER;
|
2012-11-23 13:49:57 -08:00
|
|
|
|
|
|
|
face_slice = _ephysics_body_face_slice_add(body,
|
|
|
|
EPHYSICS_BODY_SOFT_CIRCLE_FACE_FRONT);
|
|
|
|
if (!face_slice)
|
|
|
|
{
|
|
|
|
ERR("Could not allocate face slice data structure.");
|
|
|
|
goto no_face_slice;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_slice->slices_cnt = 19;
|
|
|
|
face_slice->points_deform = (int *)malloc(face_slice->slices_cnt *
|
|
|
|
sizeof(int));
|
|
|
|
if (!face_slice->points_deform)
|
2012-10-04 15:40:07 -07:00
|
|
|
{
|
|
|
|
ERR("Couldn't create points of deformation.");
|
|
|
|
goto no_deform;
|
|
|
|
}
|
2012-08-22 13:04:39 -07:00
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
for (int i = 0; i < face_slice->slices_cnt; i++)
|
|
|
|
face_slice->points_deform[i] = points[i];
|
2012-11-23 13:49:51 -08:00
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
face_slice->slices = _ephysics_body_slices_add(body, face_slice->slices_cnt,
|
|
|
|
face_slice->points_deform, 0.55,
|
|
|
|
1.1);
|
|
|
|
if (!face_slice->slices)
|
2012-10-25 14:54:14 -07:00
|
|
|
{
|
|
|
|
ERR("Couldn't create slices.");
|
|
|
|
goto no_slices;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
body->default_face = face_slice;
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(world);
|
2012-08-22 13:04:39 -07:00
|
|
|
return body;
|
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
no_slices:
|
|
|
|
no_deform:
|
2012-11-23 13:49:57 -08:00
|
|
|
_ephysics_body_face_slice_del(face_slice);
|
|
|
|
no_face_slice:
|
2012-10-25 14:54:14 -07:00
|
|
|
ephysics_world_body_del(world, body);
|
2012-08-22 13:04:39 -07:00
|
|
|
no_body:
|
|
|
|
delete soft_body;
|
|
|
|
no_soft_body:
|
|
|
|
delete shape;
|
|
|
|
no_collision_shape:
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(world);
|
2012-08-22 13:04:39 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_circle_add(EPhysics_World *world)
|
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
btCollisionShape *collision_shape;
|
2012-10-04 15:38:06 -07:00
|
|
|
EPhysics_Body *body;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
if (!world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
ERR("Can't add circle, world is null.");
|
2012-06-26 15:36:12 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
collision_shape = new btCylinderShapeZ(btVector3(0.5, 0.5, 0.5));
|
2012-08-22 13:04:39 -07:00
|
|
|
if (!collision_shape)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a new cylinder shape.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(world);
|
2012-10-04 15:40:16 -07:00
|
|
|
body = _ephysics_body_rigid_body_add(world, collision_shape, "circle", 0.5,
|
2012-10-10 12:17:54 -07:00
|
|
|
0.5, 0.5);
|
2012-11-09 10:53:04 -08:00
|
|
|
body->shape = EPHYSICS_BODY_SHAPE_CYLINDER;
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(world);
|
|
|
|
return body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_soft_box_add(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body;
|
2012-11-23 13:49:57 -08:00
|
|
|
EPhysics_Body_Face_Slice *face_slice;
|
2012-08-22 13:04:39 -07:00
|
|
|
btCollisionShape *shape;
|
|
|
|
btSoftBodyWorldInfo *world_info;
|
|
|
|
btSoftBody *soft_body;
|
2012-10-04 15:40:07 -07:00
|
|
|
int points[16] = {14, 85, 88, 28, 41, 55, 10, 24, 93, 79, 56, 86, 91, 8,
|
|
|
|
27, 1};
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't add circle, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(world);
|
2012-08-22 13:04:39 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:07 -07:00
|
|
|
body = _ephysics_body_soft_body_add(world, shape, soft_body);
|
2012-08-22 13:04:39 -07:00
|
|
|
if (!body)
|
|
|
|
goto no_body;
|
|
|
|
|
2012-11-09 10:53:04 -08:00
|
|
|
body->shape = EPHYSICS_BODY_SHAPE_BOX;
|
2012-11-23 13:49:57 -08:00
|
|
|
|
|
|
|
face_slice = _ephysics_body_face_slice_add(body,
|
|
|
|
EPHYSICS_BODY_SOFT_BOX_FACE_FRONT);
|
|
|
|
if (!face_slice)
|
|
|
|
{
|
|
|
|
ERR("Could not allocate face slice data structure.");
|
|
|
|
goto no_face_slice;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_slice->slices_cnt = 16;
|
|
|
|
face_slice->points_deform = (int *)malloc(face_slice->slices_cnt *
|
|
|
|
sizeof(int));
|
|
|
|
if (!face_slice->points_deform)
|
2012-10-04 15:40:07 -07:00
|
|
|
{
|
|
|
|
ERR("Couldn't create points of deformation.");
|
|
|
|
goto no_deform;
|
|
|
|
}
|
2012-08-22 13:04:39 -07:00
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
for (int i = 0; i < face_slice->slices_cnt; i++)
|
|
|
|
face_slice->points_deform[i] = points[i];
|
2012-08-22 13:04:39 -07:00
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
face_slice->slices = _ephysics_body_slices_add(body, face_slice->slices_cnt,
|
|
|
|
face_slice->points_deform, 0.55,
|
|
|
|
1.1);
|
|
|
|
if (!face_slice->slices)
|
2012-10-25 14:54:14 -07:00
|
|
|
{
|
|
|
|
ERR("Couldn't create slices.");
|
|
|
|
goto no_slices;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
body->default_face = face_slice;
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(world);
|
2012-08-22 13:04:39 -07:00
|
|
|
return body;
|
|
|
|
|
2012-10-25 14:54:14 -07:00
|
|
|
no_slices:
|
2012-11-23 13:49:57 -08:00
|
|
|
no_face_slice:
|
|
|
|
_ephysics_body_face_slice_del(face_slice);
|
2012-10-25 14:54:14 -07:00
|
|
|
no_deform:
|
|
|
|
ephysics_world_body_del(world, body);
|
2012-08-22 13:04:39 -07:00
|
|
|
no_body:
|
|
|
|
delete soft_body;
|
|
|
|
no_soft_body:
|
|
|
|
delete shape;
|
|
|
|
no_collision_shape:
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(world);
|
2012-08-22 13:04:39 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_box_add(EPhysics_World *world)
|
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
btCollisionShape *collision_shape;
|
2012-10-04 15:38:06 -07:00
|
|
|
EPhysics_Body *body;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
if (!world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
ERR("Can't add box, world is null.");
|
2012-06-26 15:36:12 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
collision_shape = new btBoxShape(btVector3(0.5, 0.5, 0.5));
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(world);
|
2012-10-10 12:17:54 -07:00
|
|
|
body = _ephysics_body_rigid_body_add(world, collision_shape, "box", 0.5,
|
|
|
|
0.5, 0.5);
|
2012-11-09 10:53:04 -08:00
|
|
|
body->shape = EPHYSICS_BODY_SHAPE_BOX;
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(world);
|
|
|
|
return body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:19 -07:00
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_shape_add(EPhysics_World *world, EPhysics_Shape *shape)
|
|
|
|
{
|
2012-10-10 12:17:54 -07:00
|
|
|
double max_x, max_y, max_z, min_x, min_y, min_z, cm_x, cm_y, cm_z,
|
|
|
|
range_x, range_y, range_z;
|
2012-09-12 14:50:01 -07:00
|
|
|
btConvexHullShape *full_shape, *simplified_shape;
|
|
|
|
btAlignedObjectArray<btVector3> vertexes, planes;
|
2012-08-10 14:05:19 -07:00
|
|
|
const Eina_Inlist *points;
|
|
|
|
EPhysics_Point *point;
|
2012-10-04 15:38:06 -07:00
|
|
|
EPhysics_Body *body;
|
2012-09-12 14:50:01 -07:00
|
|
|
int array_size, i;
|
2012-08-22 13:05:19 -07:00
|
|
|
btShapeHull *hull;
|
2012-08-10 14:05:19 -07:00
|
|
|
btVector3 point3d;
|
2012-08-22 13:05:19 -07:00
|
|
|
btScalar margin;
|
2012-08-10 14:05:19 -07:00
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't add shape, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!shape)
|
|
|
|
{
|
|
|
|
ERR("Can't add shape, shape is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:05:25 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:05:19 -07:00
|
|
|
full_shape = new btConvexHullShape();
|
|
|
|
if (!full_shape)
|
2012-08-10 14:05:19 -07:00
|
|
|
{
|
|
|
|
ERR("Couldn't create a generic convex shape.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:05:25 -07:00
|
|
|
point = EINA_INLIST_CONTAINER_GET(points, EPhysics_Point);
|
|
|
|
max_x = min_x = point->x;
|
|
|
|
max_y = min_y = point->y;
|
2012-10-10 12:17:54 -07:00
|
|
|
max_z = min_z = point->z;
|
|
|
|
cm_x = cm_y = cm_z = 0;
|
2012-08-22 13:05:25 -07:00
|
|
|
|
|
|
|
/* 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;
|
2012-10-10 12:17:54 -07:00
|
|
|
if (point->z > max_z) max_z = point->z;
|
|
|
|
if (point->z < min_z) min_z = point->z;
|
2012-08-22 13:05:25 -07:00
|
|
|
|
|
|
|
cm_x += point->x;
|
|
|
|
cm_y += point->y;
|
2012-10-10 12:17:54 -07:00
|
|
|
cm_z += point->z;
|
2012-08-22 13:05:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
cm_x /= eina_inlist_count(points);
|
|
|
|
cm_y /= eina_inlist_count(points);
|
2012-10-10 12:17:54 -07:00
|
|
|
cm_z /= eina_inlist_count(points);
|
2012-08-22 13:05:25 -07:00
|
|
|
range_x = max_x - min_x;
|
|
|
|
range_y = max_y - min_y;
|
2012-10-10 12:17:54 -07:00
|
|
|
range_z = max_z - min_z;
|
2012-08-10 14:05:19 -07:00
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(points, point)
|
|
|
|
{
|
2012-10-10 12:17:54 -07:00
|
|
|
double x, y, z;
|
2012-08-22 13:05:25 -07:00
|
|
|
|
|
|
|
x = (point->x - cm_x) / range_x;
|
|
|
|
y = - (point->y - cm_y) / range_y;
|
2012-10-10 12:17:54 -07:00
|
|
|
z = (point->z - cm_z) / range_z;
|
2012-08-22 13:05:25 -07:00
|
|
|
|
2012-10-10 12:17:54 -07:00
|
|
|
point3d = btVector3(x, y, z);
|
2012-09-12 14:50:01 -07:00
|
|
|
vertexes.push_back(point3d);
|
2012-08-10 14:05:19 -07:00
|
|
|
}
|
|
|
|
|
2012-09-12 14:50:01 -07:00
|
|
|
/* Shrink convex shape to consider margin. Otherwise it would have a gap */
|
|
|
|
btGeometryUtil::getPlaneEquationsFromVertices(vertexes, planes);
|
|
|
|
array_size = planes.size();
|
|
|
|
for (i = 0; i < array_size; ++i)
|
|
|
|
planes[i][3] += full_shape->getMargin();
|
|
|
|
|
|
|
|
vertexes.clear();
|
|
|
|
btGeometryUtil::getVerticesFromPlaneEquations(planes, vertexes);
|
|
|
|
|
|
|
|
array_size = vertexes.size();
|
|
|
|
for (i = 0; i < array_size; ++i)
|
|
|
|
full_shape->addPoint(vertexes[i]);
|
|
|
|
|
2012-08-22 13:05:19 -07:00
|
|
|
hull = new btShapeHull(full_shape);
|
2012-08-22 13:05:25 -07:00
|
|
|
if (!hull)
|
|
|
|
{
|
|
|
|
delete full_shape;
|
|
|
|
ERR("Couldn't create a shape hull.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:05:19 -07:00
|
|
|
margin = full_shape->getMargin();
|
|
|
|
hull->buildHull(margin);
|
|
|
|
simplified_shape = new btConvexHullShape(&(hull->getVertexPointer()->getX()),
|
|
|
|
hull->numVertices());
|
2012-08-22 13:05:25 -07:00
|
|
|
delete hull;
|
|
|
|
delete full_shape;
|
|
|
|
if (!simplified_shape)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a simplified shape.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-08-22 13:05:19 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(world);
|
2012-10-04 15:40:16 -07:00
|
|
|
body = _ephysics_body_rigid_body_add(world,
|
|
|
|
(btCollisionShape *)simplified_shape,
|
|
|
|
"generic", (cm_x - min_x) / range_x,
|
2012-10-10 12:17:54 -07:00
|
|
|
1 - (cm_y - min_y) / range_y,
|
|
|
|
(cm_z - min_z) / range_z);
|
2012-11-09 10:53:04 -08:00
|
|
|
body->shape = EPHYSICS_BODY_SHAPE_CUSTOM;
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(world);
|
|
|
|
return body;
|
2012-08-10 14:05:19 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
void
|
|
|
|
ephysics_body_world_boundaries_resize(EPhysics_World *world)
|
|
|
|
{
|
2012-10-15 14:54:29 -07:00
|
|
|
Evas_Coord x, y, z, w, h, d;
|
|
|
|
EPhysics_Body *bound;
|
|
|
|
|
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, &d);
|
|
|
|
|
|
|
|
bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_BOTTOM);
|
|
|
|
if (bound)
|
|
|
|
ephysics_body_geometry_set(bound, x, y + h, z, w, 10, d);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_RIGHT);
|
|
|
|
if (bound)
|
|
|
|
ephysics_body_geometry_set(bound, x + w, y, z, 10, h, d);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_LEFT);
|
|
|
|
if (bound)
|
|
|
|
ephysics_body_geometry_set(bound, x - 10, y, z, 10, h, d);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_TOP);
|
|
|
|
if (bound)
|
|
|
|
ephysics_body_geometry_set(bound, x, y - 10, z, w, 10, d);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_FRONT);
|
|
|
|
if (bound)
|
|
|
|
ephysics_body_geometry_set(bound, x, y, z - 10, w, h, 10);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_BACK);
|
|
|
|
if (bound)
|
|
|
|
ephysics_body_geometry_set(bound, x, y, z + d, w, h, 10);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static EPhysics_Body *
|
2012-10-15 14:54:29 -07:00
|
|
|
_ephysics_body_boundary_add(EPhysics_World *world, EPhysics_World_Boundary boundary, Evas_Coord x, Evas_Coord y, Evas_Coord z, Evas_Coord w, Evas_Coord h, Evas_Coord d)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body *body;
|
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't add boundary, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
body = ephysics_world_boundary_get(world, boundary);
|
|
|
|
if (body)
|
|
|
|
return body;
|
|
|
|
|
|
|
|
body = ephysics_body_box_add(world);
|
|
|
|
if (!body)
|
|
|
|
return NULL;
|
|
|
|
|
2012-11-09 10:58:51 -08:00
|
|
|
body->boundary = EINA_TRUE;
|
2012-06-26 15:36:12 -07:00
|
|
|
ephysics_body_mass_set(body, 0);
|
|
|
|
ephysics_world_boundary_set(world, boundary, body);
|
2012-11-28 13:47:58 -08:00
|
|
|
|
|
|
|
if ((w <= 0) || (h <= 0) || (d <= 0))
|
|
|
|
INF("Boundary added with default geometry. Render geometry not set yet");
|
|
|
|
else
|
|
|
|
ephysics_body_geometry_set(body, x, y, z, w, h, d);
|
2012-10-15 14:54:14 -07:00
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
2012-10-15 14:54:14 -07:00
|
|
|
ephysics_body_top_boundary_add(EPhysics_World *world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-10-15 14:54:29 -07:00
|
|
|
Evas_Coord x, y, z, w, d;
|
2012-10-04 15:38:06 -07:00
|
|
|
EPhysics_Body *body;
|
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &z, &w, NULL, &d);
|
2012-10-04 15:38:06 -07:00
|
|
|
body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_TOP,
|
2012-10-15 14:54:29 -07:00
|
|
|
x, y - 10, z, w, 10, d);
|
2012-10-04 15:38:06 -07:00
|
|
|
return body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
2012-10-15 14:54:14 -07:00
|
|
|
ephysics_body_bottom_boundary_add(EPhysics_World *world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-10-15 14:54:29 -07:00
|
|
|
Evas_Coord x, y, z, w, h, d;
|
2012-10-04 15:38:06 -07:00
|
|
|
EPhysics_Body *body;
|
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, &d);
|
2012-10-04 15:38:06 -07:00
|
|
|
body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_BOTTOM,
|
2012-10-15 14:54:29 -07:00
|
|
|
x, y + h, z, w, 10, d);
|
2012-10-04 15:38:06 -07:00
|
|
|
return body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
2012-10-15 14:54:14 -07:00
|
|
|
ephysics_body_left_boundary_add(EPhysics_World *world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-10-15 14:54:29 -07:00
|
|
|
Evas_Coord x, y, z, h, d;
|
2012-10-04 15:38:06 -07:00
|
|
|
EPhysics_Body *body;
|
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &z, NULL, &h, &d);
|
2012-10-04 15:38:06 -07:00
|
|
|
body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_LEFT,
|
2012-10-15 14:54:29 -07:00
|
|
|
x - 10, y, z, 10, h, d);
|
2012-10-04 15:38:06 -07:00
|
|
|
return body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
2012-10-15 14:54:14 -07:00
|
|
|
ephysics_body_right_boundary_add(EPhysics_World *world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-10-15 14:54:29 -07:00
|
|
|
Evas_Coord x, y, z, w, h, d;
|
2012-10-04 15:38:06 -07:00
|
|
|
EPhysics_Body *body;
|
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, &d);
|
2012-10-04 15:38:06 -07:00
|
|
|
body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_RIGHT,
|
2012-10-15 14:54:29 -07:00
|
|
|
x + w, y, z, 10, h, d);
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_front_boundary_add(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
Evas_Coord x, y, z, w, h;
|
|
|
|
EPhysics_Body *body;
|
|
|
|
|
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, NULL);
|
|
|
|
body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_FRONT,
|
|
|
|
x, y, z - 10, w, h, 10);
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_back_boundary_add(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
Evas_Coord x, y, z, w, h, d;
|
|
|
|
EPhysics_Body *body;
|
|
|
|
|
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, &d);
|
|
|
|
body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_BACK,
|
|
|
|
x, y, z + d, w, h, 10);
|
2012-10-04 15:38:06 -07:00
|
|
|
return body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ephysics_orphan_body_del(EPhysics_Body *body)
|
|
|
|
{
|
2012-09-04 15:42:20 -07:00
|
|
|
_ephysics_body_event_callback_call(body, EPHYSICS_CALLBACK_BODY_DEL,
|
|
|
|
(void *) body->evas_obj);
|
2012-06-26 15:36:12 -07:00
|
|
|
_ephysics_body_del(body);
|
2012-08-10 14:03:39 -07:00
|
|
|
INF("Body %p deleted.", body);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_del(EPhysics_Body *body)
|
|
|
|
{
|
2012-10-16 16:12:59 -07:00
|
|
|
EPhysics_World *world;
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't delete body, it wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:03:39 -07:00
|
|
|
if (body->deleted) return;
|
2012-10-16 16:12:59 -07:00
|
|
|
|
|
|
|
world = body->world;
|
|
|
|
ephysics_world_lock_take(world);
|
2012-08-10 14:03:39 -07:00
|
|
|
body->deleted = EINA_TRUE;
|
2012-10-16 16:12:59 -07:00
|
|
|
ephysics_world_body_del(world, body);
|
|
|
|
ephysics_world_lock_release(world);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-10-31 14:02:50 -07:00
|
|
|
EAPI void
|
2012-06-26 15:36:12 -07:00
|
|
|
ephysics_body_evas_object_set(EPhysics_Body *body, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
|
|
|
|
{
|
2012-11-09 10:52:35 -08:00
|
|
|
int obj_x, obj_y, obj_w, obj_h, bz, bd;
|
2012-10-10 12:17:01 -07:00
|
|
|
double rate;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, the last wasn't provided.");
|
2012-10-31 14:02:50 -07:00
|
|
|
return;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!evas_obj)
|
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, the first wasn't provided.");
|
2012-10-31 14:02:50 -07:00
|
|
|
return;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (body->evas_obj)
|
2012-08-13 15:24:47 -07:00
|
|
|
{
|
2012-10-31 14:02:50 -07:00
|
|
|
evas_object_map_enable_set(body->evas_obj, EINA_FALSE);
|
2012-08-13 15:24:47 -07:00
|
|
|
evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_evas_obj_del_cb);
|
|
|
|
evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb);
|
2012-11-23 13:49:57 -08:00
|
|
|
if (body->default_face)
|
2012-11-23 13:49:44 -08:00
|
|
|
{
|
|
|
|
evas_object_event_callback_del(body->evas_obj,
|
|
|
|
EVAS_CALLBACK_RESTACK,
|
|
|
|
_ephysics_body_soft_body_evas_restack_cb);
|
2012-11-23 13:49:57 -08:00
|
|
|
_ephysics_body_soft_body_slices_clean(body->default_face->slices);
|
2012-11-23 13:49:44 -08:00
|
|
|
}
|
2012-08-13 15:24:47 -07:00
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
body->evas_obj = evas_obj;
|
2012-10-31 14:02:50 -07:00
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_evas_obj_del_cb, body);
|
2012-10-25 14:54:14 -07:00
|
|
|
|
|
|
|
if (body->soft_body)
|
2012-11-23 13:49:44 -08:00
|
|
|
{
|
2012-12-10 09:15:05 -08:00
|
|
|
evas_object_geometry_get(body->evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
|
|
|
|
if (!obj_w && !obj_h) evas_object_resize(body->evas_obj, 1, 1);
|
|
|
|
|
2012-11-23 13:49:44 -08:00
|
|
|
evas_object_event_callback_add(body->evas_obj, EVAS_CALLBACK_RESTACK,
|
|
|
|
_ephysics_body_soft_body_evas_restack_cb, body);
|
2012-11-23 13:50:02 -08:00
|
|
|
_ephysics_body_soft_body_slices_init(body, body->evas_obj,
|
|
|
|
body->default_face->slices);
|
2012-11-23 13:49:44 -08:00
|
|
|
}
|
2012-10-25 14:54:14 -07:00
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!use_obj_pos)
|
2012-10-31 14:02:50 -07:00
|
|
|
return;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-10 12:17:01 -07:00
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-10-31 14:02:50 -07:00
|
|
|
evas_object_geometry_get(body->evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
|
2012-11-09 10:52:35 -08:00
|
|
|
ephysics_body_geometry_get(body, NULL, NULL, &bz, NULL, NULL, &bd);
|
2012-10-31 14:02:50 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-11-09 10:52:35 -08:00
|
|
|
_ephysics_body_geometry_set(body, obj_x, obj_y, bz, obj_w, obj_h, bd, rate);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-10-04 15:40:07 -07:00
|
|
|
evas_object_event_callback_add(body->evas_obj, EVAS_CALLBACK_RESIZE,
|
2012-10-04 15:38:06 -07:00
|
|
|
_ephysics_body_evas_obj_resize_cb, body);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Evas_Object *
|
|
|
|
ephysics_body_evas_object_unset(EPhysics_Body *body)
|
|
|
|
{
|
2012-10-31 14:02:50 -07:00
|
|
|
Evas_Object *obj;
|
2012-10-09 12:59:53 -07:00
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't unset evas object from body, it wasn't provided.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = body->evas_obj;
|
|
|
|
body->evas_obj = NULL;
|
|
|
|
|
|
|
|
if (obj)
|
2012-08-13 15:24:47 -07:00
|
|
|
{
|
|
|
|
evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_evas_obj_del_cb);
|
|
|
|
evas_object_event_callback_del(obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb);
|
2012-10-30 11:31:45 -07:00
|
|
|
evas_object_map_enable_set(obj, EINA_FALSE);
|
2012-08-13 15:24:47 -07:00
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-11-23 13:49:57 -08:00
|
|
|
if (body->default_face)
|
2012-11-23 13:49:44 -08:00
|
|
|
{
|
|
|
|
evas_object_event_callback_del(body->evas_obj,
|
|
|
|
EVAS_CALLBACK_RESTACK,
|
|
|
|
_ephysics_body_soft_body_evas_restack_cb);
|
2012-11-23 13:49:57 -08:00
|
|
|
_ephysics_body_soft_body_slices_clean(body->default_face->slices);
|
2012-11-23 13:49:44 -08:00
|
|
|
}
|
2012-10-09 12:59:53 -07:00
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Evas_Object *
|
|
|
|
ephysics_body_evas_object_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get evas object from body, it wasn't provided.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->evas_obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-10 12:17:01 -07:00
|
|
|
ephysics_body_geometry_set(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord z, Evas_Coord w, Evas_Coord h, Evas_Coord d)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
2012-08-20 15:10:52 -07:00
|
|
|
ERR("Can't set body geometry, body is null.");
|
2012-06-26 15:36:12 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-11-28 13:47:47 -08:00
|
|
|
INF("Body: %p geometry set to x=%i y=%i z=%i w=%i h=%i d=%i.",
|
|
|
|
body, x, y, z, w, h, d);
|
|
|
|
|
2012-10-10 12:17:01 -07:00
|
|
|
if ((w <= 0) || (h <= 0) || (d <= 0))
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-10-10 12:17:01 -07:00
|
|
|
ERR("Width, height and depth must to be a non-null, positive value.");
|
2012-06-26 15:36:12 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-10 12:17:01 -07:00
|
|
|
_ephysics_body_geometry_set(body, x, y, z, w, h, d,
|
2012-08-16 14:35:04 -07:00
|
|
|
ephysics_world_rate_get(body->world));
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-20 15:10:52 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:01 -07:00
|
|
|
ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h, Evas_Coord d)
|
2012-08-20 15:10:52 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body size, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-10 12:17:01 -07:00
|
|
|
if ((w <= 0) || (h <= 0) || (d <= 0))
|
2012-08-20 15:10:52 -07:00
|
|
|
{
|
2012-10-10 12:17:01 -07:00
|
|
|
ERR("Width, height and depth must to be a non-null, positive value.");
|
2012-08-20 15:10:52 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-10 12:17:01 -07:00
|
|
|
_ephysics_body_resize(body, w, h, d);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-08-20 15:10:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-10 12:17:01 -07:00
|
|
|
ephysics_body_move(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord z)
|
2012-08-20 15:10:52 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body position, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-10 12:17:01 -07:00
|
|
|
_ephysics_body_move(body, x, y, z);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-08-20 15:10:52 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:01 -07:00
|
|
|
ephysics_body_geometry_get(const EPhysics_Body *body, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z, Evas_Coord *w, Evas_Coord *h, Evas_Coord *d)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
btTransform trans;
|
2012-10-04 15:40:16 -07:00
|
|
|
btVector3 scale;
|
2012-06-26 15:36:12 -07:00
|
|
|
double rate;
|
|
|
|
int wy, height;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get body position, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
trans = _ephysics_body_transform_get(body);
|
2012-10-25 14:54:06 -07:00
|
|
|
scale = body->scale;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL,
|
|
|
|
NULL, &height, NULL);
|
2012-06-26 15:36:12 -07:00
|
|
|
height += wy;
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
if (x) *x = round((trans.getOrigin().getX() - scale.x() / 2) * rate);
|
|
|
|
if (y) *y = height - round((trans.getOrigin().getY() + scale.y() / 2)
|
2012-06-26 15:36:12 -07:00
|
|
|
* rate);
|
2012-10-10 12:17:01 -07:00
|
|
|
if (z) *z = round((trans.getOrigin().getZ() - scale.z() / 2) * rate);
|
2012-11-09 10:52:22 -08:00
|
|
|
if (w) *w = body->size.w;
|
|
|
|
if (h) *h = body->size.h;
|
|
|
|
if (d) *d = body->size.d;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_mass_set(EPhysics_Body *body, double mass)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body mass, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:39:10 -07:00
|
|
|
if (mass < 0)
|
|
|
|
{
|
|
|
|
ERR("Can't set body's mass, it must to be non-negative.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-04 15:39:42 -07:00
|
|
|
body->material = EPHYSICS_BODY_MATERIAL_CUSTOM;
|
2012-10-04 15:39:29 -07:00
|
|
|
body->density = 0;
|
2012-10-04 15:38:06 -07:00
|
|
|
_ephysics_body_mass_set(body, mass);
|
|
|
|
ephysics_world_lock_release(body->world);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_body_mass_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get body mass, body is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-27 07:47:23 -07:00
|
|
|
return body->mass;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 15:04:37 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:29 -07:00
|
|
|
ephysics_body_linear_velocity_set(EPhysics_Body *body, double x, double y, double z)
|
2012-07-04 15:04:37 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body linear velocity, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-10 12:17:29 -07:00
|
|
|
_ephysics_body_linear_velocity_set(body, x, y, z,
|
2012-08-16 14:35:04 -07:00
|
|
|
ephysics_world_rate_get(body->world));
|
2012-10-10 12:17:29 -07:00
|
|
|
DBG("Linear velocity of body %p set to (%lf, %lf, %lf).", body, x, y, z);
|
2012-07-04 15:04:37 -07:00
|
|
|
}
|
|
|
|
|
2012-12-05 05:50:08 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_linear_velocity_get(const EPhysics_Body *body, double *x, double *y, double *z, double rate)
|
|
|
|
{
|
|
|
|
btVector3 total_velocity = btVector3(0, 0, 0);
|
|
|
|
int nodes_size = body->soft_body->m_nodes.size();
|
|
|
|
|
|
|
|
for (int i = 0; i < nodes_size; i++)
|
|
|
|
total_velocity += body->soft_body->m_nodes[i].m_v;
|
|
|
|
|
|
|
|
total_velocity /= nodes_size;
|
|
|
|
if (x) *x = total_velocity.getX() * rate;
|
|
|
|
if (y) *y = -total_velocity.getY() * rate;
|
|
|
|
if (z) *z = total_velocity.getZ() * rate;
|
|
|
|
}
|
|
|
|
|
2012-07-02 19:15:28 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:29 -07:00
|
|
|
ephysics_body_linear_velocity_get(const EPhysics_Body *body, double *x, double *y, double *z)
|
2012-07-02 19:15:28 -07:00
|
|
|
{
|
2012-07-02 19:18:14 -07:00
|
|
|
double rate;
|
2012-07-04 15:04:37 -07:00
|
|
|
|
2012-07-02 19:18:14 -07:00
|
|
|
if (!body)
|
2012-07-02 19:15:28 -07:00
|
|
|
{
|
2012-07-04 15:04:37 -07:00
|
|
|
ERR("Can't get linear velocity, body is null.");
|
2012-07-02 19:15:28 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-02 19:18:14 -07:00
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-12-05 05:50:08 -08:00
|
|
|
if (body->rigid_body)
|
|
|
|
{
|
|
|
|
if (x) *x = body->rigid_body->getLinearVelocity().getX() * rate;
|
|
|
|
if (y) *y = -body->rigid_body->getLinearVelocity().getY() * rate;
|
|
|
|
if (z) *z = body->rigid_body->getLinearVelocity().getZ() * rate;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_ephysics_body_soft_body_linear_velocity_get(body, x, y, z, rate);
|
2012-07-02 19:15:28 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 15:04:37 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:29 -07:00
|
|
|
ephysics_body_angular_velocity_set(EPhysics_Body *body, double x, double y, double z)
|
2012-07-04 15:04:37 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set angular velocity, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-12-05 05:50:08 -08:00
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
{
|
|
|
|
ERR("Can't set angular velocity, not implemented for cloth.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-12-05 05:50:08 -08:00
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
2012-10-10 12:17:29 -07:00
|
|
|
body->rigid_body->setAngularVelocity(btVector3(-x / RAD_TO_DEG,
|
|
|
|
-y / RAD_TO_DEG,
|
|
|
|
-z/RAD_TO_DEG));
|
2012-12-05 05:50:08 -08:00
|
|
|
|
2012-10-10 12:17:29 -07:00
|
|
|
DBG("Angular velocity of body %p set to (%lf, %lf, %lf).", body, x, y, z);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-07-04 15:04:37 -07:00
|
|
|
}
|
|
|
|
|
2012-10-10 12:17:29 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_angular_velocity_get(const EPhysics_Body *body, double *x, double *y, double *z)
|
2012-07-02 19:15:28 -07:00
|
|
|
{
|
2012-07-02 19:18:14 -07:00
|
|
|
if (!body)
|
2012-07-02 19:15:28 -07:00
|
|
|
{
|
2012-07-04 15:04:37 -07:00
|
|
|
ERR("Can't get angular velocity, body is null.");
|
2012-10-10 12:17:29 -07:00
|
|
|
return;
|
2012-07-02 19:15:28 -07:00
|
|
|
}
|
|
|
|
|
2012-12-05 05:50:08 -08:00
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
{
|
|
|
|
ERR("Can't get angular velocity, not implemented for cloth.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-10 12:17:29 -07:00
|
|
|
if (x) *x = -body->rigid_body->getAngularVelocity().getX() * RAD_TO_DEG;
|
|
|
|
if (y) *y = -body->rigid_body->getAngularVelocity().getY() * RAD_TO_DEG;
|
|
|
|
if (z) *z = -body->rigid_body->getAngularVelocity().getZ() * RAD_TO_DEG;
|
2012-07-02 19:15:28 -07:00
|
|
|
}
|
|
|
|
|
2012-07-27 07:48:59 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_sleeping_threshold_set(EPhysics_Body *body, double linear_threshold, double angular_threshold)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set sleeping thresholds, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-08-16 14:35:04 -07:00
|
|
|
_ephysics_body_sleeping_threshold_set(body, linear_threshold,
|
|
|
|
angular_threshold,
|
|
|
|
ephysics_world_rate_get(body->world));
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-07-27 07:48:59 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:03:57 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_sleeping_threshold_get(const EPhysics_Body *body, double *linear_threshold, double *angular_threshold)
|
2012-07-27 07:48:59 -07:00
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get linear sleeping threshold, body is null.");
|
2012-08-10 14:03:57 -07:00
|
|
|
return;
|
2012-07-27 07:48:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-08-10 14:03:57 -07:00
|
|
|
if (linear_threshold)
|
|
|
|
*linear_threshold = body->rigid_body->getLinearSleepingThreshold() * rate;
|
|
|
|
if (angular_threshold)
|
|
|
|
*angular_threshold = body->rigid_body->getAngularSleepingThreshold() *
|
|
|
|
RAD_TO_DEG;
|
2012-07-27 07:48:59 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 15:04:37 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_stop(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't stop a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-12-05 05:50:08 -08:00
|
|
|
if (body->rigid_body)
|
|
|
|
{
|
|
|
|
body->rigid_body->setLinearVelocity(btVector3(0, 0, 0));
|
|
|
|
body->rigid_body->setAngularVelocity(btVector3(0, 0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->soft_body)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
|
|
|
|
{
|
|
|
|
body->soft_body->m_nodes[i].m_v *= 0;
|
|
|
|
body->soft_body->m_nodes[i].m_f *= 0;
|
|
|
|
}
|
|
|
|
}
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-07-04 15:04:37 -07:00
|
|
|
|
|
|
|
DBG("Body %p stopped", body);
|
|
|
|
}
|
|
|
|
|
2012-07-05 15:52:53 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_damping_set(EPhysics_Body *body, double linear_damping, double angular_damping)
|
|
|
|
{
|
2012-10-31 14:03:36 -07:00
|
|
|
if (!body)
|
2012-07-05 15:52:53 -07:00
|
|
|
{
|
|
|
|
ERR("Can't set body damping, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-31 14:03:36 -07:00
|
|
|
body->rigid_body->setDamping(btScalar(linear_damping),
|
|
|
|
btScalar(angular_damping));
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-07-05 15:52:53 -07:00
|
|
|
}
|
|
|
|
|
2012-07-05 15:53:56 -07:00
|
|
|
EAPI void
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_body_damping_get(const EPhysics_Body *body, double *linear_damping, double *angular_damping)
|
2012-07-05 15:53:56 -07:00
|
|
|
{
|
2012-10-31 14:03:36 -07:00
|
|
|
if (!body)
|
2012-07-05 15:53:56 -07:00
|
|
|
{
|
|
|
|
ERR("Can't get damping, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-31 14:03:36 -07:00
|
|
|
if (linear_damping) *linear_damping = body->rigid_body->getLinearDamping();
|
|
|
|
if (angular_damping) *angular_damping =
|
|
|
|
body->rigid_body->getAngularDamping();
|
2012-07-05 15:53:56 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_evas_object_update(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't update a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_body_evas_object_default_update(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-07-02 19:09:34 -07:00
|
|
|
ephysics_body_event_callback_add(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func, const void *data)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body_Callback *cb;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body event callback, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!func)
|
|
|
|
{
|
|
|
|
ERR("Can't set body event callback, function is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-02 19:09:34 -07:00
|
|
|
if ((type < 0) || (type >= EPHYSICS_CALLBACK_BODY_LAST))
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
ERR("Can't set body event callback, callback type is wrong.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:42 -07:00
|
|
|
cb = (EPhysics_Body_Callback *)calloc(1, sizeof(EPhysics_Body_Callback));
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!cb)
|
|
|
|
{
|
|
|
|
ERR("Can't set body event callback, can't create cb instance.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cb->func = func;
|
|
|
|
cb->type = type;
|
|
|
|
cb->data = (void *)data;
|
|
|
|
|
|
|
|
body->callbacks = eina_inlist_append(body->callbacks, EINA_INLIST_GET(cb));
|
2012-10-31 14:02:43 -07:00
|
|
|
if (type == EPHYSICS_CALLBACK_BODY_COLLISION)
|
|
|
|
body->collision_cb++;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
2012-07-02 19:09:34 -07:00
|
|
|
ephysics_body_event_callback_del(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body_Callback *cb;
|
2012-08-10 14:04:08 -07:00
|
|
|
void *cb_data = NULL;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't delete body event callback, body is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(body->callbacks, cb)
|
|
|
|
{
|
2012-08-10 14:04:08 -07:00
|
|
|
if ((cb->type != type) || (cb->func != func))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cb_data = cb->data;
|
|
|
|
_ephysics_body_event_callback_del(body, cb);
|
2012-10-31 14:02:43 -07:00
|
|
|
if (type == EPHYSICS_CALLBACK_BODY_COLLISION)
|
|
|
|
body->collision_cb--;
|
2012-08-10 14:04:08 -07:00
|
|
|
break;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
return cb_data;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-02 19:09:21 -07:00
|
|
|
EAPI void *
|
2012-07-02 19:09:34 -07:00
|
|
|
ephysics_body_event_callback_del_full(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func, void *data)
|
2012-07-02 19:09:21 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body_Callback *cb;
|
2012-08-10 14:04:08 -07:00
|
|
|
void *cb_data = NULL;
|
2012-07-02 19:09:21 -07:00
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't delete body event callback, body is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(body->callbacks, cb)
|
|
|
|
{
|
2012-08-10 14:04:08 -07:00
|
|
|
if ((cb->type != type) || (cb->func != func) || (cb->data != data))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cb_data = cb->data;
|
|
|
|
_ephysics_body_event_callback_del(body, cb);
|
|
|
|
break;
|
2012-07-02 19:09:21 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
return cb_data;
|
2012-07-02 19:09:21 -07:00
|
|
|
}
|
|
|
|
|
2012-10-04 15:39:42 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_restitution_set(EPhysics_Body *body, double restitution)
|
|
|
|
{
|
2012-12-03 11:47:18 -08:00
|
|
|
DBG("Body %p restitution set to %lf", body, restitution);
|
2012-10-04 15:40:16 -07:00
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
body->rigid_body->setRestitution(btScalar(restitution));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->soft_body->setRestitution(btScalar(restitution));
|
2012-10-04 15:39:42 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_restitution_set(EPhysics_Body *body, double restitution)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body restitution, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-04 15:39:42 -07:00
|
|
|
body->material = EPHYSICS_BODY_MATERIAL_CUSTOM;
|
|
|
|
_ephysics_body_restitution_set(body, restitution);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_body_restitution_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get body restitution, body is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
return body->rigid_body->getRestitution();
|
|
|
|
|
|
|
|
return body->soft_body->getRestitution();
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-10-04 15:39:42 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_friction_set(EPhysics_Body *body, double friction)
|
|
|
|
{
|
2012-12-03 11:47:18 -08:00
|
|
|
DBG("Body %p friction set to %lf", body, friction);
|
2012-10-04 15:40:16 -07:00
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
{
|
|
|
|
body->rigid_body->setFriction(btScalar(friction));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->soft_body->setFriction(btScalar(friction));
|
2012-10-04 15:39:42 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_friction_set(EPhysics_Body *body, double friction)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body friction, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-04 15:39:42 -07:00
|
|
|
body->material = EPHYSICS_BODY_MATERIAL_CUSTOM;
|
|
|
|
_ephysics_body_friction_set(body, friction);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_body_friction_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get body friction, body is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_RIGID)
|
|
|
|
return body->rigid_body->getFriction();
|
|
|
|
|
|
|
|
return body->soft_body->getFriction();
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_World *
|
|
|
|
ephysics_body_world_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get the world a null body belongs to.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->world;
|
|
|
|
}
|
|
|
|
|
2012-10-25 14:53:51 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_central_impulse_apply(EPhysics_Body *body, btVector3 impulse)
|
|
|
|
{
|
|
|
|
btSoftBody::Face *face;
|
|
|
|
|
|
|
|
for (int m = 0; m < body->soft_body->m_faces.size(); m++)
|
|
|
|
{
|
|
|
|
face = &body->soft_body->m_faces[m];
|
|
|
|
for (int n = 0; n < 3; n++)
|
|
|
|
face->m_n[n]->m_v += impulse * face->m_n[n]->m_im;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:36 -07:00
|
|
|
ephysics_body_central_impulse_apply(EPhysics_Body *body, double x, double y, double z)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-20 15:12:14 -07:00
|
|
|
double rate;
|
2012-10-25 14:53:51 -07:00
|
|
|
btVector3 impulse;
|
2012-08-20 15:12:14 -07:00
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply impulse to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:12:14 -07:00
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-04 15:40:16 -07:00
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
2012-10-25 14:53:51 -07:00
|
|
|
|
|
|
|
impulse = btVector3(x / rate, - y / rate, z / rate);
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
_ephysics_body_soft_body_central_impulse_apply(body, impulse);
|
|
|
|
else
|
|
|
|
body->rigid_body->applyCentralImpulse(impulse);
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-20 15:14:25 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:36 -07:00
|
|
|
ephysics_body_impulse_apply(EPhysics_Body *body, double x, double y, double z, Evas_Coord pos_x, Evas_Coord pos_y, Evas_Coord pos_z)
|
2012-08-20 15:14:25 -07:00
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply impulse to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-04 15:40:16 -07:00
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
2012-10-10 12:17:36 -07:00
|
|
|
body->rigid_body->applyImpulse(btVector3(x / rate, - y / rate, z / rate),
|
2012-08-20 15:14:25 -07:00
|
|
|
btVector3((double) pos_x / rate,
|
2012-10-10 12:17:36 -07:00
|
|
|
(double) pos_y / rate,
|
|
|
|
(double) pos_z / rate));
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-08-20 15:14:25 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 15:05:52 -07:00
|
|
|
EAPI void
|
2012-10-10 12:16:43 -07:00
|
|
|
ephysics_body_linear_movement_enable_set(EPhysics_Body *body, Eina_Bool enable_x, Eina_Bool enable_y, Eina_Bool enable_z)
|
2012-07-04 15:05:52 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set linear factor on a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-10 12:16:43 -07:00
|
|
|
body->rigid_body->setLinearFactor(btVector3(!!enable_x, !!enable_y,
|
|
|
|
!!enable_z));
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-07-04 15:05:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-10 12:16:43 -07:00
|
|
|
ephysics_body_linear_movement_enable_get(const EPhysics_Body *body, Eina_Bool *enable_x, Eina_Bool *enable_y, Eina_Bool *enable_z)
|
2012-07-04 15:05:52 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't check if linear factor is enabled, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enable_x) *enable_x = !!body->rigid_body->getLinearFactor().x();
|
|
|
|
if (enable_y) *enable_y = !!body->rigid_body->getLinearFactor().y();
|
2012-10-10 12:16:43 -07:00
|
|
|
if (enable_z) *enable_z = !!body->rigid_body->getLinearFactor().z();
|
2012-07-04 15:05:52 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:36 -07:00
|
|
|
ephysics_body_torque_impulse_apply(EPhysics_Body *body, double pitch, double yaw, double roll)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply torque impulse to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-04 15:40:16 -07:00
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
2012-10-10 12:17:36 -07:00
|
|
|
body->rigid_body->applyTorqueImpulse(btVector3(-pitch, -yaw, -roll));
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-10 12:16:48 -07:00
|
|
|
ephysics_body_angular_movement_enable_set(EPhysics_Body *body, Eina_Bool enable_x, Eina_Bool enable_y, Eina_Bool enable_z)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set rotation on a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-10 12:16:48 -07:00
|
|
|
body->rigid_body->setAngularFactor(btVector3(!!enable_x, !!enable_y,
|
|
|
|
!!enable_z));
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-10-10 12:16:48 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_angular_movement_enable_get(const EPhysics_Body *body, Eina_Bool *enable_x, Eina_Bool *enable_y, Eina_Bool *enable_z)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't check if rotation is enabled, body is null.");
|
2012-10-10 12:16:48 -07:00
|
|
|
return;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-10-10 12:16:48 -07:00
|
|
|
if (enable_x) *enable_x = !!body->rigid_body->getAngularFactor().x();
|
|
|
|
if (enable_y) *enable_y = !!body->rigid_body->getAngularFactor().y();
|
|
|
|
if (enable_z) *enable_z = !!body->rigid_body->getAngularFactor().z();
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-11-13 14:18:16 -08:00
|
|
|
EAPI EPhysics_Quaternion *
|
2012-11-14 12:01:20 -08:00
|
|
|
ephysics_body_rotation_get(const EPhysics_Body *body, EPhysics_Quaternion *rotation)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-11-13 14:18:16 -08:00
|
|
|
EPhysics_Quaternion *quat;
|
2012-06-26 15:36:12 -07:00
|
|
|
btTransform trans;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get rotation, body is null.");
|
2012-11-13 14:18:16 -08:00
|
|
|
return NULL;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-11-14 12:01:20 -08:00
|
|
|
if (!rotation)
|
|
|
|
{
|
|
|
|
quat = ephysics_quaternion_new();
|
|
|
|
if (!quat) return NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
quat = rotation;
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
trans = _ephysics_body_transform_get(body);
|
2012-11-14 12:01:20 -08:00
|
|
|
quat->x = trans.getRotation().x();
|
|
|
|
quat->y = trans.getRotation().y();
|
|
|
|
quat->z = trans.getRotation().z();
|
|
|
|
quat->w = trans.getRotation().getW();
|
|
|
|
|
2012-11-13 14:18:16 -08:00
|
|
|
return quat;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-12-03 13:28:52 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_soft_body_rotation_set(EPhysics_Body *body, btTransform trans)
|
|
|
|
{
|
|
|
|
btSoftBody::Node *node;
|
|
|
|
const btScalar margin= body->soft_body->getCollisionShape()->getMargin();
|
|
|
|
ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
|
|
|
|
|
|
|
|
for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
|
|
|
|
{
|
|
|
|
node = &body->soft_body->m_nodes[i];
|
|
|
|
node->m_n = (trans.getBasis() * btVector3(1, 1, 1));
|
|
|
|
vol = btDbvtVolume::FromCR(node->m_x, margin);
|
|
|
|
|
|
|
|
body->soft_body->m_ndbvt.update(node->m_leaf, vol);
|
|
|
|
}
|
|
|
|
|
|
|
|
body->soft_body->updateNormals();
|
|
|
|
body->soft_body->updateBounds();
|
|
|
|
body->soft_body->updateConstants();
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:14:43 -07:00
|
|
|
EAPI void
|
2012-11-13 14:18:16 -08:00
|
|
|
ephysics_body_rotation_set(EPhysics_Body *body, EPhysics_Quaternion *quat)
|
2012-08-20 15:14:43 -07:00
|
|
|
{
|
2012-11-13 14:18:16 -08:00
|
|
|
btQuaternion bt_quat;
|
2012-08-20 15:14:43 -07:00
|
|
|
btTransform trans;
|
2012-11-13 14:18:16 -08:00
|
|
|
double x, y, z, w;
|
2012-08-20 15:14:43 -07:00
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set rotation, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-11-13 14:18:16 -08:00
|
|
|
if (!quat)
|
|
|
|
{
|
|
|
|
ERR("Can't set rotation, quaternion is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ephysics_quaternion_get(quat, &x, &y, &z, &w);
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-10-04 15:40:16 -07:00
|
|
|
ephysics_body_activate(body, EINA_TRUE);
|
|
|
|
|
2012-11-13 14:18:16 -08:00
|
|
|
bt_quat = btQuaternion(x, y, z, w);
|
2012-12-03 13:28:52 -08:00
|
|
|
trans = _ephysics_body_transform_get(body);
|
|
|
|
trans.setRotation(bt_quat);
|
2012-08-22 13:04:39 -07:00
|
|
|
|
|
|
|
if (body->soft_body)
|
2012-12-03 13:28:52 -08:00
|
|
|
_ephysics_body_soft_body_rotation_set(body, trans);
|
2012-10-30 11:31:38 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
body->rigid_body->proceedToTransform(trans);
|
|
|
|
body->rigid_body->getMotionState()->setWorldTransform(trans);
|
|
|
|
}
|
2012-08-20 15:14:43 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-10-15 14:53:56 -07:00
|
|
|
}
|
|
|
|
|
2012-07-27 07:47:46 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_data_set(EPhysics_Body *body, void *data)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set data, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->data = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
|
|
|
ephysics_body_data_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get data, body is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->data;
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:15:52 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:49 -07:00
|
|
|
ephysics_body_central_force_apply(EPhysics_Body *body, double x, double y, double z)
|
2012-08-20 15:15:52 -07:00
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply force to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-08-20 15:15:52 -07:00
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
ephysics_body_forces_apply(body);
|
2012-10-10 12:17:49 -07:00
|
|
|
body->rigid_body->applyCentralForce(btVector3(x / rate, - y / rate,
|
|
|
|
z / rate));
|
2012-08-20 15:15:52 -07:00
|
|
|
_ephysics_body_forces_update(body);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-08-20 15:15:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-10 12:17:49 -07:00
|
|
|
ephysics_body_force_apply(EPhysics_Body *body, double x, double y, double z, Evas_Coord pos_x, Evas_Coord pos_y, Evas_Coord pos_z)
|
2012-08-20 15:15:52 -07:00
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply force to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-08-20 15:15:52 -07:00
|
|
|
ephysics_body_forces_apply(body);
|
2012-10-10 12:17:49 -07:00
|
|
|
body->rigid_body->applyForce(btVector3(x / rate, - y / rate, z / rate),
|
2012-08-20 15:15:52 -07:00
|
|
|
btVector3((double) pos_x / rate,
|
2012-10-10 12:17:49 -07:00
|
|
|
(double) pos_y / rate,
|
|
|
|
(double) pos_z / rate));
|
2012-08-20 15:15:52 -07:00
|
|
|
_ephysics_body_forces_update(body);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-08-20 15:15:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-10 12:17:49 -07:00
|
|
|
ephysics_body_torque_apply(EPhysics_Body *body, double torque_x, double torque_y, double torque_z)
|
2012-08-20 15:15:52 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply force to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
2012-08-20 15:15:52 -07:00
|
|
|
ephysics_body_forces_apply(body);
|
2012-10-10 12:17:49 -07:00
|
|
|
body->rigid_body->applyTorque(btVector3(-torque_x, -torque_y, -torque_z));
|
2012-08-20 15:15:52 -07:00
|
|
|
_ephysics_body_forces_update(body);
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_lock_release(body->world);
|
2012-08-20 15:15:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-10 12:17:49 -07:00
|
|
|
ephysics_body_forces_get(const EPhysics_Body *body, double *x, double *y, double *z)
|
2012-08-20 15:15:52 -07:00
|
|
|
{
|
2012-10-10 12:17:49 -07:00
|
|
|
double rate, gx, gy, gz;
|
2012-08-20 15:15:52 -07:00
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get forces from a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-10-10 12:17:49 -07:00
|
|
|
ephysics_world_gravity_get(body->world, &gx, &gy, &gz);
|
2012-08-20 15:15:52 -07:00
|
|
|
|
2012-08-20 15:17:34 -07:00
|
|
|
if (x) *x = body->force.x * rate + gx;
|
2012-08-20 15:18:14 -07:00
|
|
|
if (y) *y = -body->force.y * rate + gy;
|
2012-10-10 12:17:49 -07:00
|
|
|
if (z) *z = body->force.z * rate + gz;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_torques_get(const EPhysics_Body *body, double *x, double *y, double *z)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get torques from a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x) *x = -body->force.torque_x;
|
|
|
|
if (y) *y = -body->force.torque_y;
|
|
|
|
if (z) *z = -body->force.torque_z;
|
2012-08-20 15:15:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_forces_clear(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't clear forces of a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->force.x = 0;
|
|
|
|
body->force.y = 0;
|
2012-10-10 12:17:49 -07:00
|
|
|
body->force.z = 0;
|
|
|
|
body->force.torque_x = 0;
|
|
|
|
body->force.torque_y = 0;
|
|
|
|
body->force.torque_z = 0;
|
2012-08-20 15:15:52 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 13:05:35 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:54 -07:00
|
|
|
ephysics_body_center_mass_get(const EPhysics_Body *body, double *x, double *y, double *z)
|
2012-08-22 13:05:35 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get center of mass from a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x) *x = body->cm.x;
|
|
|
|
if (y) *y = body->cm.y;
|
2012-10-10 12:17:54 -07:00
|
|
|
if (z) *z = body->cm.z;
|
2012-08-22 13:05:35 -07:00
|
|
|
}
|
|
|
|
|
2012-10-04 15:39:29 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_density_set(EPhysics_Body *body, double density)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set the density of a null body's material.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:39:42 -07:00
|
|
|
body->material = EPHYSICS_BODY_MATERIAL_CUSTOM;
|
2012-10-04 15:39:29 -07:00
|
|
|
body->density = density;
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
_ephysics_body_mass_set(body, 0);
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_body_density_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get the density of a null body's material.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->density;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:39:42 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_material_set(EPhysics_Body *body, EPhysics_Body_Material material)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body's material.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (material >= EPHYSICS_BODY_MATERIAL_LAST)
|
|
|
|
{
|
|
|
|
ERR("Invalid material.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (material != ephysics_material_props[material].material)
|
|
|
|
{
|
|
|
|
ERR("Material properties weren't found.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-17 14:37:10 -07:00
|
|
|
if (material == EPHYSICS_BODY_MATERIAL_CUSTOM)
|
|
|
|
{
|
|
|
|
body->material = material;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:39:42 -07:00
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
body->density = ephysics_material_props[material].density;
|
|
|
|
_ephysics_body_mass_set(body, 0);
|
|
|
|
_ephysics_body_friction_set(body,
|
|
|
|
ephysics_material_props[material].friction);
|
|
|
|
_ephysics_body_restitution_set(
|
|
|
|
body, ephysics_material_props[material].restitution);
|
|
|
|
body->material = material;
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body_Material
|
|
|
|
ephysics_body_material_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get body's material.");
|
|
|
|
return EPHYSICS_BODY_MATERIAL_LAST;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->material;
|
|
|
|
}
|
|
|
|
|
2012-10-10 13:32:08 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_light_set(EPhysics_Body *body, Eina_Bool enable)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("No body, no light.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->light_apply = !!enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
ephysics_body_light_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("No body, no light.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->light_apply;
|
|
|
|
}
|
|
|
|
|
2012-10-18 14:23:05 -07:00
|
|
|
EAPI double
|
|
|
|
ephysics_body_volume_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("No body, no volume.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return _ephysics_body_volume_get(body);
|
|
|
|
}
|
2012-10-10 13:32:08 -07:00
|
|
|
|
2012-10-19 11:50:46 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_back_face_culling_set(EPhysics_Body *body, Eina_Bool enable)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Body is NULL.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
body->back_face_culling = !!enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
ephysics_body_back_face_culling_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Body is NULL.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
return body->back_face_culling;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
ephysics_body_clockwise_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Body is NULL.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
return body->clockwise;
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:42 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_face_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body = (EPhysics_Body *) data;
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->obj == obj)
|
|
|
|
{
|
|
|
|
body->face_objs = eina_list_remove(body->face_objs, face_obj);
|
|
|
|
free(face_obj);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_face_obj_unset(Evas_Object *obj, Evas_Object_Event_Cb resize_func)
|
|
|
|
{
|
|
|
|
evas_object_map_enable_set(obj, EINA_FALSE);
|
|
|
|
evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_face_obj_del_cb);
|
|
|
|
evas_object_event_callback_del(obj, EVAS_CALLBACK_RESIZE, resize_func);
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_face_evas_object_del(EPhysics_Body *body, EPhysics_Body_Face_Obj *face_obj, Evas_Object_Event_Cb resize_func)
|
|
|
|
{
|
|
|
|
_ephysics_body_face_obj_unset(face_obj->obj, resize_func);
|
|
|
|
body->face_objs = eina_list_remove(body->face_objs, face_obj);
|
|
|
|
free(face_obj);
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:42 -08:00
|
|
|
static void
|
2012-11-09 10:52:49 -08:00
|
|
|
_ephysics_body_face_evas_object_add(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Evas_Object_Event_Cb resize_func)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->face == face)
|
|
|
|
{
|
|
|
|
_ephysics_body_face_obj_unset(face_obj->obj, resize_func);
|
|
|
|
face_obj->obj = evas_obj;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)calloc(1,
|
|
|
|
sizeof(EPhysics_Body_Face_Obj));
|
|
|
|
if (!face_obj)
|
|
|
|
{
|
|
|
|
ERR("Failed to create face object");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_obj->face = face;
|
|
|
|
face_obj->obj = evas_obj;
|
|
|
|
body->face_objs = eina_list_append(body->face_objs, face_obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_box_face_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
|
|
|
|
{
|
2012-11-09 10:52:49 -08:00
|
|
|
EPhysics_Body_Face face = EPHYSICS_BODY_FACE_LAST;
|
2012-11-09 10:52:42 -08:00
|
|
|
EPhysics_Body *body = (EPhysics_Body *) data;
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
int w, h, bw, bh, bd;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->obj == obj)
|
|
|
|
{
|
2012-11-09 10:52:49 -08:00
|
|
|
face = face_obj->face;
|
2012-11-09 10:52:42 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(face)
|
|
|
|
{
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_FRONT:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_BACK:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_MIDDLE_BACK:
|
|
|
|
if ((w == body->size.w) && (h == body->size.h))
|
|
|
|
return;
|
|
|
|
bw = w;
|
|
|
|
bh = h;
|
|
|
|
bd = body->size.d;
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_RIGHT:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_LEFT:
|
|
|
|
if ((w == body->size.d) && (h == body->size.h))
|
|
|
|
return;
|
|
|
|
bw = body->size.w;
|
|
|
|
bh = h;
|
|
|
|
bd = w;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_TOP:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_BOTTOM:
|
|
|
|
if ((w == body->size.w) && (h == body->size.d))
|
|
|
|
return;
|
|
|
|
bw = w;
|
|
|
|
bh = body->size.h;
|
|
|
|
bd = h;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Resizing body %p to w=%i, h=%i, d=%i", body, bw, bh, bd);
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
_ephysics_body_resize(body, bw, bh, bd);
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_box_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
int obj_x, obj_y, obj_w, obj_h, bx, by, bz, bw, bh, bd;
|
|
|
|
double rate;
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
if ((face < EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_BOX_FACE_BOTTOM))
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, face is invalid.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->soft_body)
|
|
|
|
{
|
|
|
|
ERR("Not implemented for soft bodies yet.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_body_face_evas_object_add(body, face, evas_obj,
|
|
|
|
_ephysics_body_box_face_obj_resize_cb);
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_face_obj_del_cb, body);
|
|
|
|
|
|
|
|
if (!use_obj_pos)
|
|
|
|
return;
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
evas_object_geometry_get(evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
|
|
|
|
ephysics_body_geometry_get(body, &bx, &by, &bz, &bw, &bh, &bd);
|
|
|
|
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
|
|
|
|
switch(face)
|
|
|
|
{
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_FRONT:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_BACK:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_MIDDLE_BACK:
|
|
|
|
_ephysics_body_geometry_set(body, obj_x, obj_y, bz,
|
|
|
|
obj_w, obj_h, bd, rate);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_RIGHT:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_LEFT:
|
|
|
|
_ephysics_body_geometry_set(body, bx, by, bz,
|
|
|
|
bw, obj_h, obj_w, rate);
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_TOP:
|
|
|
|
case EPHYSICS_BODY_BOX_FACE_BOTTOM:
|
|
|
|
_ephysics_body_geometry_set(body, bx, by, bz,
|
|
|
|
obj_w, bh, obj_h, rate);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_box_face_obj_resize_cb,
|
|
|
|
body);
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
static Evas_Object *
|
|
|
|
_ephysics_body_box_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
if ((face < EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_BOX_FACE_BOTTOM))
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
ERR("Can't get evas object from body, face is invalid.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->face == face)
|
|
|
|
return face_obj->obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR("Couldn't find an object associated to face %i.", face);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
static Evas_Object *
|
|
|
|
_ephysics_body_box_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
if ((face < EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_BOX_FACE_BOTTOM))
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
ERR("Can't unset evas object from body, face is invalid.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->face == face)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = face_obj->obj;
|
|
|
|
_ephysics_body_face_obj_unset(
|
|
|
|
obj, _ephysics_body_box_face_obj_resize_cb);
|
|
|
|
body->face_objs = eina_list_remove(body->face_objs, face_obj);
|
|
|
|
free(face_obj);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR("Couldn't find an object associated to face %i.", face);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_cylinder_face_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
|
|
|
|
{
|
2012-11-09 10:52:49 -08:00
|
|
|
EPhysics_Body_Face face = EPHYSICS_BODY_FACE_LAST;
|
2012-11-09 10:52:42 -08:00
|
|
|
EPhysics_Body *body = (EPhysics_Body *) data;
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
int w, h, bw, bh, bd;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->obj == obj)
|
|
|
|
{
|
2012-11-09 10:52:49 -08:00
|
|
|
face = face_obj->face;
|
2012-11-09 10:52:42 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(face)
|
|
|
|
{
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_FRONT:
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_BACK:
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT:
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_BACK:
|
|
|
|
if ((w == body->size.w) && (h == body->size.h))
|
|
|
|
return;
|
|
|
|
bw = w;
|
|
|
|
bh = h;
|
|
|
|
bd = body->size.d;
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_CURVED:
|
|
|
|
if ((h == body->size.d))
|
|
|
|
return;
|
|
|
|
bw = body->size.w;
|
|
|
|
bh = body->size.h;
|
|
|
|
bd = h;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Resizing body %p to w=%i, h=%i, d=%i", body, bw, bh, bd);
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
_ephysics_body_resize(body, bw, bh, bd);
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_cylinder_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
int obj_x, obj_y, obj_w, obj_h, bx, by, bz, bw, bh, bd;
|
|
|
|
double rate;
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
if ((face < EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_CYLINDER_FACE_CURVED))
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, face is invalid.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->soft_body)
|
|
|
|
{
|
|
|
|
ERR("Not implemented for soft bodies yet.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_body_face_evas_object_add(
|
|
|
|
body, face, evas_obj, _ephysics_body_cylinder_face_obj_resize_cb);
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_face_obj_del_cb, body);
|
|
|
|
|
|
|
|
if (!use_obj_pos)
|
|
|
|
return;
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
evas_object_geometry_get(evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
|
|
|
|
ephysics_body_geometry_get(body, &bx, &by, &bz, &bw, &bh, &bd);
|
|
|
|
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
|
|
|
|
switch(face)
|
|
|
|
{
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_FRONT:
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_BACK:
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT:
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_BACK:
|
|
|
|
_ephysics_body_geometry_set(body, obj_x, obj_y, bz,
|
|
|
|
obj_w, obj_h, bd, rate);
|
|
|
|
break;
|
|
|
|
case EPHYSICS_BODY_CYLINDER_FACE_CURVED:
|
|
|
|
_ephysics_body_geometry_set(body, bx, by, bz,
|
|
|
|
bw, bh, obj_h, rate);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_cylinder_face_obj_resize_cb,
|
|
|
|
body);
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
static Evas_Object *
|
|
|
|
_ephysics_body_cylinder_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
if ((face < EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_CYLINDER_FACE_CURVED))
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
ERR("Can't get evas object from body, face is invalid.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->face == face)
|
|
|
|
return face_obj->obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR("Couldn't find an object associated to face %i.", face);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
static Evas_Object *
|
|
|
|
_ephysics_body_cylinder_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
if ((face < EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_CYLINDER_FACE_CURVED))
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
ERR("Can't unset evas object from body, face is invalid.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->face == face)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = face_obj->obj;
|
|
|
|
_ephysics_body_face_obj_unset(
|
|
|
|
obj, _ephysics_body_cylinder_face_obj_resize_cb);
|
|
|
|
body->face_objs = eina_list_remove(body->face_objs, face_obj);
|
|
|
|
free(face_obj);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR("Couldn't find an object associated to face %i.", face);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_cloth_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
int obj_x, obj_y, obj_w, obj_h, bz, bd;
|
|
|
|
double rate;
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
if ((face < EPHYSICS_BODY_CLOTH_FACE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_CLOTH_FACE_BACK))
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, face is invalid.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_body_face_evas_object_add(body, face, evas_obj,
|
|
|
|
_ephysics_body_evas_obj_resize_cb);
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_face_obj_del_cb, body);
|
|
|
|
|
|
|
|
if (!use_obj_pos)
|
|
|
|
return;
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
evas_object_geometry_get(evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
|
|
|
|
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
ephysics_body_geometry_get(body, NULL, NULL, &bz, NULL, NULL, &bd);
|
|
|
|
_ephysics_body_geometry_set(body, obj_x, obj_y, bz, obj_w, obj_h, bd, rate);
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb,
|
|
|
|
body);
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
static Evas_Object *
|
|
|
|
_ephysics_body_cloth_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
if ((face < EPHYSICS_BODY_CLOTH_FACE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_CLOTH_FACE_BACK))
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
ERR("Can't get evas object from body, face is invalid.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->face == face)
|
|
|
|
return face_obj->obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR("Couldn't find an object associated to face %i.", face);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
static Evas_Object *
|
|
|
|
_ephysics_body_cloth_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
if ((face < EPHYSICS_BODY_CLOTH_FACE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_CLOTH_FACE_BACK))
|
2012-11-09 10:52:42 -08:00
|
|
|
{
|
|
|
|
ERR("Can't unset evas object from body, face is invalid.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
if (face_obj->face == face)
|
|
|
|
{
|
|
|
|
Evas_Object *obj = face_obj->obj;
|
|
|
|
_ephysics_body_face_obj_unset(
|
|
|
|
obj, _ephysics_body_evas_obj_resize_cb);
|
|
|
|
body->face_objs = eina_list_remove(body->face_objs, face_obj);
|
|
|
|
free(face_obj);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR("Couldn't find an object associated to face %i.", face);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-11-23 13:51:38 -08:00
|
|
|
static void
|
|
|
|
_ephysics_body_ellipsoid_face_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body = (EPhysics_Body *) data;
|
|
|
|
Evas_Coord bd, w, h;
|
|
|
|
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
|
|
|
|
ephysics_body_geometry_get(body, NULL, NULL, NULL, NULL, NULL, &bd);
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
ephysics_body_resize(body, w, h, bd);
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_ellipsoid_face_evas_object_del_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
void *ldata;
|
|
|
|
EPhysics_Body_Face_Obj *face_obj = NULL;
|
|
|
|
EPhysics_Body_Face_Slice *face_slice = (EPhysics_Body_Face_Slice *)data;
|
|
|
|
EPhysics_Body *body = face_slice->body;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(body->face_objs, l, ldata)
|
|
|
|
{
|
|
|
|
if (((EPhysics_Body_Face_Obj *)ldata)->face == face_slice->face)
|
|
|
|
{
|
|
|
|
face_obj = (EPhysics_Body_Face_Obj *)ldata;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_body_face_evas_object_del(body, face_obj,
|
|
|
|
_ephysics_body_ellipsoid_face_obj_resize_cb);
|
|
|
|
_ephysics_body_soft_body_slices_clean(face_slice->slices);
|
|
|
|
DBG("Ellipsoid's face cleaned up.");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_ellipsoid_face_evas_object_clean(EPhysics_Body *body, EPhysics_Body_Face_Obj *face_obj, Eina_List *slices)
|
|
|
|
{
|
|
|
|
evas_object_map_enable_set(face_obj->obj, EINA_FALSE);
|
|
|
|
evas_object_event_callback_del(face_obj->obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_ellipsoid_face_evas_object_del_cb);
|
|
|
|
evas_object_event_callback_del(face_obj->obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb);
|
|
|
|
evas_object_event_callback_del(face_obj->obj, EVAS_CALLBACK_RESTACK,
|
|
|
|
_ephysics_body_soft_body_evas_restack_cb);
|
|
|
|
_ephysics_body_soft_body_slices_clean(slices);
|
|
|
|
|
|
|
|
_ephysics_body_face_evas_object_del(body, face_obj,
|
|
|
|
_ephysics_body_ellipsoid_face_obj_resize_cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_ellipsoid_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
|
|
|
|
{
|
|
|
|
int obj_x, obj_y, obj_w, obj_h, bz, bd;
|
|
|
|
double rate;
|
|
|
|
EPhysics_Body_Face_Slice *face_slice = NULL;
|
|
|
|
EPhysics_Body_Face_Obj *face_obj;
|
|
|
|
|
|
|
|
if ((face < EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_BACK))
|
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, face is invalid.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, the last wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!evas_obj)
|
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, the first wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_slice = _ephysics_body_face_slice_get(body, face);
|
|
|
|
if (!face_slice)
|
|
|
|
{
|
|
|
|
ERR("Could not find pre initialized face slice for the wanted face.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_obj = _ephysics_body_face_evas_object_get(body, face);
|
|
|
|
|
|
|
|
if (face_obj)
|
|
|
|
_ephysics_body_ellipsoid_face_evas_object_clean(body, face_obj,
|
|
|
|
face_slice->slices);
|
|
|
|
|
|
|
|
_ephysics_body_face_evas_object_add(body, face, evas_obj,
|
|
|
|
_ephysics_body_ellipsoid_face_obj_resize_cb);
|
|
|
|
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_ellipsoid_face_evas_object_del_cb, face_slice);
|
|
|
|
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESTACK,
|
|
|
|
_ephysics_body_soft_body_evas_restack_cb,
|
|
|
|
body);
|
|
|
|
|
|
|
|
_ephysics_body_soft_body_slices_init(body, evas_obj, face_slice->slices);
|
|
|
|
|
|
|
|
if (!use_obj_pos)
|
|
|
|
return;
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
evas_object_geometry_get(evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
|
|
|
|
ephysics_body_geometry_get(body, NULL, NULL, &bz, NULL, NULL, &bd);
|
|
|
|
|
|
|
|
ephysics_world_lock_take(body->world);
|
|
|
|
_ephysics_body_geometry_set(body, obj_x, obj_y, bz, obj_w, obj_h, bd, rate);
|
|
|
|
ephysics_world_lock_release(body->world);
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb, body);
|
|
|
|
DBG("Ellipsoid face evas object set.");
|
|
|
|
}
|
|
|
|
|
|
|
|
static Evas_Object *
|
|
|
|
_ephysics_body_ellipsoid_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
|
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Obj *face_obj = NULL;
|
|
|
|
|
|
|
|
if ((face < EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_BACK))
|
|
|
|
{
|
|
|
|
ERR("Can't get evas object from body, face is invalid.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_obj = _ephysics_body_face_evas_object_get((EPhysics_Body *)body, face);
|
|
|
|
if (face_obj) return face_obj->obj;
|
|
|
|
|
|
|
|
ERR("Couldn't find an object associated to face %i.", face);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Evas_Object *
|
|
|
|
_ephysics_body_ellipsoid_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
|
|
|
|
{
|
|
|
|
EPhysics_Body_Face_Slice *face_slice;
|
|
|
|
EPhysics_Body_Face_Obj *face_obj = NULL;
|
|
|
|
Evas_Object *obj;
|
|
|
|
|
|
|
|
if ((face < EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_FRONT) ||
|
|
|
|
(face > EPHYSICS_BODY_SOFT_ELLIPSOID_FACE_BACK))
|
|
|
|
{
|
|
|
|
ERR("Can't unset evas object from body, face is invalid.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
face_obj = _ephysics_body_face_evas_object_get(body, face);
|
|
|
|
|
|
|
|
if (!face_obj) return NULL;
|
|
|
|
|
|
|
|
obj = face_obj->obj;
|
|
|
|
face_slice = _ephysics_body_face_slice_get(body, face);
|
|
|
|
_ephysics_body_ellipsoid_face_evas_object_clean(body, face_obj,
|
|
|
|
face_slice->slices);
|
|
|
|
|
|
|
|
DBG("EPhysics Body face unset.");
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2012-11-09 10:52:49 -08:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, the last wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!evas_obj)
|
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, the first wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
return _ephysics_body_cloth_face_evas_object_set(body, face, evas_obj,
|
|
|
|
use_obj_pos);
|
2012-11-09 10:53:04 -08:00
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_CYLINDER)
|
2012-11-09 10:52:49 -08:00
|
|
|
return _ephysics_body_cylinder_face_evas_object_set(body, face, evas_obj,
|
|
|
|
use_obj_pos);
|
2012-11-09 10:53:04 -08:00
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_BOX)
|
2012-11-09 10:52:49 -08:00
|
|
|
return _ephysics_body_box_face_evas_object_set(body, face, evas_obj,
|
|
|
|
use_obj_pos);
|
2012-11-23 13:51:38 -08:00
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_ELLIPSOID)
|
|
|
|
return _ephysics_body_ellipsoid_face_evas_object_set(body, face, evas_obj,
|
|
|
|
use_obj_pos);
|
2012-11-09 10:52:49 -08:00
|
|
|
|
|
|
|
ERR("Can't handle body %p type.", body);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Evas_Object *
|
|
|
|
ephysics_body_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get evas object from body, it wasn't provided.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
return _ephysics_body_cloth_face_evas_object_get(body, face);
|
2012-11-09 10:53:04 -08:00
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_CYLINDER)
|
2012-11-09 10:52:49 -08:00
|
|
|
return _ephysics_body_cylinder_face_evas_object_get(body, face);
|
2012-11-09 10:53:04 -08:00
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_BOX)
|
2012-11-09 10:52:49 -08:00
|
|
|
return _ephysics_body_box_face_evas_object_get(body, face);
|
2012-11-23 13:51:38 -08:00
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_ELLIPSOID)
|
|
|
|
return _ephysics_body_ellipsoid_face_evas_object_get(body, face);
|
2012-11-09 10:52:49 -08:00
|
|
|
|
|
|
|
ERR("Can't handle body %p type.", body);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Evas_Object *
|
|
|
|
ephysics_body_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't unset evas object from body, it wasn't provided.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
|
|
|
|
return _ephysics_body_cloth_face_evas_object_unset(body, face);
|
2012-11-09 10:53:04 -08:00
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_CYLINDER)
|
2012-11-09 10:52:49 -08:00
|
|
|
return _ephysics_body_cylinder_face_evas_object_unset(body, face);
|
2012-11-09 10:53:04 -08:00
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_BOX)
|
2012-11-09 10:52:49 -08:00
|
|
|
return _ephysics_body_box_face_evas_object_unset(body, face);
|
2012-11-23 13:51:38 -08:00
|
|
|
if (body->shape == EPHYSICS_BODY_SHAPE_ELLIPSOID)
|
|
|
|
return _ephysics_body_ellipsoid_face_evas_object_unset(body, face);
|
2012-11-09 10:52:49 -08:00
|
|
|
|
|
|
|
ERR("Can't handle body %p type.", body);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|