1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <Evas.h>
6 #include <Ecore.h>
7
8 #pragma GCC diagnostic push
9 #pragma GCC diagnostic ignored "-Wshadow"
10
11 #include <BulletCollision/CollisionShapes/btShapeHull.h>
12 #include <LinearMath/btGeometryUtil.h>
13
14 #pragma GCC diagnostic pop
15
16 #include <math.h>
17
18 #include "ephysics_trimesh.h"
19 #include "ephysics_private.h"
20 #include "ephysics_body_materials.h"
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 #define BODY_CLOTH_CHECK() \
27 do { \
28 if (body->type == EPHYSICS_BODY_TYPE_CLOTH) \
29 { \
30 WRN("Not supported for cloth"); \
31 return; \
32 } \
33 } while(0)
34
35 typedef struct _EPhysics_Body_Callback EPhysics_Body_Callback;
36 typedef struct _EPhysics_Body_Evas_Stacking EPhysics_Body_Evas_Stacking;
37 typedef struct _EPhysics_Body_Soft_Body_Slice EPhysics_Body_Soft_Body_Slice;
38 typedef struct _EPhysics_Body_Face_Obj EPhysics_Body_Face_Obj;
39 typedef struct _EPhysics_Quaternion EPhysics_Quaternion;
40
41 struct _EPhysics_Body_Callback {
42 EINA_INLIST;
43 void (*func) (void *data, EPhysics_Body *body, void *event_info);
44 void *data;
45 EPhysics_Callback_Body_Type type;
46 Eina_Bool deleted:1;
47 };
48
49 struct _EPhysics_Body_Collision {
50 EPhysics_Body *contact_body;
51 Evas_Coord x;
52 Evas_Coord y;
53 Evas_Coord z;
54 };
55
56 struct _EPhysics_Body_Evas_Stacking {
57 Evas_Object *evas;
58 float stacking;
59 };
60
61 struct _EPhysics_Body_Soft_Body_Slice
62 {
63 Evas_Object *evas_obj;
64 int index;
65 struct {
66 double x;
67 double y;
68 } p[3];
69 float stacking;
70 };
71
72 struct _EPhysics_Body_Face_Obj {
73 EPhysics_Body_Face face;
74 Evas_Object *obj;
75 };
76
77 static void
_ephysics_body_cloth_anchor_mass_reset(EPhysics_Body * body)78 _ephysics_body_cloth_anchor_mass_reset(EPhysics_Body *body)
79 {
80 double anchor_mass;
81 anchor_mass = 1 / (body->soft_body->m_nodes.size() * 0.025);
82
83 for (int i = 0; i < body->soft_body->m_anchors.size(); i++)
84 body->soft_body->m_anchors[i].m_node->m_im = anchor_mass;
85
86 DBG("Cloth anchors mass reset.");
87 }
88
89 EAPI void
_ephysics_body_soft_body_light_apply(Evas_Map * m,Evas_Coord lx,Evas_Coord ly,Evas_Coord lz,int lr,int lg,int lb,int ar,int ag,int ab,Evas_Coord bx,Evas_Coord by,Evas_Coord bz)90 _ephysics_body_soft_body_light_apply(Evas_Map *m, Evas_Coord lx, Evas_Coord ly, Evas_Coord lz, int lr, int lg, int lb, int ar, int ag, int ab, Evas_Coord bx, Evas_Coord by, Evas_Coord bz)
91 {
92 double x, y, z, nx, ny, nz, ln, br;
93 Evas_Coord mx, my, mz, mr, mg, mb, ma;
94 int i;
95
96 for (i = 0; i < 4; i++)
97 {
98
99 evas_map_point_coord_get(m, i, &mx, &my, &mz);
100 evas_map_point_color_get(m, i, NULL, NULL, NULL, &ma);
101
102 x = mx;
103 y = my;
104 z = mz;
105
106 nx = sqrt(pow(bx - x, 2));
107 ny = sqrt(pow(by - y, 2));
108 nz = sqrt(pow(bz - z, 2));
109 ln = nx + ny + nz;
110
111 if (ln != 0.0)
112 {
113 nx /= ln;
114 ny /= ln;
115 nz /= ln;
116 }
117
118 x = lx - bx;
119 y = ly - by;
120 z = lz - bz;
121
122 ln = pow(x, 2) + pow(y, 2) + pow(z, 2);
123 ln = sqrt(ln);
124
125 if (ln != 0.0)
126 {
127 x /= ln;
128 y /= ln;
129 z /= ln;
130 }
131
132 br = (nx * x) + (ny * y) + (nz * z);
133 if (br < 0.0) br = 0.0;
134
135 mr = ar + ((lr - ar) * br);
136 mg = ag + ((lg - ag) * br);
137 mb = ab + ((lb - ab) * br);
138
139 evas_map_point_color_set(m, i, mr, mg, mb, ma);
140 }
141 }
142
143 static void
_ephysics_body_soft_body_slices_apply(EPhysics_Body * body,Evas_Object * evas_obj,Eina_List * slices)144 _ephysics_body_soft_body_slices_apply(EPhysics_Body *body, Evas_Object *evas_obj, Eina_List *slices)
145 {
146 double rate;
147 void *list_data;
148 Eina_List *l;
149 Evas_Coord wy, wh, y0, y1, y2, x0, x1, x2, z0, z1, z2, w, h, bx, by, bz;
150 Evas_Map *map;
151 btVector3 p0, p1, p2;
152 btSoftBody::tFaceArray faces;
153 EPhysics_Body_Soft_Body_Slice *slice;
154 int lr, lg, lb, ar, ag, ab;
155 Evas_Coord lx, ly, lz;
156 Eina_Bool light = EINA_FALSE;
157 EPhysics_Camera *camera;
158
159 int px, py, pz, foc;
160 Eina_Bool perspective = EINA_FALSE;
161
162 camera = ephysics_world_camera_get(body->world);
163 rate = ephysics_world_rate_get(body->world);
164 ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, NULL, &wh,
165 NULL);
166 evas_object_geometry_get(evas_obj, NULL, NULL, &w, &h);
167
168 ephysics_body_geometry_get(body, &bx, &by, &bz, NULL, NULL, NULL);
169
170 if ((body->light_apply) ||
171 (ephysics_world_light_all_bodies_get(body->world)))
172 {
173 ephysics_world_point_light_position_get(body->world, &lx, &ly, &lz);
174 ephysics_world_point_light_color_get(body->world, &lr, &lg, &lb);
175 ephysics_world_ambient_light_color_get(body->world, &ar, &ag, &ab);
176 light = EINA_TRUE;
177 }
178
179 if (ephysics_camera_perspective_enabled_get(camera))
180 {
181 ephysics_camera_perspective_get(camera, &px, &py, &pz, &foc);
182 perspective = EINA_TRUE;
183 }
184
185 EINA_LIST_FOREACH(slices, l, list_data)
186 {
187 slice = (EPhysics_Body_Soft_Body_Slice *)list_data;
188
189 faces = body->soft_body->m_faces;
190 p0 = faces[slice->index].m_n[0]->m_x;
191 p1 = faces[slice->index].m_n[1]->m_x;
192 p2 = faces[slice->index].m_n[2]->m_x;
193
194 slice->stacking = p0.z() + p1.z() + p2.z();
195
196 map = evas_map_new(4);
197
198 evas_map_point_image_uv_set(map, 0, slice->p[0].x * w,
199 slice->p[0].y * h);
200 evas_map_point_image_uv_set(map, 1, slice->p[1].x * w,
201 slice->p[1].y * h);
202 evas_map_point_image_uv_set(map, 2, slice->p[2].x * w,
203 slice->p[2].y * h);
204 evas_map_point_image_uv_set(map, 3, slice->p[2].x * w,
205 slice->p[2].y * h);
206
207 x0 = p0.x() * rate;
208 x1 = p1.x() * rate;
209 x2 = p2.x() * rate;
210
211 y0 = wh + wy - (p0.y() * rate);
212 y1 = wh + wy - (p1.y() * rate);
213 y2 = wh + wy - (p2.y() * rate);
214
215 z0 = p0.z() * rate;
216 z1 = p1.z() * rate;
217 z2 = p2.z() * rate;
218
219 evas_map_point_coord_set(map, 0, x0, y0, z0);
220 evas_map_point_coord_set(map, 1, x1, y1, z1);
221 evas_map_point_coord_set(map, 2, x2, y2, z2);
222 evas_map_point_coord_set(map, 3, x2, y2, z2);
223
224 if (perspective)
225 evas_map_util_3d_perspective(map, px, py, pz, foc);
226
227 if (body->back_face_culling)
228 {
229 if (evas_map_util_clockwise_get(map))
230 evas_object_show(slice->evas_obj);
231 else
232 {
233 evas_map_free(map);
234 evas_object_hide(slice->evas_obj);
235 continue;
236 }
237 }
238
239 if (light)
240 _ephysics_body_soft_body_light_apply(map, lx, ly, lz, lr, lg, lb, ar,
241 ag, ab, bx, by, bz);
242
243 evas_object_map_set(slice->evas_obj, map);
244 evas_object_map_enable_set(slice->evas_obj, EINA_TRUE);
245 evas_map_free(map);
246 }
247 }
248
249 static inline double
_ephysics_body_soft_body_slice_calc(double val,double delta,double max)250 _ephysics_body_soft_body_slice_calc(double val, double delta, double max)
251 {
252 double ret = val + delta / max;
253 if (ret < 0)
254 ret = 0;
255 else if (ret > 1)
256 ret = 1;
257 return ret;
258 }
259
260 static EPhysics_Body_Soft_Body_Slice *
_ephysics_body_soft_body_slice_new(EPhysics_Body * body,double delta,double max,int index)261 _ephysics_body_soft_body_slice_new(EPhysics_Body *body, double delta, double max, int index)
262 {
263 EPhysics_Body_Soft_Body_Slice *slice;
264 btSoftBody::tFaceArray faces;
265
266 slice = (EPhysics_Body_Soft_Body_Slice *)calloc(
267 1, sizeof(EPhysics_Body_Soft_Body_Slice));
268 if (!slice)
269 {
270 ERR("Couldn't allocate EPhysics_Soft_Body_Slice memory.");
271 return NULL;
272 }
273
274 faces = body->soft_body->m_faces;
275
276 slice->index = index;
277 if (!faces.size()) return slice;
278 slice->p[0].x = _ephysics_body_soft_body_slice_calc(
279 faces[slice->index].m_n[0]->m_x.x(), delta, max);
280 slice->p[0].y = 1 - _ephysics_body_soft_body_slice_calc(
281 faces[slice->index].m_n[0]->m_x.y(), delta, max);
282 slice->p[1].x = _ephysics_body_soft_body_slice_calc(
283 faces[slice->index].m_n[1]->m_x.x(), delta, max);
284 slice->p[1].y = 1 - _ephysics_body_soft_body_slice_calc(
285 faces[slice->index].m_n[1]->m_x.y(), delta, max);
286 slice->p[2].x = _ephysics_body_soft_body_slice_calc(
287 faces[slice->index].m_n[2]->m_x.x(), delta, max);
288 slice->p[2].y = 1 - _ephysics_body_soft_body_slice_calc(
289 faces[slice->index].m_n[2]->m_x.y(), delta, max);
290
291 return slice;
292 }
293
294 static Eina_List *
_ephysics_body_soft_body_slices_get(EPhysics_Body * body)295 _ephysics_body_soft_body_slices_get(EPhysics_Body *body)
296 {
297 Eina_List *l, *slices_list, *slices = NULL;
298 void *ldata, *slice_data;
299 EPhysics_Body_Face_Slice *face_slice;
300
301 EINA_LIST_FOREACH(body->faces_slices, l, ldata)
302 {
303 face_slice = (EPhysics_Body_Face_Slice *)ldata;
304 EINA_LIST_FOREACH(face_slice->slices, slices_list, slice_data)
305 slices = eina_list_append(slices, slice_data);
306 }
307
308 return slices;
309 }
310
311 EAPI int
ephysics_body_soft_body_slice_index_get(EPhysics_Body * body,Evas_Object * slice)312 ephysics_body_soft_body_slice_index_get(EPhysics_Body *body, Evas_Object *slice)
313 {
314 Eina_List *slices;
315 void *ldata;
316 EPhysics_Body_Soft_Body_Slice *slice_data;
317
318 if (!body)
319 {
320 ERR("Can't get soft body slice index, body is null.");
321 return -1;
322 }
323
324 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
325 {
326 ERR("Can't get soft body slice index, operation not allowed for rigid"
327 " bodies.");
328 return -1;
329 }
330
331 slices = _ephysics_body_soft_body_slices_get(body);
332 EINA_LIST_FREE(slices, ldata)
333 {
334 slice_data = (EPhysics_Body_Soft_Body_Slice *)ldata;
335 if (slice_data->evas_obj == slice)
336 return slice_data->index;
337 }
338
339 return -1;
340 }
341
342 static void
_ephysics_body_soft_body_slice_del_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)343 _ephysics_body_soft_body_slice_del_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
344 {
345 EPhysics_Body_Soft_Body_Slice *slice = (EPhysics_Body_Soft_Body_Slice *)data;
346 slice->evas_obj = NULL;
347 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
348 _ephysics_body_soft_body_slice_del_cb);
349 }
350
351 static void
_ephysics_body_soft_body_slices_init(EPhysics_Body * body,Evas_Object * obj,Eina_List * slices)352 _ephysics_body_soft_body_slices_init(EPhysics_Body *body, Evas_Object *obj, Eina_List *slices)
353 {
354 EPhysics_Body_Soft_Body_Slice *slice = NULL;
355 btVector3 p0, p1, p2;
356 void *slice_data;
357 Evas_Coord w, h;
358 Eina_List *l;
359 Evas *evas;
360 Evas_Object *parent;
361
362 evas = evas_object_evas_get(obj);
363 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
364
365 parent = evas_object_smart_parent_get(obj);
366 EINA_LIST_FOREACH(slices, l, slice_data)
367 {
368 slice = (EPhysics_Body_Soft_Body_Slice *) slice_data;
369 slice->evas_obj = evas_object_image_filled_add(evas);
370 evas_object_layer_set(slice->evas_obj,
371 evas_object_layer_get(obj));
372 evas_object_image_source_set(slice->evas_obj, obj);
373 evas_object_image_source_events_set(slice->evas_obj, EINA_TRUE);
374 evas_object_resize(slice->evas_obj, w, h);
375 evas_object_show(slice->evas_obj);
376 evas_object_image_smooth_scale_set(slice->evas_obj, EINA_TRUE);
377 evas_object_event_callback_add(slice->evas_obj, EVAS_CALLBACK_DEL,
378 _ephysics_body_soft_body_slice_del_cb,
379 slice);
380
381 if (parent) evas_object_smart_member_add(slice->evas_obj, parent);
382 }
383
384 if (slice)
385 evas_object_image_source_visible_set(slice->evas_obj, EINA_FALSE);
386
387 _ephysics_body_soft_body_slices_apply(body, obj, slices);
388 }
389
390 static void
_ephysics_body_soft_body_slices_free(Eina_List * slices)391 _ephysics_body_soft_body_slices_free(Eina_List *slices)
392 {
393 EPhysics_Body_Soft_Body_Slice *slice;
394 void *slice_data;
395
396 EINA_LIST_FREE(slices, slice_data)
397 {
398 slice = (EPhysics_Body_Soft_Body_Slice *)slice_data;
399 if (slice->evas_obj)
400 evas_object_del(slice->evas_obj);
401 free(slice);
402 }
403 }
404
405 static void
_ephysics_body_soft_body_slices_clean(Eina_List * slices)406 _ephysics_body_soft_body_slices_clean(Eina_List *slices)
407 {
408 EPhysics_Body_Soft_Body_Slice *slice;
409 void *slice_data;
410 Eina_List *l;
411
412 EINA_LIST_FOREACH(slices, l, slice_data)
413 {
414 slice = (EPhysics_Body_Soft_Body_Slice *)slice_data;
415 if (slice->evas_obj)
416 evas_object_del(slice->evas_obj);
417 }
418 }
419
420 static btTransform
_ephysics_body_transform_get(const EPhysics_Body * body)421 _ephysics_body_transform_get(const EPhysics_Body *body)
422 {
423 btTransform trans;
424 btVector3 center;
425 btScalar radius;
426
427 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
428 {
429 body->rigid_body->getMotionState()->getWorldTransform(trans);
430 return trans;
431 }
432
433 body->soft_body->getCollisionShape()->getBoundingSphere(center, radius);
434 trans.setIdentity();
435 trans.setOrigin(center);
436 return trans;
437 }
438
439 static int
_ephysics_body_evas_stacking_sort_cb(const void * d1,const void * d2)440 _ephysics_body_evas_stacking_sort_cb(const void *d1, const void *d2)
441 {
442 const EPhysics_Body_Evas_Stacking *stacking1, *stacking2;
443
444 stacking1 = (const EPhysics_Body_Evas_Stacking *)d1;
445 stacking2 = (const EPhysics_Body_Evas_Stacking *)d2;
446
447 if (!stacking1) return 1;
448 if (!stacking2) return -1;
449
450 if (stacking1->stacking < stacking2->stacking) return -1;
451 if (stacking1->stacking > stacking2->stacking) return 1;
452
453 return 0;
454 }
455
456 static EPhysics_Body_Evas_Stacking *
_ephysics_body_evas_stacking_new(Evas_Object * obj,float index)457 _ephysics_body_evas_stacking_new(Evas_Object *obj, float index)
458 {
459 EPhysics_Body_Evas_Stacking *stacking;
460
461 stacking = (EPhysics_Body_Evas_Stacking *)calloc(
462 1, sizeof(EPhysics_Body_Evas_Stacking));
463
464 if (!stacking)
465 {
466 ERR("Could not allocate ephysics soft body evas stacking data.");
467 return NULL;
468 }
469
470 stacking->evas = obj;
471 stacking->stacking = index;
472 return stacking;
473 }
474
475 void
ephysics_body_evas_objects_restack(EPhysics_World * world)476 ephysics_body_evas_objects_restack(EPhysics_World *world)
477 {
478 void *data, *slice_data, *stack_data;
479 EPhysics_Body *body;
480 btTransform trans;
481 EPhysics_Body_Evas_Stacking *stacking;
482 EPhysics_Body_Soft_Body_Slice *slice;
483 Eina_List *l, *slices, *bodies, *stack_list = NULL;
484 Evas_Object *prev_obj = NULL;
485 Eina_Hash *hash;
486 Eina_Iterator *it;
487 int layer;
488 Eina_List *ll = NULL;
489
490 bodies = ephysics_world_bodies_get(world);
491
492 if (!eina_list_count(bodies))
493 return;
494
495 hash = eina_hash_int32_new(NULL);
496
497 EINA_LIST_FREE(bodies, data)
498 {
499 body = (EPhysics_Body *)data;
500 if (body->deleted) continue;
501
502 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
503 {
504 if (!body->evas_obj) continue;
505 trans = _ephysics_body_transform_get(body);
506 stacking = _ephysics_body_evas_stacking_new(body->evas_obj,
507 trans.getOrigin().z());
508 if (!stacking) goto error;
509
510 layer = evas_object_layer_get(stacking->evas);
511 stack_list = (Eina_List *)eina_hash_find(hash, &layer);
512 stack_list = eina_list_append(stack_list, stacking);
513 eina_hash_set(hash, &layer, stack_list);
514
515 continue;
516 }
517
518 slices = _ephysics_body_soft_body_slices_get(body);
519 if (!slices) continue;
520
521 EINA_LIST_FREE(slices, slice_data)
522 {
523 slice = (EPhysics_Body_Soft_Body_Slice *)slice_data;
524
525 stacking = _ephysics_body_evas_stacking_new(slice->evas_obj,
526 slice->stacking);
527 if (!stacking) goto error;
528
529 layer = evas_object_layer_get(stacking->evas);
530 stack_list = (Eina_List *)eina_hash_find(hash, &layer);
531 stack_list = eina_list_append(stack_list, stacking);
532 eina_hash_set(hash, &layer, stack_list);
533 }
534 }
535
536
537 it = eina_hash_iterator_data_new(hash);
538 while (eina_iterator_next(it, &data))
539 {
540 stack_list = (Eina_List *)data;
541 stack_list = eina_list_sort(stack_list, eina_list_count(stack_list),
542 _ephysics_body_evas_stacking_sort_cb);
543 prev_obj = NULL;
544
545 ll = eina_list_append(ll, stack_list);
546
547 EINA_LIST_FOREACH(stack_list, l, stack_data)
548 {
549 stacking = (EPhysics_Body_Evas_Stacking *)stack_data;
550
551 if (prev_obj)
552 evas_object_stack_below(stacking->evas, prev_obj);
553
554 prev_obj = stacking->evas;
555 }
556 }
557
558 eina_iterator_free(it);
559
560 EINA_LIST_FREE(ll, stack_data)
561 {
562 stack_list = (Eina_List *) stack_data;
563 eina_hash_del_by_data(hash, stack_list);
564 EINA_LIST_FREE(stack_list, slice_data)
565 free(slice_data);
566 }
567
568 eina_hash_free(hash);
569 return;
570
571 error:
572 ERR("Could not allocate evas stacking data memory.");
573 eina_hash_free(hash);
574 }
575
576 static void
_ephysics_body_transform_set(EPhysics_Body * body,btTransform trans)577 _ephysics_body_transform_set(EPhysics_Body *body, btTransform trans)
578 {
579 btTransform origin;
580
581 if (body->type != EPHYSICS_BODY_TYPE_RIGID)
582 {
583 origin = _ephysics_body_transform_get(body);
584 body->soft_body->translate(trans.getOrigin() - origin.getOrigin());
585 return;
586 }
587 body->rigid_body->getMotionState()->setWorldTransform(trans);
588 }
589
590 void
ephysics_body_activate(const EPhysics_Body * body,Eina_Bool activate)591 ephysics_body_activate(const EPhysics_Body *body, Eina_Bool activate)
592 {
593 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
594 {
595 body->rigid_body->activate(activate);
596 return;
597 }
598
599 body->soft_body->activate(activate);
600 }
601
602 static void
_ephysics_body_forces_update(EPhysics_Body * body)603 _ephysics_body_forces_update(EPhysics_Body *body)
604 {
605 body->force.x = body->rigid_body->getTotalForce().getX();
606 body->force.y = body->rigid_body->getTotalForce().getY();
607 body->force.z = body->rigid_body->getTotalForce().getZ();
608 body->force.torque_x = body->rigid_body->getTotalTorque().getX();
609 body->force.torque_y = body->rigid_body->getTotalTorque().getY();
610 body->force.torque_z = body->rigid_body->getTotalTorque().getZ();
611 body->rigid_body->clearForces();
612
613 DBG("forces updated: %lf, %lf, %lf", body->force.x, body->force.y,
614 body->force.z);
615 DBG("torque updated: %lf, %lf, %lf", body->force.torque_x,
616 body->force.torque_y, body->force.torque_z);
617 }
618
619 static inline void
_ephysics_body_sleeping_threshold_set(EPhysics_Body * body,double linear_threshold,double angular_threshold,double rate)620 _ephysics_body_sleeping_threshold_set(EPhysics_Body *body, double linear_threshold, double angular_threshold, double rate)
621 {
622 body->rigid_body->setSleepingThresholds(linear_threshold / rate,
623 angular_threshold / RAD_TO_DEG);
624 }
625
626 static inline void
_ephysics_body_linear_velocity_set(EPhysics_Body * body,double x,double y,double z,double rate)627 _ephysics_body_linear_velocity_set(EPhysics_Body *body, double x, double y, double z, double rate)
628 {
629 btVector3 linear_velocity = btVector3(x / rate, -y / rate, z / rate);
630
631 ephysics_body_activate(body, EINA_TRUE);
632 if (body->rigid_body)
633 body->rigid_body->setLinearVelocity(linear_velocity);
634
635 if (body->soft_body)
636 {
637 for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
638 body->soft_body->m_nodes[i].m_v = linear_velocity;
639 }
640 }
641
642 static void
_ephysics_body_event_callback_del(EPhysics_Body * body,EPhysics_Body_Callback * cb)643 _ephysics_body_event_callback_del(EPhysics_Body *body, EPhysics_Body_Callback *cb)
644 {
645 if (cb->deleted) return;
646
647 cb->deleted = EINA_TRUE;
648
649 if (body->walking)
650 {
651 body->to_delete = eina_list_append(body->to_delete, cb);
652 return;
653 }
654
655 body->callbacks = eina_inlist_remove(body->callbacks, EINA_INLIST_GET(cb));
656 free(cb);
657 }
658
659 static Eina_Bool
_ephysics_body_event_callback_call(EPhysics_Body * body,EPhysics_Callback_Body_Type type,void * event_info)660 _ephysics_body_event_callback_call(EPhysics_Body *body, EPhysics_Callback_Body_Type type, void *event_info)
661 {
662 Eina_Bool called = EINA_FALSE;
663 EPhysics_Body_Callback *cb;
664 void *clb;
665
666 body->walking++;
667 EINA_INLIST_FOREACH(body->callbacks, cb)
668 {
669 if ((cb->type == type) && (!cb->deleted))
670 {
671 cb->func(cb->data, body, event_info);
672 called = EINA_TRUE;
673 }
674 }
675 body->walking--;
676
677 if (body->walking > 0) return called;
678
679 EINA_LIST_FREE(body->to_delete, clb)
680 {
681 cb = (EPhysics_Body_Callback *) clb;
682 body->callbacks = eina_inlist_remove(body->callbacks,
683 EINA_INLIST_GET(cb));
684 free(cb);
685 }
686
687 return called;
688 }
689
690 void
ephysics_body_active_set(EPhysics_Body * body,Eina_Bool active)691 ephysics_body_active_set(EPhysics_Body *body, Eina_Bool active)
692 {
693 if (body->active == !!active) return;
694 body->active = !!active;
695 if (active) return;
696
697 _ephysics_body_event_callback_call(body, EPHYSICS_CALLBACK_BODY_STOPPED,
698 (void *) body->evas_obj);
699 };
700
701 Eina_Bool
ephysics_body_filter_collision(EPhysics_Body * body0,EPhysics_Body * body1)702 ephysics_body_filter_collision(EPhysics_Body *body0, EPhysics_Body *body1)
703 {
704 Eina_List *l;
705 void *grp;
706
707 if ((!body0->collision_groups) || (!body1->collision_groups))
708 return EINA_TRUE;
709
710 EINA_LIST_FOREACH(body0->collision_groups, l, grp)
711 {
712 if (eina_list_data_find(body1->collision_groups, grp))
713 return EINA_TRUE;
714 }
715
716 return EINA_FALSE;
717 }
718
719 EAPI Eina_Bool
ephysics_body_collision_group_add(EPhysics_Body * body,const char * group)720 ephysics_body_collision_group_add(EPhysics_Body *body, const char *group)
721 {
722 Eina_Stringshare *group_str;
723
724 if (!body)
725 {
726 ERR("Can't add body collision group, body is null.");
727 return EINA_FALSE;
728 }
729
730 ephysics_world_lock_take(body->world);
731 group_str = eina_stringshare_add(group);
732 if (eina_list_data_find(body->collision_groups, group_str))
733 {
734 INF("Body already added to group: %s", group);
735 eina_stringshare_del(group_str);
736 ephysics_world_lock_release(body->world);
737 return EINA_TRUE;
738 }
739
740 body->collision_groups = eina_list_append(body->collision_groups, group_str);
741 ephysics_world_lock_release(body->world);
742 return EINA_TRUE;
743 }
744
745 EAPI Eina_Bool
ephysics_body_collision_group_del(EPhysics_Body * body,const char * group)746 ephysics_body_collision_group_del(EPhysics_Body *body, const char *group)
747 {
748 Eina_Stringshare *group_str;
749
750 if (!body)
751 {
752 ERR("Can't remove body collision group, body is null.");
753 return EINA_FALSE;
754 }
755
756 ephysics_world_lock_take(body->world);
757 group_str = eina_stringshare_add(group);
758 if (!eina_list_data_find(body->collision_groups, group_str))
759 {
760 INF("Body isn't part of group: %s", group);
761 eina_stringshare_del(group_str);
762 ephysics_world_lock_release(body->world);
763 return EINA_TRUE;
764 }
765
766 body->collision_groups = eina_list_remove(body->collision_groups, group_str);
767 eina_stringshare_del(group_str);
768 ephysics_world_lock_release(body->world);
769 return EINA_TRUE;
770 }
771
772 EAPI const Eina_List *
ephysics_body_collision_group_list_get(const EPhysics_Body * body)773 ephysics_body_collision_group_list_get(const EPhysics_Body *body)
774 {
775 if (!body)
776 {
777 ERR("Can't get the body's collision group, body is null.");
778 return NULL;
779 }
780
781 return body->collision_groups;
782 }
783
784 static EPhysics_Body *
_ephysics_body_new(EPhysics_World * world,btScalar mass,double cm_x,double cm_y,double cm_z)785 _ephysics_body_new(EPhysics_World *world, btScalar mass, double cm_x, double cm_y, double cm_z)
786 {
787 EPhysics_Body *body;
788 double rate;
789
790 body = (EPhysics_Body *) calloc(1, sizeof(EPhysics_Body));
791 if (!body)
792 {
793 ERR("Couldn't create a new body instance.");
794 return NULL;
795 }
796
797 rate = ephysics_world_rate_get(world);
798 body->scale[0] = 1;
799 body->scale[1] = 1;
800 body->scale[2] = 1;
801 body->size.w = rate;
802 body->size.h = rate;
803 body->size.d = rate;
804 body->mass = mass;
805 body->world = world;
806 body->cm.x = cm_x;
807 body->cm.y = cm_y;
808 body->cm.z = cm_z;
809
810 return body;
811 }
812
813 static EPhysics_Body *
_ephysics_body_rigid_body_add(EPhysics_World * world,btCollisionShape * collision_shape,const char * type,double cm_x,double cm_y,double cm_z)814 _ephysics_body_rigid_body_add(EPhysics_World *world, btCollisionShape *collision_shape, const char *type, double cm_x, double cm_y, double cm_z)
815 {
816 btRigidBody::btRigidBodyConstructionInfo *rigid_body_ci;
817 btDefaultMotionState *motion_state;
818 btRigidBody *rigid_body;
819 EPhysics_Body *body;
820 btScalar mass = 1;
821 btVector3 inertia;
822
823 if (!collision_shape)
824 {
825 ERR("Couldn't create a %s shape.", type);
826 return NULL;
827 }
828
829 body = _ephysics_body_new(world, mass, cm_x, cm_y, cm_z);
830 if (!body)
831 {
832 ERR("Couldn't create a new body instance.");
833 goto err_body;
834 }
835
836 motion_state = new btDefaultMotionState();
837 if (!motion_state)
838 {
839 ERR("Couldn't create a motion state.");
840 goto err_motion_state;
841 }
842
843 inertia = btVector3(0, 0, 0);
844 collision_shape->calculateLocalInertia(mass, inertia);
845
846 rigid_body_ci = new btRigidBody::btRigidBodyConstructionInfo(
847 mass, motion_state, collision_shape, inertia);
848 if (!rigid_body_ci)
849 {
850 ERR("Couldn't create a rigid body construction info.");
851 goto err_rigid_body_ci;
852 }
853
854 rigid_body = new btRigidBody(*rigid_body_ci);
855 if (!rigid_body)
856 {
857 ERR("Couldn't create a rigid body.");
858 goto err_rigid_body;
859 }
860
861 body->type = EPHYSICS_BODY_TYPE_RIGID;
862 body->collision_shape = collision_shape;
863 body->rigid_body = rigid_body;
864 body->rigid_body->setUserPointer(body);
865 body->rigid_body->setLinearFactor(btVector3(1, 1, 0));
866 body->rigid_body->setAngularFactor(btVector3(0, 0, 1));
867
868 if (!ephysics_world_body_add(body->world, body))
869 {
870 ERR("Couldn't add body to world's bodies list");
871 goto err_world_add;
872 }
873
874 delete rigid_body_ci;
875
876 INF("Body %p of type %s added.", body, type);
877 return body;
878
879 err_world_add:
880 delete rigid_body;
881 err_rigid_body:
882 delete rigid_body_ci;
883 err_rigid_body_ci:
884 delete motion_state;
885 err_motion_state:
886 free(body);
887 err_body:
888 delete collision_shape;
889 return NULL;
890 }
891
892 static void
_ephysics_body_efl_canvas_object_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)893 _ephysics_body_efl_canvas_object_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
894 {
895 EPhysics_Body *body = (EPhysics_Body *) data;
896
897 if (body->default_face)
898 _ephysics_body_soft_body_slices_clean(body->default_face->slices);
899
900 body->evas_obj = NULL;
901 DBG("Evas object deleted. Updating body: %p", body);
902 }
903
904 static void
_ephysics_body_soft_body_anchors_rebuild(int node,btRigidBody * rigid_body,btSoftBody * soft_body)905 _ephysics_body_soft_body_anchors_rebuild(int node, btRigidBody *rigid_body, btSoftBody *soft_body)
906 {
907 btTransform world_trans = rigid_body->getWorldTransform();
908 btVector3 local = world_trans.inverse() * soft_body->m_nodes[node].m_x;
909
910 for (int i = 0; i < soft_body->m_anchors.size(); i++)
911 {
912 if (soft_body->m_anchors[i].m_node == &soft_body->m_nodes[node])
913 soft_body->m_anchors[i].m_local = local;
914 }
915 }
916
917 void
ephysics_body_soft_body_bending_constraints_generate(EPhysics_Body * body)918 ephysics_body_soft_body_bending_constraints_generate(EPhysics_Body *body)
919 {
920 btSoftBody *soft_body = body->soft_body;
921
922 for (; body->bending_constraints; body->bending_constraints--)
923 soft_body->generateBendingConstraints(2, soft_body->m_materials
924 [body->material_index]);
925 }
926
927 static void
_ephysics_body_cloth_constraints_rebuild(EPhysics_Body * body)928 _ephysics_body_cloth_constraints_rebuild(EPhysics_Body *body)
929 {
930 btRigidBody *rigid_body;
931 btSoftBody *soft_body;
932 btSoftBody::Node *node;
933 btSoftBody::Anchor anchor;
934 int anchors_size = body->soft_body->m_anchors.size();
935
936 soft_body = body->soft_body;
937
938 if (anchors_size)
939 {
940 rigid_body = soft_body->m_anchors[0].m_body;
941 for (int m = 0; m < anchors_size; m++)
942 {
943 anchor = soft_body->m_anchors[m];
944 node = anchor.m_node;
945 for (int n = 0; n < soft_body->m_nodes.size(); n++)
946 {
947 if (node == &soft_body->m_nodes[n])
948 _ephysics_body_soft_body_anchors_rebuild(n, rigid_body,
949 soft_body);
950 }
951 }
952 }
953 soft_body->generateClusters(0);
954 ephysics_body_soft_body_bending_constraints_generate(body);
955 }
956
957 static void
_ephysics_body_soft_body_constraints_rebuild(EPhysics_Body * body)958 _ephysics_body_soft_body_constraints_rebuild(EPhysics_Body *body)
959 {
960 btSoftBody *soft_body = body->soft_body;
961 btRigidBody *rigid_body = body->rigid_body;
962
963 if (soft_body->m_anchors.size() > 0)
964 {
965 for (int i = 0; i < soft_body->m_nodes.size(); i++)
966 _ephysics_body_soft_body_anchors_rebuild(i, rigid_body, soft_body);
967 }
968 else
969 {
970 for (int i = 0; i < soft_body->m_nodes.size(); i++)
971 soft_body->appendAnchor(i, rigid_body);
972 }
973
974 soft_body->generateClusters(0);
975 ephysics_body_soft_body_bending_constraints_generate(body);
976 }
977
978 inline static double
_ephysics_body_volume_get(const EPhysics_Body * body)979 _ephysics_body_volume_get(const EPhysics_Body *body)
980 {
981 btVector3 vector = body->collision_shape->getLocalScaling();
982 return vector.x() * vector.y() * vector.z();
983 }
984
985 void
_ephysics_body_soft_body_dragging_set(EPhysics_Body * body,int triangle)986 _ephysics_body_soft_body_dragging_set(EPhysics_Body *body, int triangle)
987 {
988 btSoftBody::Face face;
989 btSoftBody::Node *node;
990
991 body->dragging_data.triangle = triangle;
992 body->dragging_data.dragging = EINA_TRUE;
993
994 face = body->soft_body->m_faces[triangle];
995 node = face.m_n[0];
996 body->dragging_data.mass = node->m_im;
997 }
998
999 static void
_ephysics_body_soft_body_mass_set(EPhysics_Body * body,double mass)1000 _ephysics_body_soft_body_mass_set(EPhysics_Body *body, double mass)
1001 {
1002 int valid_nodes;
1003 btSoftBody::Node node;
1004 double inverse_mass = 0.0;
1005
1006 if (body->type == EPHYSICS_BODY_TYPE_SOFT)
1007 body->soft_body->setTotalMass(mass);
1008 else if (mass > 0.0)
1009 {
1010 valid_nodes = 0;
1011 for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
1012 {
1013 node = body->soft_body->m_nodes[i];
1014 if (node.m_im && !node.m_battach)
1015 valid_nodes++;
1016 }
1017
1018 if (valid_nodes > 0)
1019 {
1020 inverse_mass = 1 / (mass / valid_nodes);
1021 if (body->dragging_data.dragging)
1022 {
1023 valid_nodes++;
1024 inverse_mass = 1 / (mass / valid_nodes);
1025 body->dragging_data.mass = inverse_mass;
1026 }
1027 }
1028
1029 for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
1030 {
1031 node = body->soft_body->m_nodes[i];
1032 if (node.m_im && !node.m_battach)
1033 node.m_im = inverse_mass;
1034 }
1035 }
1036 }
1037
1038 static void
_ephysics_body_mass_set(EPhysics_Body * body,double mass)1039 _ephysics_body_mass_set(EPhysics_Body *body, double mass)
1040 {
1041 btVector3 inertia(0, 0, 0);
1042
1043 if (body->density)
1044 mass = body->density * _ephysics_body_volume_get(body);
1045
1046 if (body->soft_body)
1047 _ephysics_body_soft_body_mass_set(body, mass);
1048 else
1049 {
1050 body->collision_shape->calculateLocalInertia(mass, inertia);
1051 body->rigid_body->setMassProps(mass, inertia);
1052 body->rigid_body->updateInertiaTensor();
1053 }
1054
1055 body->mass = mass;
1056 DBG("Body %p mass changed to %lf.", body, mass);
1057 }
1058
1059 static void
_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)1060 _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)
1061 {
1062 double mx, my, mz, sx, sy, sz;
1063 btTransform trans;
1064 int wy, height;
1065 btVector3 body_scale, old_scale;
1066
1067 ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL,
1068 NULL, &height, NULL);
1069 height += wy;
1070
1071 mx = (x + w * body->cm.x) / rate;
1072 my = (height - (y + h * body->cm.y)) / rate;
1073 mz = (z + d * body->cm.z) / rate;
1074 sx = (w <= 0) ? 1 : w / rate;
1075 sy = (h <= 0) ? 1 : h / rate;
1076 sz = (d <= 0) ? 1 : d / rate;
1077
1078 trans = _ephysics_body_transform_get(body);
1079 trans.setOrigin(btVector3(mx, my, mz));
1080 body_scale = btVector3(sx, sy, sz);
1081 old_scale = btVector3(body->scale[0], body->scale[1], body->scale[2]);
1082
1083 if (body->type == EPHYSICS_BODY_TYPE_SOFT)
1084 {
1085 body->soft_body->scale(btVector3(1, 1, 1) / old_scale);
1086 body->soft_body->scale(body_scale);
1087 body->rigid_body->proceedToTransform(trans);
1088 _ephysics_body_transform_set(body, trans);
1089 _ephysics_body_soft_body_constraints_rebuild(body);
1090 }
1091 else if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
1092 {
1093 body->soft_body->setTotalMass(body->mass, true);
1094 body->soft_body->scale(btVector3(1, 1, 1) / old_scale);
1095 body->soft_body->scale(body_scale);
1096 _ephysics_body_transform_set(body, trans);
1097 _ephysics_body_cloth_constraints_rebuild(body);
1098 body->soft_body->setTotalMass(body->mass, false);
1099 _ephysics_body_cloth_anchor_mass_reset(body);
1100 }
1101 else
1102 {
1103 body->collision_shape->setLocalScaling(body_scale);
1104 body->rigid_body->proceedToTransform(trans);
1105
1106 if (!body->rigid_body->isStaticObject())
1107 _ephysics_body_mass_set(body, ephysics_body_mass_get(body));
1108 }
1109
1110 _ephysics_body_transform_set(body, trans);
1111 ephysics_body_activate(body, EINA_TRUE);
1112
1113 body->size.w = w;
1114 body->size.h = h;
1115 body->size.d = d;
1116 body->scale[0] = sx;
1117 body->scale[1] = sy;
1118 body->scale[2] = sz;
1119
1120 DBG("Body %p position changed to (%lf, %lf, %lf).", body, mx, my, mz);
1121 DBG("Body %p scale changed to (%lf, %lf, %lf).", body, sx, sy, sz);
1122 }
1123
1124 static void
_ephysics_body_resize(EPhysics_Body * body,Evas_Coord w,Evas_Coord h,Evas_Coord d)1125 _ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h, Evas_Coord d)
1126 {
1127 Evas_Coord bx, by, bz;
1128 double rate, sx, sy, sz;
1129 btVector3 body_scale, center;
1130 btTransform trans;
1131
1132 rate = ephysics_world_rate_get(body->world);
1133 sx = w / rate;
1134 sy = h / rate;
1135 sz = d / rate;
1136
1137 DBG("Body %p scale changed to (%lf, %lf, %lf).", body, sx, sy, sz);
1138
1139 body_scale = btVector3(sx, sy, sz);
1140 if (body->type == EPHYSICS_BODY_TYPE_SOFT)
1141 {
1142 btVector3 old_scale(body->scale[0], body->scale[1], body->scale[2]);
1143 trans = _ephysics_body_transform_get(body);
1144
1145 body->soft_body->scale(btVector3(1, 1, 1) / old_scale);
1146 body->soft_body->scale(body_scale);
1147
1148 _ephysics_body_transform_set(body, trans);
1149 body->rigid_body->proceedToTransform(trans);
1150
1151 _ephysics_body_soft_body_constraints_rebuild(body);
1152 }
1153 else if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
1154 {
1155 ephysics_body_geometry_get(body, &bx, &by, &bz, NULL, NULL, NULL);
1156 _ephysics_body_geometry_set(body, bx, by, bz, w, h, d, rate);
1157 return;
1158 }
1159 else
1160 {
1161 body->collision_shape->setLocalScaling(body_scale);
1162
1163 if(!body->rigid_body->isStaticObject())
1164 _ephysics_body_mass_set(body, ephysics_body_mass_get(body));
1165 }
1166
1167 body->size.w = w;
1168 body->size.h = h;
1169 body->size.d = d;
1170 body->scale[0] = sx;
1171 body->scale[1] = sy;
1172 body->scale[2] = sz;
1173
1174 ephysics_body_activate(body, EINA_TRUE);
1175 }
1176
1177 static void
_ephysics_body_move(EPhysics_Body * body,Evas_Coord x,Evas_Coord y,Evas_Coord z)1178 _ephysics_body_move(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord z)
1179 {
1180 double rate, mx, my, mz;
1181 btTransform trans;
1182 int wy, height;
1183 btVector3 body_scale;
1184
1185 rate = ephysics_world_rate_get(body->world);
1186 ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL,
1187 NULL, &height, NULL);
1188 height += wy;
1189
1190 mx = (x + body->size.w * body->cm.x) / rate;
1191 my = (height - (y + body->size.h * body->cm.y)) / rate;
1192 mz = (z + body->size.d * body->cm.z) / rate;
1193
1194 trans = _ephysics_body_transform_get(body);
1195 trans.setOrigin(btVector3(mx, my, mz));
1196
1197 if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
1198 _ephysics_body_transform_set(body, trans);
1199 else if (body->type == EPHYSICS_BODY_TYPE_SOFT)
1200 {
1201 _ephysics_body_transform_set(body, trans);
1202 body->rigid_body->proceedToTransform(trans);
1203 body->rigid_body->getMotionState()->setWorldTransform(trans);
1204 }
1205 else
1206 {
1207 body->rigid_body->proceedToTransform(trans);
1208 body->rigid_body->getMotionState()->setWorldTransform(trans);
1209 }
1210
1211 ephysics_body_activate(body, EINA_TRUE);
1212
1213 DBG("Body %p position changed to (%lf, %lf, %lf).", body, mx, my, mz);
1214 }
1215
1216 static void
_ephysics_body_efl_canvas_object_resize_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1217 _ephysics_body_efl_canvas_object_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1218 {
1219 EPhysics_Body *body = (EPhysics_Body *) data;
1220 int w, h;
1221
1222 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1223 if ((w == body->size.w) && (h == body->size.h))
1224 return;
1225
1226 DBG("Resizing body %p to w=%i, h=%i, d=%i", body, w, h, body->size.d);
1227
1228 ephysics_world_lock_take(body->world);
1229 _ephysics_body_resize(body, w, h, body->size.d);
1230
1231 if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
1232 {
1233 _ephysics_body_soft_body_slices_clean(body->default_face->slices);
1234 _ephysics_body_soft_body_slices_init(body, body->evas_obj,
1235 body->default_face->slices);
1236 }
1237
1238 ephysics_world_lock_release(body->world);
1239 }
1240
1241 static void
_ephysics_body_soft_body_evas_restack_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1242 _ephysics_body_soft_body_evas_restack_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1243 {
1244 EPhysics_Body *body = (EPhysics_Body *)data;
1245 Eina_List *slices;
1246 void *ldata;
1247 EPhysics_Body_Soft_Body_Slice *slice;
1248 short layer = evas_object_layer_get(obj);
1249
1250 slices = _ephysics_body_soft_body_slices_get(body);
1251 EINA_LIST_FREE(slices, ldata)
1252 {
1253 slice = (EPhysics_Body_Soft_Body_Slice *)ldata;
1254 evas_object_layer_set(slice->evas_obj, layer);
1255 }
1256 DBG("Body's slices layer reset to: %d", layer);
1257 }
1258
1259 static void
_ephysics_body_face_slice_del(EPhysics_Body_Face_Slice * face_slice)1260 _ephysics_body_face_slice_del(EPhysics_Body_Face_Slice *face_slice)
1261 {
1262 _ephysics_body_soft_body_slices_free(face_slice->slices);
1263 free(face_slice->points_deform);
1264 free(face_slice);
1265 }
1266
1267 static EPhysics_Body_Face_Slice *
_ephysics_body_face_slice_add(EPhysics_Body * body,EPhysics_Body_Face face)1268 _ephysics_body_face_slice_add(EPhysics_Body *body, EPhysics_Body_Face face)
1269 {
1270 EPhysics_Body_Face_Slice *face_slice;
1271
1272 face_slice = (EPhysics_Body_Face_Slice *)calloc(1,
1273 sizeof(EPhysics_Body_Face_Slice));
1274 if (!face_slice)
1275 return NULL;
1276
1277 face_slice->face = face;
1278 body->faces_slices = eina_list_append(body->faces_slices, face_slice);
1279 face_slice->body = body;
1280 return face_slice;
1281 DBG("New face slice added to body %p", body);
1282 }
1283
1284 static EPhysics_Body_Face_Slice *
_ephysics_body_face_slice_get(EPhysics_Body * body,EPhysics_Body_Face face)1285 _ephysics_body_face_slice_get(EPhysics_Body *body, EPhysics_Body_Face face)
1286 {
1287 Eina_List *l;
1288 void *ldata;
1289 EPhysics_Body_Face_Slice *face_slice = NULL;
1290
1291 EINA_LIST_FOREACH(body->faces_slices, l, ldata)
1292 {
1293 if (((EPhysics_Body_Face_Slice *)ldata)->face == face)
1294 {
1295 face_slice = (EPhysics_Body_Face_Slice *)ldata;
1296 break;
1297 }
1298 }
1299
1300 return face_slice;
1301 }
1302
1303 static EPhysics_Body_Face_Obj *
_ephysics_body_face_evas_object_get(EPhysics_Body * body,EPhysics_Body_Face face)1304 _ephysics_body_face_evas_object_get(EPhysics_Body *body, EPhysics_Body_Face face)
1305 {
1306 Eina_List *l;
1307 void *ldata;
1308 EPhysics_Body_Face_Obj *face_obj;
1309
1310 EINA_LIST_FOREACH(body->face_objs, l, ldata)
1311 {
1312 face_obj = (EPhysics_Body_Face_Obj *)ldata;
1313 if (face_obj->face == face)
1314 return face_obj;
1315 }
1316
1317 DBG("Could not find requested face");
1318 return NULL;
1319 }
1320
1321 static void
_ephysics_body_del(EPhysics_Body * body)1322 _ephysics_body_del(EPhysics_Body *body)
1323 {
1324 EPhysics_Body_Callback *cb;
1325 void *ldata;
1326 void *group;
1327 EPhysics_Body_Face_Slice *face_slice;
1328
1329 if (body->evas_obj)
1330 {
1331 evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_DEL,
1332 _ephysics_body_efl_canvas_object_del_cb);
1333 evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_RESIZE,
1334 _ephysics_body_efl_canvas_object_resize_cb);
1335
1336 if (body->faces_slices)
1337 evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_RESTACK,
1338 _ephysics_body_soft_body_evas_restack_cb);
1339 }
1340
1341 while (body->callbacks)
1342 {
1343 cb = EINA_INLIST_CONTAINER_GET(body->callbacks,
1344 EPhysics_Body_Callback);
1345 body->callbacks = eina_inlist_remove(body->callbacks, body->callbacks);
1346 free(cb);
1347 }
1348
1349 ephysics_constraint_body_del(body);
1350
1351 EINA_LIST_FREE(body->collision_groups, group)
1352 eina_stringshare_del((Eina_Stringshare *)group);
1353
1354 EINA_LIST_FREE(body->faces_slices, ldata)
1355 {
1356 face_slice = (EPhysics_Body_Face_Slice *)ldata;
1357 if (_ephysics_body_face_evas_object_get(body, face_slice->face))
1358 ephysics_body_face_evas_object_unset(body, face_slice->face);
1359 _ephysics_body_face_slice_del(face_slice);
1360 }
1361
1362 if (body->rigid_body)
1363 {
1364 delete body->rigid_body->getMotionState();
1365 delete body->collision_shape;
1366 delete body->rigid_body;
1367 }
1368
1369 delete body->soft_body;
1370
1371 free(body);
1372 }
1373
1374 static void
_ephysics_body_evas_object_map_apply(EPhysics_Body * body,Evas_Map * map,Evas_Object * obj,Eina_Bool bfc,Eina_Bool update_cw)1375 _ephysics_body_evas_object_map_apply(EPhysics_Body *body, Evas_Map *map, Evas_Object *obj, Eina_Bool bfc, Eina_Bool update_cw)
1376 {
1377 EPhysics_Camera *camera = ephysics_world_camera_get(body->world);
1378
1379 if (ephysics_camera_perspective_enabled_get(camera))
1380 {
1381 int px, py, z0, foc;
1382 ephysics_camera_perspective_get(camera, &px, &py, &z0, &foc);
1383 evas_map_util_3d_perspective(map, px, py, z0, foc);
1384 }
1385
1386 if (bfc)
1387 {
1388 if (evas_map_util_clockwise_get(map))
1389 {
1390 if (update_cw)
1391 body->clockwise = EINA_TRUE;
1392 evas_object_show(obj);
1393 }
1394 else
1395 {
1396 if (update_cw)
1397 body->clockwise = EINA_FALSE;
1398 evas_map_free(map);
1399 evas_object_hide(obj);
1400 return;
1401 }
1402 }
1403 else
1404 evas_object_show(obj);
1405
1406 if ((body->light_apply) ||
1407 (ephysics_world_light_all_bodies_get(body->world)))
1408 {
1409 int lr, lg, lb, ar, ag, ab;
1410 Evas_Coord lx, ly, lz;
1411
1412 ephysics_world_point_light_position_get(body->world, &lx, &ly, &lz);
1413 ephysics_world_point_light_color_get(body->world, &lr, &lg, &lb);
1414 ephysics_world_ambient_light_color_get(body->world, &ar, &ag, &ab);
1415 evas_map_util_3d_lighting(map, lx, ly, lz, lr, lg, lb, ar, ag, ab);
1416 }
1417
1418 evas_object_map_set(obj, map);
1419 evas_object_map_enable_set(obj, EINA_TRUE);
1420 evas_map_free(map);
1421 }
1422
1423 static void
_ephysics_cloth_face_objs_update(EPhysics_Body * body EINA_UNUSED)1424 _ephysics_cloth_face_objs_update(EPhysics_Body *body EINA_UNUSED)
1425 {
1426
1427 }
1428
1429 static void
_ephysics_cylinder_face_objs_update(EPhysics_Body * body)1430 _ephysics_cylinder_face_objs_update(EPhysics_Body *body)
1431 {
1432 int bx, by, x, y, z, wx, wy, wh, cx, cy;
1433 EPhysics_Body_Face_Obj *face_obj;
1434 EPhysics_Camera *camera;
1435 btQuaternion quat;
1436 btTransform trans;
1437 Evas_Map *map;
1438 Eina_List *l;
1439 double rate;
1440 void *ldata;
1441
1442 ephysics_world_render_geometry_get(body->world, &wx, &wy, NULL,
1443 NULL, &wh, NULL);
1444 camera = ephysics_world_camera_get(body->world);
1445 ephysics_camera_position_get(camera, &cx, &cy);
1446 cx -= wx;
1447 cy -= wy;
1448
1449 rate = ephysics_world_rate_get(body->world);
1450 trans = _ephysics_body_transform_get(body);
1451
1452 bx = (int) (trans.getOrigin().getX() * rate) - cx;
1453 by = wh + wy - (int) (trans.getOrigin().getY() * rate) - cy;
1454 x = bx - body->size.w / 2;
1455 y = by - body->size.h / 2;
1456 z = (int) (trans.getOrigin().getZ() * rate);
1457
1458 quat = trans.getRotation();
1459 quat.normalize();
1460
1461 EINA_LIST_FOREACH(body->face_objs, l, ldata)
1462 {
1463 Evas_Object *obj;
1464 Evas_Coord w, h;
1465
1466 face_obj = (EPhysics_Body_Face_Obj *)ldata;
1467 obj = face_obj->obj;
1468
1469 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1470 evas_object_move(obj, x, y);
1471 if ((!w) || (!h))
1472 {
1473 DBG("Evas object with no geometry: %p, w=%i h=%i", obj, w, h);
1474 continue;
1475 }
1476
1477 map = evas_map_new(4);
1478
1479 switch(face_obj->face)
1480 {
1481 case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT:
1482 evas_map_util_points_populate_from_object_full(map, obj, z);
1483 break;
1484 case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_BACK:
1485 evas_map_util_points_populate_from_object_full(map, obj, z + 1);
1486 evas_map_util_3d_rotate(map, 0, 180, 0, bx, by, z + 1);
1487 break;
1488 case EPHYSICS_BODY_CYLINDER_FACE_FRONT:
1489 evas_map_util_points_populate_from_object_full(
1490 map, obj, z - body->size.d / 2);
1491 break;
1492 case EPHYSICS_BODY_CYLINDER_FACE_BACK:
1493 evas_map_util_points_populate_from_object_full(
1494 map, obj, z + body->size.d / 2);
1495 evas_map_util_3d_rotate(map, 0, 180, 0, bx, by,
1496 z + body->size.d / 2);
1497 break;
1498 default:
1499 WRN("Face %i not updated", face_obj->face);
1500 evas_map_free(map);
1501 continue;
1502 }
1503
1504 evas_map_util_quat_rotate(map, quat.x(), -quat.y(), quat.z(), -quat.w(),
1505 bx, by, z);
1506
1507 _ephysics_body_evas_object_map_apply(body, map, obj, EINA_TRUE,
1508 EINA_FALSE);
1509 }
1510 }
1511
1512 static void
_ephysics_box_face_objs_update(EPhysics_Body * body)1513 _ephysics_box_face_objs_update(EPhysics_Body *body)
1514 {
1515 EPhysics_Body_Face_Obj *face_obj;
1516 int i, x, y, z, wx, wy, wh, cx, cy;
1517 EPhysics_Camera *camera;
1518 Evas_Coord v[8][3];
1519 btQuaternion quat;
1520 btTransform trans;
1521 btBoxShape *shape;
1522 Evas_Map *map;
1523 Eina_List *l;
1524 double rate;
1525 void *ldata;
1526
1527 ephysics_world_render_geometry_get(body->world, &wx, &wy, NULL,
1528 NULL, &wh, NULL);
1529 camera = ephysics_world_camera_get(body->world);
1530 ephysics_camera_position_get(camera, &cx, &cy);
1531 cx -= wx;
1532 cy -= wy;
1533
1534 rate = ephysics_world_rate_get(body->world);
1535 trans = _ephysics_body_transform_get(body);
1536
1537 x = (int) (trans.getOrigin().getX() * rate) - cx;
1538 y = wh + wy - (int) (trans.getOrigin().getY() * rate) - cy;
1539 z = (int) (trans.getOrigin().getZ() * rate);
1540
1541 shape = (btBoxShape *) body->collision_shape;
1542 for (i = 0; i < 8; i++)
1543 {
1544 btVector3 vertice;
1545 shape->getVertex(i, vertice);
1546 v[i][0] = vertice.getX() * rate + x;
1547 v[i][1] = - vertice.getY() * rate + y;
1548 v[i][2] = vertice.getZ() * rate + z;
1549 }
1550
1551 quat = trans.getRotation();
1552 quat.normalize();
1553
1554 EINA_LIST_FOREACH(body->face_objs, l, ldata)
1555 {
1556 Evas_Object *obj;
1557 Evas_Coord w, h;
1558
1559 face_obj = (EPhysics_Body_Face_Obj *)ldata;
1560 obj = face_obj->obj;
1561 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1562
1563 map = evas_map_new(4);
1564 evas_map_point_image_uv_set(map, 0, 0, 0);
1565 evas_map_point_image_uv_set(map, 1, w, 0);
1566 evas_map_point_image_uv_set(map, 2, w, h);
1567 evas_map_point_image_uv_set(map, 3, 0, h);
1568
1569 switch(face_obj->face)
1570 {
1571 case EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT:
1572 evas_map_point_coord_set(map, 0, v[5][0], v[5][1], z);
1573 evas_map_point_coord_set(map, 1, v[4][0], v[4][1], z);
1574 evas_map_point_coord_set(map, 2, v[6][0], v[6][1], z);
1575 evas_map_point_coord_set(map, 3, v[7][0], v[7][1], z);
1576 break;
1577 case EPHYSICS_BODY_BOX_FACE_MIDDLE_BACK:
1578 evas_map_point_coord_set(map, 0, v[0][0], v[0][1], z);
1579 evas_map_point_coord_set(map, 1, v[1][0], v[1][1], z);
1580 evas_map_point_coord_set(map, 2, v[3][0], v[3][1], z);
1581 evas_map_point_coord_set(map, 3, v[2][0], v[2][1], z);
1582 break;
1583 case EPHYSICS_BODY_BOX_FACE_FRONT:
1584 evas_map_point_coord_set(map, 0, v[5][0], v[5][1], v[5][2]);
1585 evas_map_point_coord_set(map, 1, v[4][0], v[4][1], v[4][2]);
1586 evas_map_point_coord_set(map, 2, v[6][0], v[6][1], v[6][2]);
1587 evas_map_point_coord_set(map, 3, v[7][0], v[7][1], v[7][2]);
1588 break;
1589 case EPHYSICS_BODY_BOX_FACE_BACK:
1590 evas_map_point_coord_set(map, 0, v[0][0], v[0][1], v[0][2]);
1591 evas_map_point_coord_set(map, 1, v[1][0], v[1][1], v[1][2]);
1592 evas_map_point_coord_set(map, 2, v[3][0], v[3][1], v[3][2]);
1593 evas_map_point_coord_set(map, 3, v[2][0], v[2][1], v[2][2]);
1594 break;
1595 case EPHYSICS_BODY_BOX_FACE_RIGHT:
1596 evas_map_point_coord_set(map, 0, v[4][0], v[4][1], v[4][2]);
1597 evas_map_point_coord_set(map, 1, v[0][0], v[0][1], v[0][2]);
1598 evas_map_point_coord_set(map, 2, v[2][0], v[2][1], v[2][2]);
1599 evas_map_point_coord_set(map, 3, v[6][0], v[6][1], v[6][2]);
1600 break;
1601 case EPHYSICS_BODY_BOX_FACE_LEFT:
1602 evas_map_point_coord_set(map, 0, v[1][0], v[1][1], v[1][2]);
1603 evas_map_point_coord_set(map, 1, v[5][0], v[5][1], v[5][2]);
1604 evas_map_point_coord_set(map, 2, v[7][0], v[7][1], v[7][2]);
1605 evas_map_point_coord_set(map, 3, v[3][0], v[3][1], v[3][2]);
1606 break;
1607 case EPHYSICS_BODY_BOX_FACE_TOP:
1608 evas_map_point_coord_set(map, 0, v[1][0], v[1][1], v[1][2]);
1609 evas_map_point_coord_set(map, 1, v[0][0], v[0][1], v[0][2]);
1610 evas_map_point_coord_set(map, 2, v[4][0], v[4][1], v[4][2]);
1611 evas_map_point_coord_set(map, 3, v[5][0], v[5][1], v[5][2]);
1612 break;
1613 case EPHYSICS_BODY_BOX_FACE_BOTTOM:
1614 evas_map_point_coord_set(map, 0, v[7][0], v[7][1], v[7][2]);
1615 evas_map_point_coord_set(map, 1, v[6][0], v[6][1], v[6][2]);
1616 evas_map_point_coord_set(map, 2, v[2][0], v[2][1], v[2][2]);
1617 evas_map_point_coord_set(map, 3, v[3][0], v[3][1], v[3][2]);
1618 break;
1619 default:
1620 WRN("Face %i not updated", face_obj->face);
1621 evas_map_free(map);
1622 continue;
1623 }
1624
1625 evas_map_util_quat_rotate(map, quat.x(), -quat.y(), quat.z(), -quat.w(),
1626 x, y, z);
1627 _ephysics_body_evas_object_map_apply(body, map, obj, EINA_TRUE,
1628 EINA_FALSE);
1629 }
1630 }
1631
1632 static void
_ephysics_body_evas_object_update(EPhysics_Body * body,Evas_Object * evas_obj)1633 _ephysics_body_evas_object_update(EPhysics_Body *body, Evas_Object *evas_obj)
1634 {
1635 int bx, by, x, y, z, w, h, wx, wy, wh, cx, cy;
1636 EPhysics_Camera *camera;
1637 btTransform trans;
1638 btQuaternion quat;
1639 Evas_Map *map;
1640 double rate;
1641
1642 trans = _ephysics_body_transform_get(body);
1643 ephysics_world_render_geometry_get(body->world, &wx, &wy, NULL,
1644 NULL, &wh, NULL);
1645 camera = ephysics_world_camera_get(body->world);
1646 ephysics_camera_position_get(camera, &cx, &cy);
1647 cx -= wx;
1648 cy -= wy;
1649
1650 evas_object_geometry_get(evas_obj, NULL, NULL, &w, &h);
1651 rate = ephysics_world_rate_get(body->world);
1652 bx = (int) (trans.getOrigin().getX() * rate) - cx;
1653 by = wh + wy - (int) (trans.getOrigin().getY() * rate) - cy;
1654 x = bx - w * body->cm.x;
1655 y = by - h * body->cm.y;
1656 z = (int) (trans.getOrigin().getZ() * rate);
1657
1658 evas_object_move(evas_obj, x, y);
1659
1660 if ((!w) || (!h))
1661 {
1662 DBG("Evas object with no geometry: %p, w=%i h=%i", evas_obj, w, h);
1663 return;
1664 }
1665
1666 if (body->type != EPHYSICS_BODY_TYPE_RIGID)
1667 {
1668 if (!body->back_face_culling)
1669 evas_object_show(body->evas_obj);
1670 _ephysics_body_soft_body_slices_apply(body, body->evas_obj,
1671 body->default_face->slices);
1672 return;
1673 }
1674
1675 map = evas_map_new(4);
1676 evas_map_util_points_populate_from_object(map, body->evas_obj);
1677
1678 quat = trans.getRotation();
1679 quat.normalize();
1680 evas_map_util_quat_rotate(map, quat.x(), -quat.y(), quat.z(), -quat.w(),
1681 bx, by, z);
1682
1683 _ephysics_body_evas_object_map_apply(body, map, evas_obj,
1684 body->back_face_culling, EINA_TRUE);
1685 }
1686
1687 static void
_ephysics_body_soft_body_update(EPhysics_Body * body)1688 _ephysics_body_soft_body_update(EPhysics_Body *body)
1689 {
1690 Eina_List *l;
1691 void *ldata;
1692 EPhysics_Body_Face_Slice *face_slice;
1693 EPhysics_Body_Face_Obj *face_obj;
1694
1695 EINA_LIST_FOREACH(body->faces_slices, l, ldata)
1696 {
1697 face_slice = (EPhysics_Body_Face_Slice *)ldata;
1698 face_obj = _ephysics_body_face_evas_object_get(body,
1699 face_slice->face);
1700 if (!face_obj) continue;
1701 _ephysics_body_soft_body_slices_apply(body, face_obj->obj,
1702 face_slice->slices);
1703 }
1704 }
1705
1706 static void
_ephysics_body_evas_object_default_update(EPhysics_Body * body)1707 _ephysics_body_evas_object_default_update(EPhysics_Body *body)
1708 {
1709 if (body->face_objs)
1710 {
1711 if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
1712 _ephysics_cloth_face_objs_update(body);
1713 else if (body->type == EPHYSICS_BODY_TYPE_RIGID)
1714 {
1715 if (body->shape == EPHYSICS_BODY_SHAPE_CYLINDER)
1716 _ephysics_cylinder_face_objs_update(body);
1717 else if (body->shape == EPHYSICS_BODY_SHAPE_BOX)
1718 _ephysics_box_face_objs_update(body);
1719 }
1720 else if (body->type == EPHYSICS_BODY_TYPE_SOFT)
1721 _ephysics_body_soft_body_update(body);
1722
1723 if (body->evas_obj)
1724 evas_object_hide(body->evas_obj);
1725
1726 return;
1727 }
1728
1729 if (!body->evas_obj)
1730 return;
1731
1732 _ephysics_body_evas_object_update(body, body->evas_obj);
1733 }
1734
1735 static void
_ephysics_body_outside_render_area_check(EPhysics_Body * body)1736 _ephysics_body_outside_render_area_check(EPhysics_Body *body)
1737 {
1738 int wx, wy, wz, ww, wh, wd, bx, by, bz, bw, bh, bd;
1739
1740 ephysics_world_render_geometry_get(body->world, &wx, &wy, &wz,
1741 &ww, &wh, &wd);
1742 ephysics_body_geometry_get(body, &bx, &by, &bz, &bw, &bh, &bd);
1743
1744 // FIXME: check what should be done regarding rotated bodies
1745 if (((ephysics_world_bodies_outside_top_autodel_get(body->world)) &&
1746 (by + bh < wy)) ||
1747 ((ephysics_world_bodies_outside_bottom_autodel_get(body->world)) &&
1748 (by > wy + wh)) ||
1749 ((ephysics_world_bodies_outside_left_autodel_get(body->world)) &&
1750 (bx + bh < wx)) ||
1751 ((ephysics_world_bodies_outside_right_autodel_get(body->world)) &&
1752 (bx > wx + ww)) ||
1753 ((ephysics_world_bodies_outside_front_autodel_get(body->world)) &&
1754 (bz + bd < wz)) ||
1755 ((ephysics_world_bodies_outside_back_autodel_get(body->world)) &&
1756 (bz > wz + wd)))
1757 {
1758 DBG("Body %p out of render area", body);
1759 ephysics_body_del(body);
1760 }
1761 }
1762
1763 void
ephysics_body_forces_apply(EPhysics_Body * body)1764 ephysics_body_forces_apply(EPhysics_Body *body)
1765 {
1766 if (!((body->force.x) || (body->force.y) || (body->force.z) ||
1767 (body->force.torque_x) || (body->force.torque_y) ||
1768 (body->force.torque_z)))
1769 return;
1770
1771 DBG("body: %p, applying forces: %lf, %lf, %lf", body, body->force.x,
1772 body->force.y, body->force.z);
1773
1774 ephysics_body_activate(body, EINA_TRUE);
1775 body->rigid_body->applyCentralForce(btVector3(body->force.x,
1776 body->force.y,
1777 body->force.z));
1778 body->rigid_body->applyTorque(btVector3(body->force.torque_x,
1779 body->force.torque_y,
1780 body->force.torque_z));
1781 }
1782
1783 void
ephysics_body_recalc(EPhysics_Body * body,double rate)1784 ephysics_body_recalc(EPhysics_Body *body, double rate)
1785 {
1786 Evas_Coord x, y, z, w, h, d;
1787 double vx, vy, vz, lt, at;
1788
1789 ephysics_body_geometry_get(body, &x, &y, &z, &w, &h, &d);
1790 ephysics_body_linear_velocity_get(body, &vx, &vy, &vz);
1791 ephysics_body_sleeping_threshold_get(body, <, &at);
1792
1793 _ephysics_body_geometry_set(body, x, y, z, w, h, d, rate);
1794 _ephysics_body_linear_velocity_set(body, vx, vy, vz, rate);
1795 _ephysics_body_sleeping_threshold_set(body, lt, at, rate);
1796 }
1797
1798 void
ephysics_body_evas_object_update_select(EPhysics_Body * body)1799 ephysics_body_evas_object_update_select(EPhysics_Body *body)
1800 {
1801 Eina_Bool callback_called = EINA_FALSE;
1802
1803 if (!body || body->deleted)
1804 return;
1805
1806 callback_called = _ephysics_body_event_callback_call(
1807 body, EPHYSICS_CALLBACK_BODY_UPDATE, (void *) body->evas_obj);
1808
1809 if (!callback_called)
1810 _ephysics_body_evas_object_default_update(body);
1811
1812 if (ephysics_world_bodies_outside_autodel_get(body->world))
1813 _ephysics_body_outside_render_area_check(body);
1814 }
1815
1816 EAPI void
ephysics_body_collision_position_get(const EPhysics_Body_Collision * collision,Evas_Coord * x,Evas_Coord * y,Evas_Coord * z)1817 ephysics_body_collision_position_get(const EPhysics_Body_Collision *collision, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
1818 {
1819 if (!collision)
1820 {
1821 ERR("Can't get body's collision data, collision is null.");
1822 return;
1823 }
1824
1825 if (x) *x = collision->x;
1826 if (y) *y = collision->y;
1827 if (z) *z = collision->z;
1828 }
1829
1830 EAPI EPhysics_Body *
ephysics_body_collision_contact_body_get(const EPhysics_Body_Collision * collision)1831 ephysics_body_collision_contact_body_get(const EPhysics_Body_Collision *collision)
1832 {
1833 if (!collision)
1834 {
1835 ERR("Can't get body's collision contact body, collision is null.");
1836 return NULL;
1837 }
1838
1839 return collision->contact_body;
1840 }
1841
1842 void
ephysics_body_contact_processed(EPhysics_Body * body,EPhysics_Body * contact_body,btVector3 position)1843 ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body, btVector3 position)
1844 {
1845 EPhysics_Body_Collision *collision;
1846 EPhysics_World *world;;
1847 double rate;
1848 int wy, wh;
1849
1850 if ((!body) || (!contact_body) || (body->collision_cb < 1))
1851 return;
1852
1853 collision = (EPhysics_Body_Collision *)calloc(
1854 1, sizeof(EPhysics_Body_Collision));
1855
1856 if (!collision)
1857 {
1858 ERR("Can't allocate collision data structure.");
1859 return;
1860 }
1861
1862 world = contact_body->world;
1863 ephysics_world_render_geometry_get(world, NULL, &wy, NULL, NULL, &wh, NULL);
1864 rate = ephysics_world_rate_get(world);
1865
1866 collision->contact_body = contact_body;
1867 collision->x = position.getX() * rate;
1868 collision->y = wh + wy - (position.getY() * rate);
1869 collision->z = position.getZ() * rate;
1870
1871 _ephysics_body_event_callback_call(body, EPHYSICS_CALLBACK_BODY_COLLISION,
1872 (void *) collision);
1873
1874 free(collision);
1875 }
1876
1877 btRigidBody *
ephysics_body_rigid_body_get(const EPhysics_Body * body)1878 ephysics_body_rigid_body_get(const EPhysics_Body *body)
1879 {
1880 return body->rigid_body;
1881 }
1882
1883 btSoftBody *
ephysics_body_soft_body_get(const EPhysics_Body * body)1884 ephysics_body_soft_body_get(const EPhysics_Body *body)
1885 {
1886 return body->soft_body;
1887 }
1888
1889 EAPI void
ephysics_body_soft_body_anchor_hardness_set(EPhysics_Body * body,double hardness)1890 ephysics_body_soft_body_anchor_hardness_set(EPhysics_Body *body, double hardness)
1891 {
1892 if (!body)
1893 {
1894 ERR("Can't set soft body's anchor hardness, body is null.");
1895 return;
1896 }
1897
1898 if (!body->soft_body)
1899 {
1900 ERR("Can't set soft body's anchor hardness, body seems not to be a soft"
1901 " body.");
1902 return;
1903 }
1904
1905 if (hardness < 0 || hardness > 100)
1906 {
1907 ERR("Can't set soft body's anchor hardness, it must be between 0 and"
1908 " 100.");
1909 return;
1910 }
1911
1912 ephysics_world_lock_take(body->world);
1913 body->anchor_hardness = EINA_TRUE;
1914 body->soft_body->m_cfg.kAHR = 1 - (hardness / 100);
1915 ephysics_world_lock_release(body->world);
1916 DBG("Soft body anchor hardness set to: %lf", hardness);
1917 }
1918
1919 EAPI double
ephysics_body_soft_body_anchor_hardness_get(EPhysics_Body * body)1920 ephysics_body_soft_body_anchor_hardness_get(EPhysics_Body *body)
1921 {
1922 if (!body)
1923 {
1924 ERR("Can't get soft body's anchor hardness, body is null.");
1925 return -1;
1926 }
1927
1928 if (!body->soft_body)
1929 {
1930 ERR("Can't get soft body's anchor hardness, body seems not to be a soft"
1931 " body.");
1932 return -1;
1933 }
1934
1935 return body->soft_body->m_cfg.kAHR * 100;
1936 }
1937
1938 EAPI void
ephysics_body_soft_body_drag_coefficient_set(EPhysics_Body * body,double coefficient)1939 ephysics_body_soft_body_drag_coefficient_set(EPhysics_Body *body, double coefficient)
1940 {
1941 if (!body)
1942 {
1943 ERR("Can't set soft body's drag coefficient, body is null.");
1944 return;
1945 }
1946
1947 if (!body->soft_body)
1948 {
1949 ERR("Can't set soft body's drag coefficient, body seems not to be a soft"
1950 " body.");
1951 return;
1952 }
1953
1954 body->soft_body->m_cfg.kDG = coefficient;
1955 DBG("Soft body drag coefficient set to: %lf", coefficient);
1956 }
1957
1958 EAPI double
ephysics_body_soft_body_drag_coefficient_get(const EPhysics_Body * body)1959 ephysics_body_soft_body_drag_coefficient_get(const EPhysics_Body *body)
1960 {
1961 if (!body)
1962 {
1963 ERR("Can't get soft body's drag coefficient, body is null.");
1964 return -1;
1965 }
1966
1967 if (!body->soft_body)
1968 {
1969 ERR("Can't get soft body's drag coefficient, body seems not to be a soft"
1970 " body.");
1971 return -1;
1972 }
1973
1974 return body->soft_body->m_cfg.kDG;
1975 }
1976
1977 static void
_ephysics_body_soft_body_hardness_set(EPhysics_Body * body,double hardness)1978 _ephysics_body_soft_body_hardness_set(EPhysics_Body *body, double hardness)
1979 {
1980 int m = body->material_index;
1981 btSoftBody *soft_body = body->soft_body;
1982
1983 if (!body->anchor_hardness)
1984 {
1985 if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
1986 soft_body->m_cfg.kAHR = 0.8;
1987 else
1988 soft_body->m_cfg.kAHR = (hardness / 1000) * 0.6;
1989 }
1990
1991 soft_body->m_materials[m]->m_kVST = (hardness / 1000);
1992 soft_body->m_materials[m]->m_kLST = (hardness / 1000);
1993 soft_body->m_materials[m]->m_kAST = (hardness / 1000);
1994
1995 DBG("Soft body %p hardness set to %lf.", body, hardness);
1996 }
1997
1998 EAPI void
ephysics_body_soft_body_hardness_set(EPhysics_Body * body,double hardness)1999 ephysics_body_soft_body_hardness_set(EPhysics_Body *body, double hardness)
2000 {
2001 if (!body)
2002 {
2003 ERR("Can't set soft body's hardness, body is null.");
2004 return;
2005 }
2006
2007 if (!body->soft_body)
2008 {
2009 ERR("Can't set soft body's hardness, body seems not to be a soft body.");
2010 return;
2011 }
2012
2013 if (hardness < 0 || hardness > 100)
2014 {
2015 ERR("Can't set soft body's hardness, it must be between 0 and 100.");
2016 return;
2017 }
2018
2019 ephysics_world_lock_take(body->world);
2020 _ephysics_body_soft_body_hardness_set(body, hardness);
2021 ephysics_world_lock_release(body->world);
2022 }
2023
2024 EAPI void
ephysics_body_soft_body_dragging_set(EPhysics_Body * body,int triangle)2025 ephysics_body_soft_body_dragging_set(EPhysics_Body *body, int triangle)
2026 {
2027 if (!body)
2028 {
2029 ERR("Can't set soft body dragging status, body is null.");
2030 return;
2031 }
2032
2033 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
2034 {
2035 ERR("Can set soft body dragging status, body must not be a rigid body.");
2036 return;
2037 }
2038
2039 if (triangle < 0 || triangle >= body->soft_body->m_faces.size())
2040 {
2041 ERR("Could not move soft body triangle, provided body triangle index "
2042 "ranges from 0 to %d", body->soft_body->m_faces.size());
2043 return;
2044 }
2045
2046 ephysics_world_lock_take(body->world);
2047 _ephysics_body_soft_body_dragging_set(body, triangle);
2048 ephysics_world_lock_release(body->world);
2049
2050 DBG("Body %p appended to world's dragging bodies list.", body);
2051 }
2052
2053 EAPI void
ephysics_body_soft_body_dragging_unset(EPhysics_Body * body)2054 ephysics_body_soft_body_dragging_unset(EPhysics_Body *body)
2055 {
2056 btSoftBody::Face face;
2057 btSoftBody::Node *node;
2058
2059 if (!body)
2060 {
2061 ERR("Can't unset soft body dragging status, body is null.");
2062 return;
2063 }
2064
2065 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
2066 {
2067 ERR("Can unset soft body dragging status, body must not be a rigid"
2068 " body.");
2069 return;
2070 }
2071
2072 if (!body->dragging_data.dragging)
2073 {
2074 INF("Dragging isn't set");
2075 return;
2076 }
2077
2078 ephysics_world_lock_take(body->world);
2079 face = body->soft_body->m_faces[body->dragging_data.triangle];
2080 node = face.m_n[0];
2081 node->m_im = body->dragging_data.mass;
2082
2083 body->dragging_data.mass = 0;
2084 body->dragging_data.dragging = EINA_FALSE;
2085 body->dragging_data.triangle = 0;
2086 ephysics_world_lock_release(body->world);
2087 }
2088
2089 EAPI double
ephysics_body_soft_body_hardness_get(const EPhysics_Body * body)2090 ephysics_body_soft_body_hardness_get(const EPhysics_Body *body)
2091 {
2092 if (!body)
2093 {
2094 ERR("Can't get soft body's hardness, body is null.");
2095 return 0;
2096 }
2097
2098 if (!body->soft_body)
2099 {
2100 ERR("Can't get soft body's hardness, body seems not to be a soft body.");
2101 return 0;
2102 }
2103
2104 return (body->soft_body->m_materials[body->material_index]->m_kVST * 100);
2105 }
2106
2107 static void
_ephysics_body_soft_body_default_config(EPhysics_Body * body,btSoftBody * soft_body)2108 _ephysics_body_soft_body_default_config(EPhysics_Body *body, btSoftBody *soft_body)
2109 {
2110 body->bending_constraints = 1;
2111 body->soft_body = soft_body;
2112 body->soft_body->getCollisionShape()->setMargin(btScalar(0.02));
2113 body->soft_body->setUserPointer(body);
2114 body->soft_body->setTotalMass(body->mass);
2115
2116 body->soft_body->m_cfg.collisions += btSoftBody::fCollision::SDF_RS;
2117 body->soft_body->m_cfg.collisions += btSoftBody::fCollision::VF_SS;
2118 _ephysics_body_soft_body_hardness_set(body, 100);
2119 }
2120
2121 static EPhysics_Body *
_ephysics_body_soft_body_add(EPhysics_World * world,btCollisionShape * collision_shape,btSoftBody * soft_body)2122 _ephysics_body_soft_body_add(EPhysics_World *world, btCollisionShape *collision_shape, btSoftBody *soft_body)
2123 {
2124 EPhysics_Body *body;
2125
2126 body = _ephysics_body_rigid_body_add(world, collision_shape, "soft box", 0.5,
2127 0.5, 0.5);
2128 if (!body) return NULL;
2129
2130 body->material_index = 0;
2131 body->type = EPHYSICS_BODY_TYPE_SOFT;
2132 _ephysics_body_soft_body_default_config(body, soft_body);
2133
2134 body->rigid_body->setCollisionFlags(
2135 btCollisionObject::CF_NO_CONTACT_RESPONSE);
2136
2137 _ephysics_body_soft_body_constraints_rebuild(body);
2138 ephysics_world_soft_body_add(world, body);
2139
2140 return body;
2141 }
2142
2143 EAPI void
ephysics_body_cloth_anchor_full_add(EPhysics_Body * body1,EPhysics_Body * body2,EPhysics_Body_Cloth_Anchor_Side side)2144 ephysics_body_cloth_anchor_full_add(EPhysics_Body *body1, EPhysics_Body *body2, EPhysics_Body_Cloth_Anchor_Side side)
2145 {
2146 int rows;
2147 int columns;
2148
2149 if (!body1 || !body2)
2150 {
2151 ERR("Could not add anchors, body1 or body2 is null");
2152 return;
2153 }
2154
2155 if (body1->type != EPHYSICS_BODY_TYPE_CLOTH ||
2156 body2->type != EPHYSICS_BODY_TYPE_RIGID)
2157 {
2158 ERR("Cloth anchors are allowed only between cloth and rigid body.");
2159 return;
2160 }
2161
2162 if ((side < 0) || (side >= EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_LAST))
2163 {
2164 ERR("Could not add anchors, side is invalid.");
2165 return;
2166 }
2167
2168 rows = body1->cloth_rows + 1;
2169 columns = body1->cloth_columns + 1;
2170
2171 if (side == EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_RIGHT)
2172 {
2173 for (int i = 0; i < rows; i++)
2174 body1->soft_body->appendAnchor(i, body2->rigid_body);
2175 goto mass_reset;
2176 }
2177
2178 if (side == EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_LEFT)
2179 {
2180 for (int i = 1; i <= rows; i++)
2181 body1->soft_body->appendAnchor((rows * columns) - i,
2182 body2->rigid_body);
2183 goto mass_reset;
2184 }
2185
2186 if (side == EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_BOTTOM)
2187 {
2188 for (int i = 0; i <= rows; i++)
2189 body1->soft_body->appendAnchor(i * rows, body2->rigid_body);
2190 goto mass_reset;
2191 }
2192
2193 if (side == EPHYSICS_BODY_CLOTH_ANCHOR_SIDE_TOP)
2194 {
2195 for (int i = 0; i < columns; i++)
2196 body1->soft_body->appendAnchor((rows - 1) + rows * i,
2197 body2->rigid_body);
2198 }
2199
2200 mass_reset:
2201 _ephysics_body_cloth_anchor_mass_reset(body1);
2202 }
2203
2204 EAPI void
ephysics_body_cloth_anchor_add(EPhysics_Body * body1,EPhysics_Body * body2,int node)2205 ephysics_body_cloth_anchor_add(EPhysics_Body *body1, EPhysics_Body *body2, int node)
2206 {
2207 if (!body1 || !body2)
2208 {
2209 ERR("Could not add anchors, body1 or body2 is null");
2210 return;
2211 }
2212
2213 if (body1->type != EPHYSICS_BODY_TYPE_CLOTH ||
2214 body2->type != EPHYSICS_BODY_TYPE_RIGID)
2215 {
2216 ERR("Cloth anchors are allowed only between cloth and rigid body.");
2217 return;
2218 }
2219
2220 body1->soft_body->appendAnchor(node, body2->rigid_body);
2221 _ephysics_body_cloth_anchor_mass_reset(body1);
2222 }
2223
2224 EAPI void
ephysics_body_cloth_anchor_del(EPhysics_Body * body)2225 ephysics_body_cloth_anchor_del(EPhysics_Body *body)
2226 {
2227 if (!body)
2228 {
2229 ERR("Could not delete anchor, body is null.");
2230 return;
2231 }
2232
2233 if (body->type != EPHYSICS_BODY_TYPE_CLOTH)
2234 {
2235 ERR("Could not delete anchors, body is not a cloth.");
2236 return;
2237 }
2238
2239 body->soft_body->m_anchors.resize(0);
2240 body->soft_body->setTotalMass(body->mass);
2241 }
2242
2243 static Eina_List *
_ephysics_body_slices_add(EPhysics_Body * body,int slices_cnt,int * points,double delta,double max)2244 _ephysics_body_slices_add(EPhysics_Body *body, int slices_cnt, int *points, double delta, double max)
2245 {
2246 Eina_List *slices = NULL;
2247 EPhysics_Body_Soft_Body_Slice *slice;
2248 btSoftBody::tFaceArray faces;
2249
2250 for (int i = 0; i < slices_cnt; i++)
2251 {
2252 faces = body->soft_body->m_faces;
2253
2254 slice = _ephysics_body_soft_body_slice_new(body, delta, max,
2255 points[i]);
2256 if (!slice) goto no_slices;
2257
2258 slices = eina_list_append(slices, slice);
2259 }
2260 return slices;
2261
2262 no_slices:
2263 _ephysics_body_soft_body_slices_clean(slices);
2264 return NULL;
2265 }
2266
2267 EAPI void
ephysics_body_soft_body_position_iterations_set(EPhysics_Body * body,int iterations)2268 ephysics_body_soft_body_position_iterations_set(EPhysics_Body *body, int iterations)
2269 {
2270 if (!body)
2271 {
2272 ERR("Could not set the number of iterations for position solver, body "
2273 "is null.");
2274 return;
2275 }
2276
2277 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
2278 {
2279 ERR("Could not set the number of iterations for position solver, body "
2280 "must be a soft body or a cloth");
2281 return;
2282 }
2283
2284 body->soft_body->m_cfg.piterations = iterations;
2285 DBG("Soft body position solver iterations set to: %d", iterations);
2286 }
2287
2288 EAPI int
ephysics_body_soft_body_position_iterations_get(EPhysics_Body * body)2289 ephysics_body_soft_body_position_iterations_get(EPhysics_Body *body)
2290 {
2291 if (!body)
2292 {
2293 ERR("Could not get the number of iterations for position solver, body "
2294 "is null.");
2295 return 0;
2296 }
2297
2298 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
2299 {
2300 ERR("Could not get the number of iterations for position solver, body "
2301 "must be a soft body or a cloth");
2302 return 0;
2303 }
2304
2305 return body->soft_body->m_cfg.piterations;
2306 }
2307
2308 EAPI void
ephysics_body_soft_body_bending_constraints_add(EPhysics_Body * body,int number)2309 ephysics_body_soft_body_bending_constraints_add(EPhysics_Body *body, int number)
2310 {
2311 if (!body)
2312 {
2313 ERR("Could add new bending constraint, body is null.");
2314 return;
2315 }
2316
2317 if (number <= 0)
2318 {
2319 ERR("Could not add new bending constraints, number must be greater"
2320 " than 0");
2321 return;
2322 }
2323
2324 body->bending_constraints += number;
2325 DBG("Added new bending constraints to body: %p", body);
2326 }
2327
2328 EAPI EPhysics_Body *
ephysics_body_cloth_add(EPhysics_World * world,unsigned short rows,unsigned short columns)2329 ephysics_body_cloth_add(EPhysics_World *world, unsigned short rows, unsigned short columns)
2330 {
2331 EPhysics_Body *body;
2332 EPhysics_Body_Face_Slice *face_slice;
2333 btSoftBodyWorldInfo *world_info;
2334 btSoftBody *soft_body;
2335 const int body_rows = (!rows) ? 15 : rows;
2336 const int body_columns = (!columns) ? 15 : columns;
2337
2338 if (!world)
2339 {
2340 ERR("Can't add circle, world is null.");
2341 return NULL;
2342 }
2343
2344 world_info = ephysics_world_info_get(world);
2345 soft_body = btSoftBodyHelpers::CreatePatch(*world_info,
2346 btVector3(2, 2, 0),
2347 btVector3(2, 1, 0),
2348 btVector3(1, 2, 0),
2349 btVector3(1, 1, 0),
2350 body_rows + 1, body_columns + 1,
2351 0, false);
2352
2353 if (!soft_body)
2354 {
2355 ERR("Couldn't create a new soft body.");
2356 return NULL;
2357 }
2358
2359 body = _ephysics_body_new(world, 1, 0.5, 0.5, 0.5);
2360 if (!body)
2361 goto no_body;
2362
2363 soft_body->setPose(false, true);
2364
2365 soft_body->appendMaterial();
2366 body->material_index = 1;
2367 soft_body->m_cfg.piterations = body_rows / 5;
2368
2369 _ephysics_body_soft_body_default_config(body, soft_body);
2370 _ephysics_body_cloth_constraints_rebuild(body);
2371
2372 face_slice = _ephysics_body_face_slice_add(body,
2373 EPHYSICS_BODY_CLOTH_FACE_FRONT);
2374 if (!face_slice)
2375 {
2376 ERR("Could not allocate face slice data structure.");
2377 goto no_face_slice;
2378 }
2379
2380 face_slice->slices_cnt = soft_body->m_faces.size();
2381 face_slice->points_deform = (int *)malloc(face_slice->slices_cnt *
2382 sizeof(int));
2383 if (!face_slice->points_deform)
2384 {
2385 ERR("Couldn't create points of deformation.");
2386 goto no_deform;
2387 }
2388
2389 for (int i = 0; i < face_slice->slices_cnt; i++)
2390 face_slice->points_deform[i] = i;
2391
2392 face_slice->slices = _ephysics_body_slices_add(body, face_slice->slices_cnt,
2393 face_slice->points_deform, -1,
2394 1);
2395 if (!face_slice->slices)
2396 {
2397 ERR("Couldn't create slices.");
2398 goto no_slices;
2399 }
2400
2401 body->default_face = face_slice;
2402
2403 body->cloth_columns = body_columns;
2404 body->cloth_rows = body_rows;
2405 body->type = EPHYSICS_BODY_TYPE_CLOTH;
2406
2407 ephysics_world_soft_body_add(world, body);
2408
2409 return body;
2410
2411 no_slices:
2412 no_deform:
2413 _ephysics_body_face_slice_del(face_slice);
2414 no_face_slice:
2415 free(body);
2416 no_body:
2417 delete soft_body;
2418 return NULL;
2419 }
2420
2421 static void
_ephysics_body_soft_body_single_face_transform(btSoftBody * soft_body,int face_idx,int node_idx,btTransform trans)2422 _ephysics_body_soft_body_single_face_transform(btSoftBody *soft_body, int face_idx, int node_idx, btTransform trans)
2423 {
2424 btSoftBody::Node *node;
2425 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
2426 const btScalar margin = soft_body->getCollisionShape()->getMargin();
2427
2428 node = soft_body->m_faces[face_idx].m_n[node_idx];
2429
2430 if (node->m_battach)
2431 return;
2432
2433 node->m_x = trans * node->m_x;
2434 node->m_q = trans * node->m_q;
2435 node->m_n = trans.getBasis() * node->m_n;
2436 vol = btDbvtVolume::FromCR(node->m_x, margin);
2437 soft_body->m_ndbvt.update(node->m_leaf, vol);
2438 }
2439
2440 void
ephysics_body_soft_body_dragging_apply(EPhysics_Body * body)2441 ephysics_body_soft_body_dragging_apply(EPhysics_Body *body)
2442 {
2443 btSoftBody::Face face;
2444 btSoftBody::Node *node;
2445
2446 face = body->soft_body->m_faces[body->dragging_data.triangle];
2447 node = face.m_n[0];
2448 node->m_v *= 0;
2449 node->m_im *= 0;
2450 }
2451
2452 EAPI void
ephysics_body_soft_body_triangle_move(EPhysics_Body * body,int idx,Evas_Coord x,Evas_Coord y,Evas_Coord z)2453 ephysics_body_soft_body_triangle_move(EPhysics_Body *body, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
2454 {
2455 btScalar xx, yy, zz;
2456 Evas_Coord wh, wy;
2457 double rate;
2458 btVector3 new_pos;
2459 btTransform diff;
2460 btSoftBody::Face face;
2461 btSoftBody::Node *node;
2462
2463 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
2464 {
2465 ERR("Could not move soft body triangle, body must be soft or cloth.");
2466 return;
2467 }
2468
2469 if (idx < 0 || idx >= body->soft_body->m_faces.size())
2470 {
2471 ERR("Could not move soft body triangle, provided body triangle index "
2472 "ranges from 0 to %d", body->soft_body->m_faces.size());
2473 return;
2474 }
2475
2476 rate = ephysics_world_rate_get(body->world);
2477 ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, NULL, &wh,
2478 NULL);
2479
2480 xx = x / rate;
2481 yy = ((wh + wy) - y) / rate;
2482 zz = z / rate;
2483
2484 new_pos = btVector3(xx, yy, zz);
2485 ephysics_world_lock_take(body->world);
2486
2487 face = body->soft_body->m_faces[idx];
2488
2489 node = face.m_n[0];
2490 diff.setIdentity();
2491 diff.setOrigin(new_pos - node->m_x);
2492 _ephysics_body_soft_body_single_face_transform(body->soft_body, idx, 0, diff);
2493
2494 diff.setOrigin(diff.getOrigin() * 0.1);
2495 for (int m = 0; m < body->soft_body->m_faces.size(); m++)
2496 {
2497 if (m == idx) continue;
2498 _ephysics_body_soft_body_single_face_transform(body->soft_body, m, 0,
2499 diff);
2500 }
2501
2502 body->soft_body->updateClusters();
2503 body->soft_body->updateBounds();
2504 body->soft_body->updateNormals();
2505 body->soft_body->updatePose();
2506 ephysics_world_lock_release(body->world);
2507 }
2508
2509 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)2510 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)
2511 {
2512 Eina_List *face_list = NULL;
2513 btSoftBody::Face *bt_face;
2514 btSoftBody::Node *node;
2515 int out, *idx;
2516 btScalar nx, ny, nz, xx, yy, zz, dd, ww, hh;
2517 Evas_Coord wy, wh;
2518 double rate;
2519
2520 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
2521 {
2522 ERR("Can't get triangle indexes, operation not permited to rigid"
2523 " bodies.");
2524 return NULL;
2525 }
2526
2527 ephysics_world_lock_take(body->world);
2528 rate = ephysics_world_rate_get(body->world);
2529 ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, NULL, &wh,
2530 NULL);
2531 xx = x / rate;
2532 yy = (wy + (wh - y)) / rate;
2533 zz = z / rate;
2534 dd = d / rate;
2535 ww = w / rate;
2536 hh = h / rate;
2537
2538 for (int m = 0; m < body->soft_body->m_faces.size(); m++)
2539 {
2540 out = 0;
2541 bt_face = &body->soft_body->m_faces[m];
2542 for (int n = 0; n < 3; n++)
2543 {
2544 node = bt_face->m_n[n];
2545 nx = node->m_x.x();
2546 ny = node->m_x.y();
2547 nz = node->m_x.z();
2548
2549 if ((nz < zz || nz > zz + dd) || (nx < xx || nx > xx + ww) ||
2550 (ny > yy || ny < yy - hh))
2551 out++;
2552 }
2553
2554 if (!out)
2555 {
2556 idx = (int *)malloc(sizeof(int));
2557 *idx = m;
2558 face_list = eina_list_append(face_list, idx);
2559 }
2560 }
2561
2562 ephysics_world_lock_release(body->world);
2563
2564 return face_list;
2565 }
2566
2567 static void
_ephysics_body_soft_body_triangle_impulse_apply(EPhysics_Body * body,int idx,double x,double y,double z)2568 _ephysics_body_soft_body_triangle_impulse_apply(EPhysics_Body *body, int idx, double x, double y, double z)
2569 {
2570 btSoftBody::Face face;
2571 btSoftBody::Node *node;
2572 double rate;
2573 btVector3 impulse;
2574
2575 rate = ephysics_world_rate_get(body->world);
2576 impulse = btVector3(x / rate, - y / rate, z / rate);
2577
2578 face = body->soft_body->m_faces[idx];
2579 for (int i = 0; i < 3; i++)
2580 {
2581 node = face.m_n[i];
2582 node->m_v = impulse * node->m_im;
2583 }
2584
2585 DBG("Impulse applied to soft body node(%d): %lf, %lf, %lf", idx, impulse.x(),
2586 impulse.y(), impulse.z());
2587 }
2588
2589 EAPI void
ephysics_body_soft_body_triangle_impulse_apply(EPhysics_Body * body,int idx,double x,double y,double z)2590 ephysics_body_soft_body_triangle_impulse_apply(EPhysics_Body * body, int idx, double x, double y, double z)
2591 {
2592
2593 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
2594 {
2595 ERR("Can't apply impulse, operation not permited to rigid bodies.");
2596 return;
2597 }
2598
2599 if (idx < 0 || idx >= body->soft_body->m_faces.size())
2600 {
2601 ERR("Could not apply impulse, provided body triangle index ranges from"
2602 " 0 to %d", body->soft_body->m_faces.size());
2603 return;
2604 }
2605
2606 ephysics_world_lock_take(body->world);
2607 _ephysics_body_soft_body_triangle_impulse_apply(body, idx, x, y, z);
2608 ephysics_world_lock_release(body->world);
2609 }
2610
2611 EAPI void
ephysics_body_soft_body_triangle_list_impulse_apply(EPhysics_Body * body,Eina_List * triangles,double x,double y,double z)2612 ephysics_body_soft_body_triangle_list_impulse_apply(EPhysics_Body *body, Eina_List *triangles, double x, double y, double z)
2613 {
2614 Eina_List *l;
2615 void *ldata;
2616 int idx, faces_cnt;
2617
2618 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
2619 {
2620 ERR("Can't apply impulse, operation not permited to rigid bodies.");
2621 return;
2622 }
2623
2624 faces_cnt = body->soft_body->m_faces.size();
2625 ephysics_world_lock_take(body->world);
2626 EINA_LIST_FOREACH(triangles, l, ldata)
2627 {
2628 idx = *(int *)ldata;
2629 if (idx < 0 || idx >= faces_cnt)
2630 {
2631 INF("Could not apply impulse to triangle %d, provided body"
2632 " triangle index ranges from 0 to %d", idx, faces_cnt);
2633 continue;
2634 }
2635
2636 _ephysics_body_soft_body_triangle_impulse_apply(body, idx, x, y, z);
2637 DBG("Applied impulse on body %p, triangle: %d", body, idx);
2638 }
2639 ephysics_world_lock_release(body->world);
2640 }
2641
2642 EAPI int
ephysics_body_soft_body_triangle_index_get(EPhysics_Body * body,Evas_Coord x,Evas_Coord y)2643 ephysics_body_soft_body_triangle_index_get(EPhysics_Body *body, Evas_Coord x, Evas_Coord y)
2644 {
2645 int w, h, r, c, index = -1;
2646
2647 if (!body->evas_obj)
2648 {
2649 ERR("No evas object associated to body");
2650 return -1;
2651 }
2652
2653 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
2654 {
2655 ERR("Can't get node index, operation not permited to rigid bodies");
2656 return -1;
2657 }
2658
2659 if (body->type == EPHYSICS_BODY_TYPE_SOFT)
2660 {
2661 ERR("Can't get node index, not implemented for soft bodies yet.");
2662 return -1;
2663 }
2664
2665 evas_object_geometry_get(body->evas_obj, NULL, NULL, &w, &h);
2666 r = y * body->cloth_rows / h;
2667 c = (w - x) * body->cloth_columns / w;
2668
2669 index = 2 * r + c * body->cloth_rows * 2;
2670
2671 return index;
2672 }
2673
2674 static EPhysics_Body_Face_Slice *
_ephysics_body_soft_sphere_face_slices_add(EPhysics_Body * body,EPhysics_Body_Face face,btVector3 center)2675 _ephysics_body_soft_sphere_face_slices_add(EPhysics_Body *body, EPhysics_Body_Face face, btVector3 center)
2676 {
2677 btSoftBody::Face *bt_face;
2678 btSoftBody::Node *node;
2679 int out;
2680 btScalar depth_limit;
2681 Eina_List *face_list = NULL;
2682 void *data;
2683 int *idx, i = 0;
2684 EPhysics_Body_Face_Slice *face_slice;
2685
2686 depth_limit = center.z();
2687
2688 for (int m = 0; m < body->soft_body->m_faces.size(); m++)
2689 {
2690 out = 0;
2691 bt_face = &body->soft_body->m_faces[m];
2692 for (int n = 0; n < 3; n++)
2693 {
2694 node = bt_face->m_n[n];
2695 if ((face == EPHYSICS_BODY_SPHERE_FACE_FRONT &&
2696 node->m_x.z() > depth_limit) ||
2697 (face == EPHYSICS_BODY_SPHERE_FACE_BACK &&
2698 node->m_x.z() < depth_limit))
2699 out++;
2700 }
2701
2702 if (out < 2)
2703 {
2704 idx = (int *)malloc(sizeof(int));
2705 if (!idx)
2706 goto no_deform;
2707 *idx = m;
2708 face_list = eina_list_append(face_list, idx);
2709 }
2710 }
2711
2712 face_slice = _ephysics_body_face_slice_add(body, face);
2713 if (!face_slice)
2714 {
2715 ERR("Could not allocate face slice data structure.");
2716 goto no_deform;
2717 }
2718
2719 face_slice->slices_cnt = eina_list_count(face_list);
2720 face_slice->points_deform = (int *)malloc(face_slice->slices_cnt *
2721 sizeof(int));
2722 if (!face_slice->points_deform)
2723 goto no_points_deform;
2724
2725 EINA_LIST_FREE(face_list, data)
2726 {
2727 face_slice->points_deform[i] = *((int *)data);
2728 i++;
2729 }
2730
2731 face_slice->slices = _ephysics_body_slices_add(body, face_slice->slices_cnt,
2732 face_slice->points_deform, -0.5, 1);
2733 if (!face_slice->slices)
2734 {
2735 ERR("Couldn't create slices.");
2736 goto no_points_deform;
2737 }
2738 return face_slice;
2739
2740 no_points_deform:
2741 _ephysics_body_face_slice_del(face_slice);
2742 no_deform:
2743 EINA_LIST_FREE(face_list, data)
2744 free(data);
2745 return NULL;
2746 }
2747
2748 EAPI EPhysics_Body *
ephysics_body_soft_sphere_add(EPhysics_World * world,int granularity)2749 ephysics_body_soft_sphere_add(EPhysics_World *world, int granularity)
2750 {
2751 EPhysics_Body *body;
2752 EPhysics_Body_Face_Slice *front_face, *back_face;
2753 btCollisionShape *shape;
2754 btSoftBodyWorldInfo *world_info;
2755 btSoftBody *soft_body;
2756 btVector3 center, radius;
2757 int body_granularity = (!granularity) ? 100 : granularity;
2758
2759
2760 if (!world)
2761 {
2762 ERR("Can't add soft sphere, world is null.");
2763 return NULL;
2764 }
2765
2766 ephysics_world_lock_take(world);
2767 shape = new btCylinderShapeZ(btVector3(0.25, 0.25, 0.25));
2768
2769 if (!shape)
2770 {
2771 ERR("Couldn't create a new cylinder shape.");
2772 goto no_collision_shape;
2773 }
2774
2775 world_info = ephysics_world_info_get(world);
2776 center = btVector3(1, 1, 1);
2777 radius = btVector3(0.5, 0.5, 0.5);
2778 soft_body = btSoftBodyHelpers::CreateEllipsoid(*world_info, center, radius,
2779 body_granularity);
2780
2781 if (!soft_body)
2782 {
2783 ERR("Couldn't create a new soft body.");
2784 goto no_soft_body;
2785 }
2786
2787 body = _ephysics_body_soft_body_add(world, shape, soft_body);
2788 if (!body)
2789 goto no_body;
2790
2791 body->soft_body->setPose(false, true);
2792
2793 front_face = _ephysics_body_soft_sphere_face_slices_add(body,
2794 EPHYSICS_BODY_SPHERE_FACE_FRONT, center);
2795 if (!front_face)
2796 {
2797 ERR("Could not create points of deformation mapping for front face.");
2798 goto no_front_face;
2799 }
2800 body->default_face = front_face;
2801
2802 back_face = _ephysics_body_soft_sphere_face_slices_add(body,
2803 EPHYSICS_BODY_SPHERE_FACE_BACK, center);
2804 if (!back_face)
2805 {
2806 ERR("Could not create points of deformation mapping for back face.");
2807 goto no_back_face;
2808 }
2809
2810 body->shape = EPHYSICS_BODY_SHAPE_SPHERE;
2811 ephysics_world_lock_release(world);
2812 return body;
2813
2814 no_back_face:
2815 _ephysics_body_face_slice_del(front_face);
2816 no_front_face:
2817 ephysics_world_body_del(world, body);
2818 no_body:
2819 delete soft_body;
2820 no_soft_body:
2821 delete shape;
2822 no_collision_shape:
2823 ephysics_world_lock_release(world);
2824 return NULL;
2825 }
2826
2827 EAPI EPhysics_Body *
ephysics_body_soft_cylinder_add(EPhysics_World * world)2828 ephysics_body_soft_cylinder_add(EPhysics_World *world)
2829 {
2830 EPhysics_Body *body;
2831 EPhysics_Body_Face_Slice *face_slice;
2832 btCollisionShape *shape;
2833 btSoftBodyWorldInfo *world_info;
2834 btSoftBody *soft_body;
2835 int points[19] = {16, 58, 44, 79, 97, 35, 6, 27, 45, 1, 38, 18, 21, 10, 26,
2836 7, 86, 37, 55};
2837
2838 if (!world)
2839 {
2840 ERR("Can't add circle, world is null.");
2841 return NULL;
2842 }
2843
2844 ephysics_world_lock_take(world);
2845 shape = new btCylinderShapeZ(btVector3(0.5, 0.5, 0.5));
2846
2847 if (!shape)
2848 {
2849 ERR("Couldn't create a new cylinder shape.");
2850 goto no_collision_shape;
2851 }
2852
2853 world_info = ephysics_world_info_get(world);
2854 soft_body = btSoftBodyHelpers::CreateFromTriMesh(*world_info,
2855 cylinder_vertices, &cylinder_indices[0][0],
2856 CYLINDER_NUM_TRIANGLES);
2857 if (!soft_body)
2858 {
2859 ERR("Couldn't create a new soft body.");
2860 goto no_soft_body;
2861 }
2862
2863 body = _ephysics_body_soft_body_add(world, shape, soft_body);
2864 if (!body)
2865 goto no_body;
2866
2867 body->shape = EPHYSICS_BODY_SHAPE_CYLINDER;
2868
2869 face_slice = _ephysics_body_face_slice_add(body,
2870 EPHYSICS_BODY_CYLINDER_FACE_FRONT);
2871 if (!face_slice)
2872 {
2873 ERR("Could not allocate face slice data structure.");
2874 goto no_face_slice;
2875 }
2876
2877 face_slice->slices_cnt = 19;
2878 face_slice->points_deform = (int *)malloc(face_slice->slices_cnt *
2879 sizeof(int));
2880 if (!face_slice->points_deform)
2881 {
2882 ERR("Couldn't create points of deformation.");
2883 goto no_deform;
2884 }
2885
2886 for (int i = 0; i < face_slice->slices_cnt; i++)
2887 face_slice->points_deform[i] = points[i];
2888
2889 face_slice->slices = _ephysics_body_slices_add(body, face_slice->slices_cnt,
2890 face_slice->points_deform, 0.55,
2891 1.1);
2892 if (!face_slice->slices)
2893 {
2894 ERR("Couldn't create slices.");
2895 goto no_slices;
2896 }
2897
2898 body->default_face = face_slice;
2899
2900 ephysics_world_lock_release(world);
2901 return body;
2902
2903 no_slices:
2904 no_deform:
2905 _ephysics_body_face_slice_del(face_slice);
2906 no_face_slice:
2907 ephysics_world_body_del(world, body);
2908 no_body:
2909 delete soft_body;
2910 no_soft_body:
2911 delete shape;
2912 no_collision_shape:
2913 ephysics_world_lock_release(world);
2914 return NULL;
2915 }
2916
2917 EAPI EPhysics_Body *
ephysics_body_sphere_add(EPhysics_World * world)2918 ephysics_body_sphere_add(EPhysics_World *world)
2919 {
2920 btCollisionShape *collision_shape;
2921 EPhysics_Body *body;
2922
2923 if (!world)
2924 {
2925 ERR("Can't add sphere, world is null.");
2926 return NULL;
2927 }
2928
2929 collision_shape = new btSphereShape(0.5);
2930 if (!collision_shape)
2931 {
2932 ERR("Couldn't create a new sphere shape.");
2933 return NULL;
2934 }
2935
2936 ephysics_world_lock_take(world);
2937 body = _ephysics_body_rigid_body_add(world, collision_shape, "sphere", 0.5,
2938 0.5, 0.5);
2939 body->shape = EPHYSICS_BODY_SHAPE_SPHERE;
2940 ephysics_world_lock_release(world);
2941 return body;
2942 }
2943
2944 EAPI EPhysics_Body *
ephysics_body_cylinder_add(EPhysics_World * world)2945 ephysics_body_cylinder_add(EPhysics_World *world)
2946 {
2947 btCollisionShape *collision_shape;
2948 EPhysics_Body *body;
2949
2950 if (!world)
2951 {
2952 ERR("Can't add cylinder, world is null.");
2953 return NULL;
2954 }
2955
2956 collision_shape = new btCylinderShapeZ(btVector3(0.5, 0.5, 0.5));
2957 if (!collision_shape)
2958 {
2959 ERR("Couldn't create a new cylinder shape.");
2960 return NULL;
2961 }
2962
2963 ephysics_world_lock_take(world);
2964 body = _ephysics_body_rigid_body_add(world, collision_shape, "cylinder", 0.5,
2965 0.5, 0.5);
2966 body->shape = EPHYSICS_BODY_SHAPE_CYLINDER;
2967 ephysics_world_lock_release(world);
2968 return body;
2969 }
2970
2971 EAPI EPhysics_Body *
ephysics_body_soft_box_add(EPhysics_World * world)2972 ephysics_body_soft_box_add(EPhysics_World *world)
2973 {
2974 EPhysics_Body *body;
2975 EPhysics_Body_Face_Slice *face_slice = NULL;
2976 btCollisionShape *shape;
2977 btSoftBodyWorldInfo *world_info;
2978 btSoftBody *soft_body;
2979 int points[16] = {14, 85, 88, 28, 41, 55, 10, 24, 93, 79, 56, 86, 91, 8,
2980 27, 1};
2981
2982
2983 if (!world)
2984 {
2985 ERR("Can't add circle, world is null.");
2986 return NULL;
2987 }
2988
2989 ephysics_world_lock_take(world);
2990 shape = new btBoxShape(btVector3(0.25, 0.25, 0.25));
2991 if (!shape)
2992 {
2993 ERR("Couldn't create a new box shape.");
2994 goto no_collision_shape;
2995 }
2996
2997 world_info = ephysics_world_info_get(world);
2998 soft_body = btSoftBodyHelpers::CreateFromTriMesh(*world_info,
2999 cube_vertices, &cube_indices[0][0],
3000 CUBE_NUM_TRIANGLES);
3001 if (!soft_body)
3002 {
3003 ERR("Couldn't create a new soft body.");
3004 goto no_soft_body;
3005 }
3006
3007 body = _ephysics_body_soft_body_add(world, shape, soft_body);
3008 if (!body)
3009 goto no_body;
3010
3011 body->shape = EPHYSICS_BODY_SHAPE_BOX;
3012
3013 face_slice = _ephysics_body_face_slice_add(body,
3014 EPHYSICS_BODY_BOX_FACE_FRONT);
3015 if (!face_slice)
3016 {
3017 ERR("Could not allocate face slice data structure.");
3018 goto no_face_slice;
3019 }
3020
3021 face_slice->slices_cnt = 16;
3022 face_slice->points_deform = (int *)malloc(face_slice->slices_cnt *
3023 sizeof(int));
3024 if (!face_slice->points_deform)
3025 {
3026 ERR("Couldn't create points of deformation.");
3027 goto no_deform;
3028 }
3029
3030 for (int i = 0; i < face_slice->slices_cnt; i++)
3031 face_slice->points_deform[i] = points[i];
3032
3033 face_slice->slices = _ephysics_body_slices_add(body, face_slice->slices_cnt,
3034 face_slice->points_deform, 0.55,
3035 1.1);
3036 if (!face_slice->slices)
3037 {
3038 ERR("Couldn't create slices.");
3039 goto no_slices;
3040 }
3041
3042 body->default_face = face_slice;
3043
3044 ephysics_world_lock_release(world);
3045 return body;
3046
3047 no_slices:
3048 no_face_slice:
3049 if (face_slice) _ephysics_body_face_slice_del(face_slice);
3050 no_deform:
3051 ephysics_world_body_del(world, body);
3052 no_body:
3053 delete soft_body;
3054 no_soft_body:
3055 delete shape;
3056 no_collision_shape:
3057 ephysics_world_lock_release(world);
3058 return NULL;
3059 }
3060
3061 EAPI EPhysics_Body *
ephysics_body_box_add(EPhysics_World * world)3062 ephysics_body_box_add(EPhysics_World *world)
3063 {
3064 btCollisionShape *collision_shape;
3065 EPhysics_Body *body;
3066
3067 if (!world)
3068 {
3069 ERR("Can't add box, world is null.");
3070 return NULL;
3071 }
3072
3073 collision_shape = new btBoxShape(btVector3(0.5, 0.5, 0.5));
3074
3075 ephysics_world_lock_take(world);
3076 body = _ephysics_body_rigid_body_add(world, collision_shape, "box", 0.5,
3077 0.5, 0.5);
3078 body->shape = EPHYSICS_BODY_SHAPE_BOX;
3079 ephysics_world_lock_release(world);
3080 return body;
3081 }
3082
3083 EAPI EPhysics_Body *
ephysics_body_shape_add(EPhysics_World * world,EPhysics_Shape * shape)3084 ephysics_body_shape_add(EPhysics_World *world, EPhysics_Shape *shape)
3085 {
3086 double max_x, max_y, max_z, min_x, min_y, min_z, cm_x, cm_y, cm_z,
3087 range_x, range_y, range_z;
3088 btConvexHullShape *full_shape, *simplified_shape;
3089 btAlignedObjectArray<btVector3> vertexes, planes;
3090 const Eina_Inlist *points;
3091 EPhysics_Point *point;
3092 EPhysics_Body *body;
3093 int array_size, i;
3094 btShapeHull *hull;
3095 btVector3 point3d;
3096 btScalar margin;
3097
3098 if (!world)
3099 {
3100 ERR("Can't add shape, world is null.");
3101 return NULL;
3102 }
3103
3104 if (!shape)
3105 {
3106 ERR("Can't add shape, shape is null.");
3107 return NULL;
3108 }
3109
3110 points = ephysics_shape_points_get(shape);
3111 if (eina_inlist_count(points) < 3)
3112 {
3113 ERR("At least 3 points are required to add a shape");
3114 return NULL;
3115 }
3116
3117 full_shape = new btConvexHullShape();
3118 if (!full_shape)
3119 {
3120 ERR("Couldn't create a generic convex shape.");
3121 return NULL;
3122 }
3123
3124 point = EINA_INLIST_CONTAINER_GET(points, EPhysics_Point);
3125 max_x = min_x = point->x;
3126 max_y = min_y = point->y;
3127 max_z = min_z = point->z;
3128 cm_x = cm_y = cm_z = 0;
3129
3130 /* FIXME : only vertices should be used to calculate the center of mass */
3131 EINA_INLIST_FOREACH(points, point)
3132 {
3133 if (point->x > max_x) max_x = point->x;
3134 if (point->x < min_x) min_x = point->x;
3135 if (point->y > max_y) max_y = point->y;
3136 if (point->y < min_y) min_y = point->y;
3137 if (point->z > max_z) max_z = point->z;
3138 if (point->z < min_z) min_z = point->z;
3139
3140 cm_x += point->x;
3141 cm_y += point->y;
3142 cm_z += point->z;
3143 }
3144
3145 cm_x /= eina_inlist_count(points);
3146 cm_y /= eina_inlist_count(points);
3147 cm_z /= eina_inlist_count(points);
3148 range_x = max_x - min_x;
3149 range_y = max_y - min_y;
3150 range_z = max_z - min_z;
3151
3152 EINA_INLIST_FOREACH(points, point)
3153 {
3154 double x, y, z;
3155
3156 x = (point->x - cm_x) / range_x;
3157 y = - (point->y - cm_y) / range_y;
3158 z = (point->z - cm_z) / range_z;
3159
3160 point3d = btVector3(x, y, z);
3161 vertexes.push_back(point3d);
3162 }
3163
3164 /* Shrink convex shape to consider margin. Otherwise it would have a gap */
3165 btGeometryUtil::getPlaneEquationsFromVertices(vertexes, planes);
3166 array_size = planes.size();
3167 for (i = 0; i < array_size; ++i)
3168 planes[i][3] += full_shape->getMargin();
3169
3170 vertexes.clear();
3171 btGeometryUtil::getVerticesFromPlaneEquations(planes, vertexes);
3172
3173 array_size = vertexes.size();
3174 for (i = 0; i < array_size; ++i)
3175 full_shape->addPoint(vertexes[i]);
3176
3177 hull = new btShapeHull(full_shape);
3178 if (!hull)
3179 {
3180 delete full_shape;
3181 ERR("Couldn't create a shape hull.");
3182 return NULL;
3183 }
3184
3185 margin = full_shape->getMargin();
3186 hull->buildHull(margin);
3187 simplified_shape = new btConvexHullShape(&(hull->getVertexPointer()->getX()),
3188 hull->numVertices());
3189 delete hull;
3190 delete full_shape;
3191 if (!simplified_shape)
3192 {
3193 ERR("Couldn't create a simplified shape.");
3194 return NULL;
3195 }
3196
3197 ephysics_world_lock_take(world);
3198 body = _ephysics_body_rigid_body_add(world,
3199 (btCollisionShape *)simplified_shape,
3200 "generic", (cm_x - min_x) / range_x,
3201 1 - (cm_y - min_y) / range_y,
3202 (cm_z - min_z) / range_z);
3203 body->shape = EPHYSICS_BODY_SHAPE_CUSTOM;
3204 ephysics_world_lock_release(world);
3205 return body;
3206 }
3207
3208 void
ephysics_body_world_boundaries_resize(EPhysics_World * world)3209 ephysics_body_world_boundaries_resize(EPhysics_World *world)
3210 {
3211 Evas_Coord x, y, z, w, h, d;
3212 EPhysics_Body *bound;
3213
3214 ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, &d);
3215
3216 bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_BOTTOM);
3217 if (bound)
3218 ephysics_body_geometry_set(bound, x, y + h, z, w, 10, d);
3219
3220 bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_RIGHT);
3221 if (bound)
3222 ephysics_body_geometry_set(bound, x + w, y, z, 10, h, d);
3223
3224 bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_LEFT);
3225 if (bound)
3226 ephysics_body_geometry_set(bound, x - 10, y, z, 10, h, d);
3227
3228 bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_TOP);
3229 if (bound)
3230 ephysics_body_geometry_set(bound, x, y - 10, z, w, 10, d);
3231
3232 bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_FRONT);
3233 if (bound)
3234 ephysics_body_geometry_set(bound, x, y, z - 10, w, h, 10);
3235
3236 bound = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_BACK);
3237 if (bound)
3238 ephysics_body_geometry_set(bound, x, y, z + d, w, h, 10);
3239 }
3240
3241 static EPhysics_Body *
_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)3242 _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)
3243 {
3244 EPhysics_Body *body;
3245
3246 if (!world)
3247 {
3248 ERR("Can't add boundary, world is null.");
3249 return NULL;
3250 }
3251
3252 body = ephysics_world_boundary_get(world, boundary);
3253 if (body)
3254 return body;
3255
3256 body = ephysics_body_box_add(world);
3257 if (!body)
3258 return NULL;
3259
3260 body->boundary = EINA_TRUE;
3261 ephysics_body_mass_set(body, 0);
3262 ephysics_world_boundary_set(world, boundary, body);
3263
3264 if ((w <= 0) || (h <= 0) || (d <= 0))
3265 INF("Boundary added with default geometry. Render geometry not set yet");
3266 else
3267 ephysics_body_geometry_set(body, x, y, z, w, h, d);
3268
3269 return body;
3270 }
3271
3272 EAPI EPhysics_Body *
ephysics_body_top_boundary_add(EPhysics_World * world)3273 ephysics_body_top_boundary_add(EPhysics_World *world)
3274 {
3275 Evas_Coord x, y, z, w, d;
3276 EPhysics_Body *body;
3277
3278 ephysics_world_render_geometry_get(world, &x, &y, &z, &w, NULL, &d);
3279 body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_TOP,
3280 x, y - 10, z, w, 10, d);
3281 return body;
3282 }
3283
3284 EAPI EPhysics_Body *
ephysics_body_bottom_boundary_add(EPhysics_World * world)3285 ephysics_body_bottom_boundary_add(EPhysics_World *world)
3286 {
3287 Evas_Coord x, y, z, w, h, d;
3288 EPhysics_Body *body;
3289
3290 ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, &d);
3291 body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_BOTTOM,
3292 x, y + h, z, w, 10, d);
3293 return body;
3294 }
3295
3296 EAPI EPhysics_Body *
ephysics_body_left_boundary_add(EPhysics_World * world)3297 ephysics_body_left_boundary_add(EPhysics_World *world)
3298 {
3299 Evas_Coord x, y, z, h, d;
3300 EPhysics_Body *body;
3301
3302 ephysics_world_render_geometry_get(world, &x, &y, &z, NULL, &h, &d);
3303 body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_LEFT,
3304 x - 10, y, z, 10, h, d);
3305 return body;
3306 }
3307
3308 EAPI EPhysics_Body *
ephysics_body_right_boundary_add(EPhysics_World * world)3309 ephysics_body_right_boundary_add(EPhysics_World *world)
3310 {
3311 Evas_Coord x, y, z, w, h, d;
3312 EPhysics_Body *body;
3313
3314 ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, &d);
3315 body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_RIGHT,
3316 x + w, y, z, 10, h, d);
3317 return body;
3318 }
3319
3320 EAPI EPhysics_Body *
ephysics_body_front_boundary_add(EPhysics_World * world)3321 ephysics_body_front_boundary_add(EPhysics_World *world)
3322 {
3323 Evas_Coord x, y, z, w, h;
3324 EPhysics_Body *body;
3325
3326 ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, NULL);
3327 body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_FRONT,
3328 x, y, z - 10, w, h, 10);
3329 return body;
3330 }
3331
3332 EAPI EPhysics_Body *
ephysics_body_back_boundary_add(EPhysics_World * world)3333 ephysics_body_back_boundary_add(EPhysics_World *world)
3334 {
3335 Evas_Coord x, y, z, w, h, d;
3336 EPhysics_Body *body;
3337
3338 ephysics_world_render_geometry_get(world, &x, &y, &z, &w, &h, &d);
3339 body = _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_BACK,
3340 x, y, z + d, w, h, 10);
3341 return body;
3342 }
3343
3344 void
ephysics_orphan_body_del(EPhysics_Body * body)3345 ephysics_orphan_body_del(EPhysics_Body *body)
3346 {
3347 _ephysics_body_event_callback_call(body, EPHYSICS_CALLBACK_BODY_DEL,
3348 (void *) body->evas_obj);
3349 INF("Body %p deleted.", body);
3350 _ephysics_body_del(body);
3351 }
3352
3353 EAPI void
ephysics_body_del(EPhysics_Body * body)3354 ephysics_body_del(EPhysics_Body *body)
3355 {
3356 EPhysics_World *world;
3357
3358 if (!body)
3359 {
3360 ERR("Can't delete body, it wasn't provided.");
3361 return;
3362 }
3363
3364 if (body->deleted) return;
3365
3366 world = body->world;
3367 ephysics_world_lock_take(world);
3368 body->deleted = EINA_TRUE;
3369 ephysics_world_body_del(world, body);
3370 ephysics_world_lock_release(world);
3371 }
3372
3373 EAPI void
ephysics_body_evas_object_set(EPhysics_Body * body,Evas_Object * evas_obj,Eina_Bool use_obj_pos)3374 ephysics_body_evas_object_set(EPhysics_Body *body, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
3375 {
3376 int obj_x, obj_y, obj_w, obj_h, bz, bd;
3377 double rate;
3378
3379 if (!body)
3380 {
3381 ERR("Can't set evas object to body, the last wasn't provided.");
3382 return;
3383 }
3384
3385 if (!evas_obj)
3386 {
3387 ERR("Can't set evas object to body, the first wasn't provided.");
3388 return;
3389 }
3390
3391 if (body->evas_obj)
3392 {
3393 evas_object_map_enable_set(body->evas_obj, EINA_FALSE);
3394 evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_DEL,
3395 _ephysics_body_efl_canvas_object_del_cb);
3396 evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_RESIZE,
3397 _ephysics_body_efl_canvas_object_resize_cb);
3398 if (body->default_face)
3399 {
3400 evas_object_event_callback_del(body->evas_obj,
3401 EVAS_CALLBACK_RESTACK,
3402 _ephysics_body_soft_body_evas_restack_cb);
3403 _ephysics_body_soft_body_slices_clean(body->default_face->slices);
3404 }
3405 }
3406
3407 body->evas_obj = evas_obj;
3408 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
3409 _ephysics_body_efl_canvas_object_del_cb, body);
3410
3411 if (body->soft_body)
3412 {
3413 evas_object_geometry_get(body->evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
3414 if (!obj_w && !obj_h) evas_object_resize(body->evas_obj, 1, 1);
3415
3416 evas_object_event_callback_add(body->evas_obj, EVAS_CALLBACK_RESTACK,
3417 _ephysics_body_soft_body_evas_restack_cb, body);
3418 _ephysics_body_soft_body_slices_init(body, body->evas_obj,
3419 body->default_face->slices);
3420 }
3421
3422 if (!use_obj_pos)
3423 return;
3424
3425 rate = ephysics_world_rate_get(body->world);
3426 evas_object_geometry_get(body->evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
3427 ephysics_body_geometry_get(body, NULL, NULL, &bz, NULL, NULL, &bd);
3428
3429 ephysics_world_lock_take(body->world);
3430 _ephysics_body_geometry_set(body, obj_x, obj_y, bz, obj_w, obj_h, bd, rate);
3431 ephysics_world_lock_release(body->world);
3432 evas_object_event_callback_add(body->evas_obj, EVAS_CALLBACK_RESIZE,
3433 _ephysics_body_efl_canvas_object_resize_cb, body);
3434 }
3435
3436 EAPI Evas_Object *
ephysics_body_evas_object_unset(EPhysics_Body * body)3437 ephysics_body_evas_object_unset(EPhysics_Body *body)
3438 {
3439 Evas_Object *obj;
3440
3441 if (!body)
3442 {
3443 ERR("Can't unset evas object from body, it wasn't provided.");
3444 return NULL;
3445 }
3446
3447 obj = body->evas_obj;
3448 body->evas_obj = NULL;
3449
3450 if (obj)
3451 {
3452 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
3453 _ephysics_body_efl_canvas_object_del_cb);
3454 evas_object_event_callback_del(obj, EVAS_CALLBACK_RESIZE,
3455 _ephysics_body_efl_canvas_object_resize_cb);
3456 evas_object_map_enable_set(obj, EINA_FALSE);
3457 }
3458
3459 if (body->default_face)
3460 {
3461 evas_object_event_callback_del(body->evas_obj,
3462 EVAS_CALLBACK_RESTACK,
3463 _ephysics_body_soft_body_evas_restack_cb);
3464 _ephysics_body_soft_body_slices_clean(body->default_face->slices);
3465 }
3466
3467 return obj;
3468 }
3469
3470 EAPI Evas_Object *
ephysics_body_evas_object_get(const EPhysics_Body * body)3471 ephysics_body_evas_object_get(const EPhysics_Body *body)
3472 {
3473 if (!body)
3474 {
3475 ERR("Can't get evas object from body, it wasn't provided.");
3476 return NULL;
3477 }
3478
3479 return body->evas_obj;
3480 }
3481
3482 EAPI void
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)3483 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)
3484 {
3485 if (!body)
3486 {
3487 ERR("Can't set body geometry, body is null.");
3488 return;
3489 }
3490
3491 INF("Body: %p geometry set to x=%i y=%i z=%i w=%i h=%i d=%i.",
3492 body, x, y, z, w, h, d);
3493
3494 if ((w <= 0) || (h <= 0) || (d <= 0))
3495 {
3496 ERR("Width, height and depth must to be a non-null, positive value.");
3497 return;
3498 }
3499
3500 ephysics_world_lock_take(body->world);
3501 _ephysics_body_geometry_set(body, x, y, z, w, h, d,
3502 ephysics_world_rate_get(body->world));
3503 ephysics_world_lock_release(body->world);
3504 }
3505
3506 EAPI void
ephysics_body_resize(EPhysics_Body * body,Evas_Coord w,Evas_Coord h,Evas_Coord d)3507 ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h, Evas_Coord d)
3508 {
3509 if (!body)
3510 {
3511 ERR("Can't set body size, body is null.");
3512 return;
3513 }
3514
3515 if ((w <= 0) || (h <= 0) || (d <= 0))
3516 {
3517 ERR("Width, height and depth must to be a non-null, positive value.");
3518 return;
3519 }
3520
3521 ephysics_world_lock_take(body->world);
3522 _ephysics_body_resize(body, w, h, d);
3523 ephysics_world_lock_release(body->world);
3524 }
3525
3526 EAPI void
ephysics_body_move(EPhysics_Body * body,Evas_Coord x,Evas_Coord y,Evas_Coord z)3527 ephysics_body_move(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord z)
3528 {
3529 if (!body)
3530 {
3531 ERR("Can't set body position, body is null.");
3532 return;
3533 }
3534
3535 ephysics_world_lock_take(body->world);
3536 _ephysics_body_move(body, x, y, z);
3537 ephysics_world_lock_release(body->world);
3538 }
3539
3540 EAPI void
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)3541 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)
3542 {
3543 btTransform trans;
3544 btVector3 scale;
3545 double rate;
3546 int wy, height;
3547
3548 if (!body)
3549 {
3550 ERR("Can't get body position, body is null.");
3551 return;
3552 }
3553
3554 trans = _ephysics_body_transform_get(body);
3555 scale = btVector3(body->scale[0], body->scale[1], body->scale[2]);
3556
3557 rate = ephysics_world_rate_get(body->world);
3558 ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL,
3559 NULL, &height, NULL);
3560 height += wy;
3561
3562 if (x) *x = round((trans.getOrigin().getX() - scale[0] / 2) * rate);
3563 if (y) *y = height - round((trans.getOrigin().getY() + scale[1] / 2)
3564 * rate);
3565 if (z) *z = round((trans.getOrigin().getZ() - scale[2] / 2) * rate);
3566 if (w) *w = body->size.w;
3567 if (h) *h = body->size.h;
3568 if (d) *d = body->size.d;
3569 }
3570
3571 EAPI void
ephysics_body_mass_set(EPhysics_Body * body,double mass)3572 ephysics_body_mass_set(EPhysics_Body *body, double mass)
3573 {
3574 if (!body)
3575 {
3576 ERR("Can't set body mass, body is null.");
3577 return;
3578 }
3579
3580 if (mass < 0)
3581 {
3582 ERR("Can't set body's mass, it must to be non-negative.");
3583 return;
3584 }
3585
3586 ephysics_world_lock_take(body->world);
3587 body->material = EPHYSICS_BODY_MATERIAL_CUSTOM;
3588 body->density = 0;
3589 _ephysics_body_mass_set(body, mass);
3590 ephysics_world_lock_release(body->world);
3591 }
3592
3593 EAPI double
ephysics_body_mass_get(const EPhysics_Body * body)3594 ephysics_body_mass_get(const EPhysics_Body *body)
3595 {
3596 if (!body)
3597 {
3598 ERR("Can't get body mass, body is null.");
3599 return 0;
3600 }
3601
3602 return body->mass;
3603 }
3604
3605 EAPI void
ephysics_body_linear_velocity_set(EPhysics_Body * body,double x,double y,double z)3606 ephysics_body_linear_velocity_set(EPhysics_Body *body, double x, double y, double z)
3607 {
3608 if (!body)
3609 {
3610 ERR("Can't set body linear velocity, body is null.");
3611 return;
3612 }
3613
3614 _ephysics_body_linear_velocity_set(body, x, y, z,
3615 ephysics_world_rate_get(body->world));
3616 DBG("Linear velocity of body %p set to (%lf, %lf, %lf).", body, x, y, z);
3617 }
3618
3619 static void
_ephysics_body_soft_body_linear_velocity_get(const EPhysics_Body * body,double * x,double * y,double * z,double rate)3620 _ephysics_body_soft_body_linear_velocity_get(const EPhysics_Body *body, double *x, double *y, double *z, double rate)
3621 {
3622 btVector3 total_velocity = btVector3(0, 0, 0);
3623 int nodes_size = body->soft_body->m_nodes.size();
3624
3625 for (int i = 0; i < nodes_size; i++)
3626 total_velocity += body->soft_body->m_nodes[i].m_v;
3627
3628 total_velocity /= nodes_size;
3629 if (x) *x = total_velocity.getX() * rate;
3630 if (y) *y = -total_velocity.getY() * rate;
3631 if (z) *z = total_velocity.getZ() * rate;
3632 }
3633
3634 EAPI void
ephysics_body_linear_velocity_get(const EPhysics_Body * body,double * x,double * y,double * z)3635 ephysics_body_linear_velocity_get(const EPhysics_Body *body, double *x, double *y, double *z)
3636 {
3637 double rate;
3638
3639 if (!body)
3640 {
3641 ERR("Can't get linear velocity, body is null.");
3642 return;
3643 }
3644
3645 rate = ephysics_world_rate_get(body->world);
3646 if (body->rigid_body)
3647 {
3648 if (x) *x = body->rigid_body->getLinearVelocity().getX() * rate;
3649 if (y) *y = -body->rigid_body->getLinearVelocity().getY() * rate;
3650 if (z) *z = body->rigid_body->getLinearVelocity().getZ() * rate;
3651 return;
3652 }
3653 _ephysics_body_soft_body_linear_velocity_get(body, x, y, z, rate);
3654 }
3655
3656 EAPI void
ephysics_body_angular_velocity_set(EPhysics_Body * body,double x,double y,double z)3657 ephysics_body_angular_velocity_set(EPhysics_Body *body, double x, double y, double z)
3658 {
3659 if (!body)
3660 {
3661 ERR("Can't set angular velocity, body is null.");
3662 return;
3663 }
3664
3665 BODY_CLOTH_CHECK();
3666
3667 ephysics_world_lock_take(body->world);
3668 ephysics_body_activate(body, EINA_TRUE);
3669 body->rigid_body->setAngularVelocity(btVector3(-x / RAD_TO_DEG,
3670 -y / RAD_TO_DEG,
3671 -z/RAD_TO_DEG));
3672
3673 DBG("Angular velocity of body %p set to (%lf, %lf, %lf).", body, x, y, z);
3674 ephysics_world_lock_release(body->world);
3675 }
3676
3677 EAPI void
ephysics_body_angular_velocity_get(const EPhysics_Body * body,double * x,double * y,double * z)3678 ephysics_body_angular_velocity_get(const EPhysics_Body *body, double *x, double *y, double *z)
3679 {
3680 if (!body)
3681 {
3682 ERR("Can't get angular velocity, body is null.");
3683 return;
3684 }
3685
3686 BODY_CLOTH_CHECK();
3687
3688 if (x) *x = -body->rigid_body->getAngularVelocity().getX() * RAD_TO_DEG;
3689 if (y) *y = -body->rigid_body->getAngularVelocity().getY() * RAD_TO_DEG;
3690 if (z) *z = -body->rigid_body->getAngularVelocity().getZ() * RAD_TO_DEG;
3691 }
3692
3693 EAPI void
ephysics_body_sleeping_threshold_set(EPhysics_Body * body,double linear_threshold,double angular_threshold)3694 ephysics_body_sleeping_threshold_set(EPhysics_Body *body, double linear_threshold, double angular_threshold)
3695 {
3696 if (!body)
3697 {
3698 ERR("Can't set sleeping thresholds, body is null.");
3699 return;
3700 }
3701
3702 BODY_CLOTH_CHECK();
3703
3704 ephysics_world_lock_take(body->world);
3705 _ephysics_body_sleeping_threshold_set(body, linear_threshold,
3706 angular_threshold,
3707 ephysics_world_rate_get(body->world));
3708 ephysics_world_lock_release(body->world);
3709 }
3710
3711 EAPI void
ephysics_body_sleeping_threshold_get(const EPhysics_Body * body,double * linear_threshold,double * angular_threshold)3712 ephysics_body_sleeping_threshold_get(const EPhysics_Body *body, double *linear_threshold, double *angular_threshold)
3713 {
3714 double rate;
3715
3716 if (!body)
3717 {
3718 ERR("Can't get linear sleeping threshold, body is null.");
3719 return;
3720 }
3721
3722 BODY_CLOTH_CHECK();
3723
3724 rate = ephysics_world_rate_get(body->world);
3725 if (linear_threshold)
3726 *linear_threshold = body->rigid_body->getLinearSleepingThreshold() * rate;
3727 if (angular_threshold)
3728 *angular_threshold = body->rigid_body->getAngularSleepingThreshold() *
3729 RAD_TO_DEG;
3730 }
3731
3732 EAPI void
ephysics_body_stop(EPhysics_Body * body)3733 ephysics_body_stop(EPhysics_Body *body)
3734 {
3735 if (!body)
3736 {
3737 ERR("Can't stop a null body.");
3738 return;
3739 }
3740
3741 ephysics_world_lock_take(body->world);
3742 if (body->rigid_body)
3743 {
3744 body->rigid_body->setLinearVelocity(btVector3(0, 0, 0));
3745 body->rigid_body->setAngularVelocity(btVector3(0, 0, 0));
3746 }
3747
3748 if (body->soft_body)
3749 {
3750 for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
3751 {
3752 body->soft_body->m_nodes[i].m_v *= 0;
3753 body->soft_body->m_nodes[i].m_f *= 0;
3754 }
3755 }
3756 ephysics_world_lock_release(body->world);
3757
3758 DBG("Body %p stopped", body);
3759 }
3760
3761 EAPI void
ephysics_body_damping_set(EPhysics_Body * body,double linear_damping,double angular_damping)3762 ephysics_body_damping_set(EPhysics_Body *body, double linear_damping, double angular_damping)
3763 {
3764 if (!body)
3765 {
3766 ERR("Can't set body damping, body is null.");
3767 return;
3768 }
3769
3770 BODY_CLOTH_CHECK();
3771
3772 ephysics_world_lock_take(body->world);
3773 body->rigid_body->setDamping(btScalar(linear_damping),
3774 btScalar(angular_damping));
3775 ephysics_world_lock_release(body->world);
3776 }
3777
3778 EAPI void
ephysics_body_damping_get(const EPhysics_Body * body,double * linear_damping,double * angular_damping)3779 ephysics_body_damping_get(const EPhysics_Body *body, double *linear_damping, double *angular_damping)
3780 {
3781 if (!body)
3782 {
3783 ERR("Can't get damping, body is null.");
3784 return;
3785 }
3786
3787 BODY_CLOTH_CHECK();
3788
3789 if (linear_damping) *linear_damping = body->rigid_body->getLinearDamping();
3790 if (angular_damping) *angular_damping =
3791 body->rigid_body->getAngularDamping();
3792 }
3793
3794 EAPI void
ephysics_body_evas_object_update(EPhysics_Body * body)3795 ephysics_body_evas_object_update(EPhysics_Body *body)
3796 {
3797 if (!body)
3798 {
3799 ERR("Couldn't update a null body.");
3800 return;
3801 }
3802
3803 _ephysics_body_evas_object_default_update(body);
3804 }
3805
3806 EAPI void
ephysics_body_event_callback_add(EPhysics_Body * body,EPhysics_Callback_Body_Type type,EPhysics_Body_Event_Cb func,const void * data)3807 ephysics_body_event_callback_add(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func, const void *data)
3808 {
3809 EPhysics_Body_Callback *cb;
3810
3811 if (!body)
3812 {
3813 ERR("Can't set body event callback, body is null.");
3814 return;
3815 }
3816
3817 if (!func)
3818 {
3819 ERR("Can't set body event callback, function is null.");
3820 return;
3821 }
3822
3823 if ((type < 0) || (type >= EPHYSICS_CALLBACK_BODY_LAST))
3824 {
3825 ERR("Can't set body event callback, callback type is wrong.");
3826 return;
3827 }
3828
3829 cb = (EPhysics_Body_Callback *)calloc(1, sizeof(EPhysics_Body_Callback));
3830 if (!cb)
3831 {
3832 ERR("Can't set body event callback, can't create cb instance.");
3833 return;
3834 }
3835
3836 cb->func = func;
3837 cb->type = type;
3838 cb->data = (void *)data;
3839
3840 body->callbacks = eina_inlist_append(body->callbacks, EINA_INLIST_GET(cb));
3841 if (type == EPHYSICS_CALLBACK_BODY_COLLISION)
3842 body->collision_cb++;
3843 }
3844
3845 EAPI void *
ephysics_body_event_callback_del(EPhysics_Body * body,EPhysics_Callback_Body_Type type,EPhysics_Body_Event_Cb func)3846 ephysics_body_event_callback_del(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func)
3847 {
3848 EPhysics_Body_Callback *cb;
3849 void *cb_data = NULL;
3850
3851 if (!body)
3852 {
3853 ERR("Can't delete body event callback, body is null.");
3854 return NULL;
3855 }
3856
3857 EINA_INLIST_FOREACH(body->callbacks, cb)
3858 {
3859 if ((cb->type != type) || (cb->func != func))
3860 continue;
3861
3862 cb_data = cb->data;
3863 _ephysics_body_event_callback_del(body, cb);
3864 if (type == EPHYSICS_CALLBACK_BODY_COLLISION)
3865 body->collision_cb--;
3866 break;
3867 }
3868
3869 return cb_data;
3870 }
3871
3872 EAPI void *
ephysics_body_event_callback_del_full(EPhysics_Body * body,EPhysics_Callback_Body_Type type,EPhysics_Body_Event_Cb func,void * data)3873 ephysics_body_event_callback_del_full(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func, void *data)
3874 {
3875 EPhysics_Body_Callback *cb;
3876 void *cb_data = NULL;
3877
3878 if (!body)
3879 {
3880 ERR("Can't delete body event callback, body is null.");
3881 return NULL;
3882 }
3883
3884 EINA_INLIST_FOREACH(body->callbacks, cb)
3885 {
3886 if ((cb->type != type) || (cb->func != func) || (cb->data != data))
3887 continue;
3888
3889 cb_data = cb->data;
3890 _ephysics_body_event_callback_del(body, cb);
3891 break;
3892 }
3893
3894 return cb_data;
3895 }
3896
3897 static void
_ephysics_body_restitution_set(EPhysics_Body * body,double restitution)3898 _ephysics_body_restitution_set(EPhysics_Body *body, double restitution)
3899 {
3900 DBG("Body %p restitution set to %lf", body, restitution);
3901 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
3902 {
3903 body->rigid_body->setRestitution(btScalar(restitution));
3904 return;
3905 }
3906
3907 body->soft_body->setRestitution(btScalar(restitution));
3908 }
3909
3910 EAPI void
ephysics_body_restitution_set(EPhysics_Body * body,double restitution)3911 ephysics_body_restitution_set(EPhysics_Body *body, double restitution)
3912 {
3913 if (!body)
3914 {
3915 ERR("Can't set body restitution, body is null.");
3916 return;
3917 }
3918
3919 ephysics_world_lock_take(body->world);
3920 body->material = EPHYSICS_BODY_MATERIAL_CUSTOM;
3921 _ephysics_body_restitution_set(body, restitution);
3922 ephysics_world_lock_release(body->world);
3923 }
3924
3925 EAPI double
ephysics_body_restitution_get(const EPhysics_Body * body)3926 ephysics_body_restitution_get(const EPhysics_Body *body)
3927 {
3928 if (!body)
3929 {
3930 ERR("Can't get body restitution, body is null.");
3931 return 0;
3932 }
3933
3934 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
3935 return body->rigid_body->getRestitution();
3936
3937 return body->soft_body->getRestitution();
3938 }
3939
3940 static void
_ephysics_body_friction_set(EPhysics_Body * body,double friction)3941 _ephysics_body_friction_set(EPhysics_Body *body, double friction)
3942 {
3943 DBG("Body %p friction set to %lf", body, friction);
3944 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
3945 {
3946 body->rigid_body->setFriction(btScalar(friction));
3947 return;
3948 }
3949
3950 body->soft_body->setFriction(btScalar(friction));
3951 }
3952
3953 EAPI void
ephysics_body_friction_set(EPhysics_Body * body,double friction)3954 ephysics_body_friction_set(EPhysics_Body *body, double friction)
3955 {
3956 if (!body)
3957 {
3958 ERR("Can't set body friction, body is null.");
3959 return;
3960 }
3961
3962 ephysics_world_lock_take(body->world);
3963 body->material = EPHYSICS_BODY_MATERIAL_CUSTOM;
3964 _ephysics_body_friction_set(body, friction);
3965 ephysics_world_lock_release(body->world);
3966 }
3967
3968 EAPI double
ephysics_body_friction_get(const EPhysics_Body * body)3969 ephysics_body_friction_get(const EPhysics_Body *body)
3970 {
3971 if (!body)
3972 {
3973 ERR("Can't get body friction, body is null.");
3974 return 0;
3975 }
3976
3977 if (body->type == EPHYSICS_BODY_TYPE_RIGID)
3978 return body->rigid_body->getFriction();
3979
3980 return body->soft_body->getFriction();
3981 }
3982
3983 EAPI EPhysics_World *
ephysics_body_world_get(const EPhysics_Body * body)3984 ephysics_body_world_get(const EPhysics_Body *body)
3985 {
3986 if (!body)
3987 {
3988 ERR("Can't get the world a null body belongs to.");
3989 return NULL;
3990 }
3991
3992 return body->world;
3993 }
3994
3995 static void
_ephysics_body_soft_body_central_impulse_apply(EPhysics_Body * body,btVector3 impulse)3996 _ephysics_body_soft_body_central_impulse_apply(EPhysics_Body *body, btVector3 impulse)
3997 {
3998 btSoftBody::Face *face;
3999
4000 for (int m = 0; m < body->soft_body->m_faces.size(); m++)
4001 {
4002 face = &body->soft_body->m_faces[m];
4003 for (int n = 0; n < 3; n++)
4004 face->m_n[n]->m_v += impulse * face->m_n[n]->m_im;
4005 }
4006 }
4007
4008 EAPI void
ephysics_body_central_impulse_apply(EPhysics_Body * body,double x,double y,double z)4009 ephysics_body_central_impulse_apply(EPhysics_Body *body, double x, double y, double z)
4010 {
4011 double rate;
4012 btVector3 impulse;
4013
4014 if (!body)
4015 {
4016 ERR("Can't apply impulse to a null body.");
4017 return;
4018 }
4019
4020 rate = ephysics_world_rate_get(body->world);
4021
4022 ephysics_world_lock_take(body->world);
4023 ephysics_body_activate(body, EINA_TRUE);
4024
4025 impulse = btVector3(x / rate, - y / rate, z / rate);
4026
4027 if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
4028 _ephysics_body_soft_body_central_impulse_apply(body, impulse);
4029 else
4030 body->rigid_body->applyCentralImpulse(impulse);
4031
4032 ephysics_world_lock_release(body->world);
4033 }
4034
4035 EAPI void
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)4036 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)
4037 {
4038 double rate;
4039
4040 if (!body)
4041 {
4042 ERR("Can't apply impulse to a null body.");
4043 return;
4044 }
4045
4046 rate = ephysics_world_rate_get(body->world);
4047
4048 ephysics_world_lock_take(body->world);
4049 ephysics_body_activate(body, EINA_TRUE);
4050 body->rigid_body->applyImpulse(btVector3(x / rate, - y / rate, z / rate),
4051 btVector3((double) pos_x / rate,
4052 (double) pos_y / rate,
4053 (double) pos_z / rate));
4054 ephysics_world_lock_release(body->world);
4055 }
4056
4057 EAPI void
ephysics_body_linear_movement_enable_set(EPhysics_Body * body,Eina_Bool enable_x,Eina_Bool enable_y,Eina_Bool enable_z)4058 ephysics_body_linear_movement_enable_set(EPhysics_Body *body, Eina_Bool enable_x, Eina_Bool enable_y, Eina_Bool enable_z)
4059 {
4060 if (!body)
4061 {
4062 ERR("Can't set linear factor on a null body.");
4063 return;
4064 }
4065
4066 BODY_CLOTH_CHECK();
4067
4068 ephysics_world_lock_take(body->world);
4069 body->rigid_body->setLinearFactor(btVector3(!!enable_x, !!enable_y,
4070 !!enable_z));
4071 ephysics_world_lock_release(body->world);
4072 }
4073
4074 EAPI void
ephysics_body_linear_movement_enable_get(const EPhysics_Body * body,Eina_Bool * enable_x,Eina_Bool * enable_y,Eina_Bool * enable_z)4075 ephysics_body_linear_movement_enable_get(const EPhysics_Body *body, Eina_Bool *enable_x, Eina_Bool *enable_y, Eina_Bool *enable_z)
4076 {
4077 if (!body)
4078 {
4079 ERR("Can't check if linear factor is enabled, body is null.");
4080 return;
4081 }
4082
4083 BODY_CLOTH_CHECK();
4084
4085 if (enable_x) *enable_x = !!body->rigid_body->getLinearFactor().x();
4086 if (enable_y) *enable_y = !!body->rigid_body->getLinearFactor().y();
4087 if (enable_z) *enable_z = !!body->rigid_body->getLinearFactor().z();
4088 }
4089
4090 EAPI void
ephysics_body_torque_impulse_apply(EPhysics_Body * body,double pitch,double yaw,double roll)4091 ephysics_body_torque_impulse_apply(EPhysics_Body *body, double pitch, double yaw, double roll)
4092 {
4093 if (!body)
4094 {
4095 ERR("Can't apply torque impulse to a null body.");
4096 return;
4097 }
4098
4099 ephysics_world_lock_take(body->world);
4100 ephysics_body_activate(body, EINA_TRUE);
4101 body->rigid_body->applyTorqueImpulse(btVector3(-pitch, -yaw, -roll));
4102 ephysics_world_lock_release(body->world);
4103 }
4104
4105 EAPI void
ephysics_body_angular_movement_enable_set(EPhysics_Body * body,Eina_Bool enable_x,Eina_Bool enable_y,Eina_Bool enable_z)4106 ephysics_body_angular_movement_enable_set(EPhysics_Body *body, Eina_Bool enable_x, Eina_Bool enable_y, Eina_Bool enable_z)
4107 {
4108 if (!body)
4109 {
4110 ERR("Can't set rotation on a null body.");
4111 return;
4112 }
4113
4114 BODY_CLOTH_CHECK();
4115
4116 ephysics_world_lock_take(body->world);
4117 body->rigid_body->setAngularFactor(btVector3(!!enable_x, !!enable_y,
4118 !!enable_z));
4119 ephysics_world_lock_release(body->world);
4120 }
4121
4122 EAPI void
ephysics_body_angular_movement_enable_get(const EPhysics_Body * body,Eina_Bool * enable_x,Eina_Bool * enable_y,Eina_Bool * enable_z)4123 ephysics_body_angular_movement_enable_get(const EPhysics_Body *body, Eina_Bool *enable_x, Eina_Bool *enable_y, Eina_Bool *enable_z)
4124 {
4125 if (!body)
4126 {
4127 ERR("Can't check if rotation is enabled, body is null.");
4128 return;
4129 }
4130
4131 BODY_CLOTH_CHECK();
4132
4133 if (enable_x) *enable_x = !!body->rigid_body->getAngularFactor().x();
4134 if (enable_y) *enable_y = !!body->rigid_body->getAngularFactor().y();
4135 if (enable_z) *enable_z = !!body->rigid_body->getAngularFactor().z();
4136 }
4137
4138 EAPI EPhysics_Quaternion *
ephysics_body_rotation_get(const EPhysics_Body * body,EPhysics_Quaternion * rotation)4139 ephysics_body_rotation_get(const EPhysics_Body *body, EPhysics_Quaternion *rotation)
4140 {
4141 EPhysics_Quaternion *quat;
4142 btTransform trans;
4143
4144 if (!body)
4145 {
4146 ERR("Can't get rotation, body is null.");
4147 return NULL;
4148 }
4149
4150 if (!rotation)
4151 {
4152 quat = ephysics_quaternion_new();
4153 if (!quat) return NULL;
4154 }
4155 else
4156 quat = rotation;
4157
4158 trans = _ephysics_body_transform_get(body);
4159 quat->x = trans.getRotation().x();
4160 quat->y = trans.getRotation().y();
4161 quat->z = trans.getRotation().z();
4162 quat->w = trans.getRotation().getW();
4163
4164 return quat;
4165 }
4166
4167 static void
_ephysics_body_soft_body_rotation_set(EPhysics_Body * body,btTransform trans)4168 _ephysics_body_soft_body_rotation_set(EPhysics_Body *body, btTransform trans)
4169 {
4170 btSoftBody::Node *node;
4171 const btScalar margin= body->soft_body->getCollisionShape()->getMargin();
4172 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
4173
4174 for (int i = 0; i < body->soft_body->m_nodes.size(); i++)
4175 {
4176 node = &body->soft_body->m_nodes[i];
4177 node->m_n = (trans.getBasis() * btVector3(1, 1, 1));
4178 vol = btDbvtVolume::FromCR(node->m_x, margin);
4179
4180 body->soft_body->m_ndbvt.update(node->m_leaf, vol);
4181 }
4182
4183 body->soft_body->updateNormals();
4184 body->soft_body->updateBounds();
4185 body->soft_body->updateConstants();
4186 }
4187
4188 EAPI void
ephysics_body_rotation_set(EPhysics_Body * body,EPhysics_Quaternion * quat)4189 ephysics_body_rotation_set(EPhysics_Body *body, EPhysics_Quaternion *quat)
4190 {
4191 btQuaternion bt_quat;
4192 btTransform trans;
4193 double x, y, z, w;
4194
4195 if (!body)
4196 {
4197 ERR("Can't set rotation, body is null.");
4198 return;
4199 }
4200
4201 if (!quat)
4202 {
4203 ERR("Can't set rotation, quaternion is null.");
4204 return;
4205 }
4206
4207 ephysics_quaternion_get(quat, &x, &y, &z, &w);
4208
4209 ephysics_world_lock_take(body->world);
4210 ephysics_body_activate(body, EINA_TRUE);
4211
4212 bt_quat = btQuaternion(x, y, z, w);
4213 trans = _ephysics_body_transform_get(body);
4214 trans.setRotation(bt_quat);
4215
4216 if (body->soft_body)
4217 _ephysics_body_soft_body_rotation_set(body, trans);
4218 else
4219 {
4220 body->rigid_body->proceedToTransform(trans);
4221 body->rigid_body->getMotionState()->setWorldTransform(trans);
4222 }
4223
4224 ephysics_world_lock_release(body->world);
4225 }
4226
4227 EAPI void
ephysics_body_data_set(EPhysics_Body * body,void * data)4228 ephysics_body_data_set(EPhysics_Body *body, void *data)
4229 {
4230 if (!body)
4231 {
4232 ERR("Can't set data, body is null.");
4233 return;
4234 }
4235
4236 body->data = data;
4237 }
4238
4239 EAPI void *
ephysics_body_data_get(const EPhysics_Body * body)4240 ephysics_body_data_get(const EPhysics_Body *body)
4241 {
4242 if (!body)
4243 {
4244 ERR("Can't get data, body is null.");
4245 return NULL;
4246 }
4247
4248 return body->data;
4249 }
4250
4251 EAPI void
ephysics_body_central_force_apply(EPhysics_Body * body,double x,double y,double z)4252 ephysics_body_central_force_apply(EPhysics_Body *body, double x, double y, double z)
4253 {
4254 double rate;
4255
4256 if (!body)
4257 {
4258 ERR("Can't apply force to a null body.");
4259 return;
4260 }
4261
4262 ephysics_world_lock_take(body->world);
4263 rate = ephysics_world_rate_get(body->world);
4264 ephysics_body_forces_apply(body);
4265 body->rigid_body->applyCentralForce(btVector3(x / rate, - y / rate,
4266 z / rate));
4267 _ephysics_body_forces_update(body);
4268 ephysics_world_lock_release(body->world);
4269 }
4270
4271 EAPI void
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)4272 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)
4273 {
4274 double rate;
4275
4276 if (!body)
4277 {
4278 ERR("Can't apply force to a null body.");
4279 return;
4280 }
4281
4282 rate = ephysics_world_rate_get(body->world);
4283 ephysics_world_lock_take(body->world);
4284 ephysics_body_forces_apply(body);
4285 body->rigid_body->applyForce(btVector3(x / rate, - y / rate, z / rate),
4286 btVector3((double) pos_x / rate,
4287 (double) pos_y / rate,
4288 (double) pos_z / rate));
4289 _ephysics_body_forces_update(body);
4290 ephysics_world_lock_release(body->world);
4291 }
4292
4293 EAPI void
ephysics_body_torque_apply(EPhysics_Body * body,double torque_x,double torque_y,double torque_z)4294 ephysics_body_torque_apply(EPhysics_Body *body, double torque_x, double torque_y, double torque_z)
4295 {
4296 if (!body)
4297 {
4298 ERR("Can't apply force to a null body.");
4299 return;
4300 }
4301
4302 ephysics_world_lock_take(body->world);
4303 ephysics_body_forces_apply(body);
4304 body->rigid_body->applyTorque(btVector3(-torque_x, -torque_y, -torque_z));
4305 _ephysics_body_forces_update(body);
4306 ephysics_world_lock_release(body->world);
4307 }
4308
4309 EAPI void
ephysics_body_forces_get(const EPhysics_Body * body,double * x,double * y,double * z)4310 ephysics_body_forces_get(const EPhysics_Body *body, double *x, double *y, double *z)
4311 {
4312 double rate, gx, gy, gz;
4313
4314 if (!body)
4315 {
4316 ERR("Can't get forces from a null body.");
4317 return;
4318 }
4319
4320 rate = ephysics_world_rate_get(body->world);
4321 ephysics_world_gravity_get(body->world, &gx, &gy, &gz);
4322
4323 if (x) *x = body->force.x * rate + gx;
4324 if (y) *y = -body->force.y * rate + gy;
4325 if (z) *z = body->force.z * rate + gz;
4326 }
4327
4328 EAPI void
ephysics_body_torques_get(const EPhysics_Body * body,double * x,double * y,double * z)4329 ephysics_body_torques_get(const EPhysics_Body *body, double *x, double *y, double *z)
4330 {
4331 if (!body)
4332 {
4333 ERR("Can't get torques from a null body.");
4334 return;
4335 }
4336
4337 if (x) *x = -body->force.torque_x;
4338 if (y) *y = -body->force.torque_y;
4339 if (z) *z = -body->force.torque_z;
4340 }
4341
4342 EAPI void
ephysics_body_forces_clear(EPhysics_Body * body)4343 ephysics_body_forces_clear(EPhysics_Body *body)
4344 {
4345 if (!body)
4346 {
4347 ERR("Can't clear forces of a null body.");
4348 return;
4349 }
4350
4351 body->force.x = 0;
4352 body->force.y = 0;
4353 body->force.z = 0;
4354 body->force.torque_x = 0;
4355 body->force.torque_y = 0;
4356 body->force.torque_z = 0;
4357 }
4358
4359 EAPI void
ephysics_body_center_mass_get(const EPhysics_Body * body,double * x,double * y,double * z)4360 ephysics_body_center_mass_get(const EPhysics_Body *body, double *x, double *y, double *z)
4361 {
4362 if (!body)
4363 {
4364 ERR("Can't get center of mass from a null body.");
4365 return;
4366 }
4367
4368 if (x) *x = body->cm.x;
4369 if (y) *y = body->cm.y;
4370 if (z) *z = body->cm.z;
4371 }
4372
4373 EAPI void
ephysics_body_density_set(EPhysics_Body * body,double density)4374 ephysics_body_density_set(EPhysics_Body *body, double density)
4375 {
4376 if (!body)
4377 {
4378 ERR("Can't set the density of a null body's material.");
4379 return;
4380 }
4381
4382 body->material = EPHYSICS_BODY_MATERIAL_CUSTOM;
4383 body->density = density;
4384 ephysics_world_lock_take(body->world);
4385 _ephysics_body_mass_set(body, 0);
4386 ephysics_world_lock_release(body->world);
4387 }
4388
4389 EAPI double
ephysics_body_density_get(const EPhysics_Body * body)4390 ephysics_body_density_get(const EPhysics_Body *body)
4391 {
4392 if (!body)
4393 {
4394 ERR("Can't get the density of a null body's material.");
4395 return 0;
4396 }
4397
4398 return body->density;
4399 }
4400
4401 EAPI void
ephysics_body_material_set(EPhysics_Body * body,EPhysics_Body_Material material)4402 ephysics_body_material_set(EPhysics_Body *body, EPhysics_Body_Material material)
4403 {
4404 if (!body)
4405 {
4406 ERR("Can't set body's material.");
4407 return;
4408 }
4409
4410 if (material >= EPHYSICS_BODY_MATERIAL_LAST)
4411 {
4412 ERR("Invalid material.");
4413 return;
4414 }
4415
4416 if (material != ephysics_material_props[material].material)
4417 {
4418 ERR("Material properties weren't found.");
4419 return;
4420 }
4421
4422 if (material == EPHYSICS_BODY_MATERIAL_CUSTOM)
4423 {
4424 body->material = material;
4425 return;
4426 }
4427
4428 ephysics_world_lock_take(body->world);
4429 body->density = ephysics_material_props[material].density;
4430 _ephysics_body_mass_set(body, 0);
4431 _ephysics_body_friction_set(body,
4432 ephysics_material_props[material].friction);
4433 _ephysics_body_restitution_set(
4434 body, ephysics_material_props[material].restitution);
4435 body->material = material;
4436 ephysics_world_lock_release(body->world);
4437 }
4438
4439 EAPI EPhysics_Body_Material
ephysics_body_material_get(const EPhysics_Body * body)4440 ephysics_body_material_get(const EPhysics_Body *body)
4441 {
4442 if (!body)
4443 {
4444 ERR("Can't get body's material.");
4445 return EPHYSICS_BODY_MATERIAL_LAST;
4446 }
4447
4448 return body->material;
4449 }
4450
4451 EAPI void
ephysics_body_light_set(EPhysics_Body * body,Eina_Bool enable)4452 ephysics_body_light_set(EPhysics_Body *body, Eina_Bool enable)
4453 {
4454 if (!body)
4455 {
4456 ERR("No body, no light.");
4457 return;
4458 }
4459
4460 body->light_apply = !!enable;
4461 }
4462
4463 EAPI Eina_Bool
ephysics_body_light_get(const EPhysics_Body * body)4464 ephysics_body_light_get(const EPhysics_Body *body)
4465 {
4466 if (!body)
4467 {
4468 ERR("No body, no light.");
4469 return EINA_FALSE;
4470 }
4471
4472 return body->light_apply;
4473 }
4474
4475 EAPI double
ephysics_body_volume_get(const EPhysics_Body * body)4476 ephysics_body_volume_get(const EPhysics_Body *body)
4477 {
4478 if (!body)
4479 {
4480 ERR("No body, no volume.");
4481 return -1;
4482 }
4483 return _ephysics_body_volume_get(body);
4484 }
4485
4486 EAPI void
ephysics_body_back_face_culling_set(EPhysics_Body * body,Eina_Bool enable)4487 ephysics_body_back_face_culling_set(EPhysics_Body *body, Eina_Bool enable)
4488 {
4489 if (!body)
4490 {
4491 ERR("Body is NULL.");
4492 return;
4493 }
4494 body->back_face_culling = !!enable;
4495 }
4496
4497 EAPI Eina_Bool
ephysics_body_back_face_culling_get(const EPhysics_Body * body)4498 ephysics_body_back_face_culling_get(const EPhysics_Body *body)
4499 {
4500 if (!body)
4501 {
4502 ERR("Body is NULL.");
4503 return EINA_FALSE;
4504 }
4505 return body->back_face_culling;
4506 }
4507
4508 EAPI Eina_Bool
ephysics_body_clockwise_get(const EPhysics_Body * body)4509 ephysics_body_clockwise_get(const EPhysics_Body *body)
4510 {
4511 if (!body)
4512 {
4513 ERR("Body is NULL.");
4514 return EINA_FALSE;
4515 }
4516 return body->clockwise;
4517 }
4518
4519 static void
_ephysics_body_face_obj_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)4520 _ephysics_body_face_obj_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
4521 {
4522 EPhysics_Body *body = (EPhysics_Body *) data;
4523 EPhysics_Body_Face_Obj *face_obj;
4524 Eina_List *l;
4525 void *ldata;
4526
4527 EINA_LIST_FOREACH(body->face_objs, l, ldata)
4528 {
4529 face_obj = (EPhysics_Body_Face_Obj *)ldata;
4530 if (face_obj->obj == obj)
4531 {
4532 body->face_objs = eina_list_remove(body->face_objs, face_obj);
4533 free(face_obj);
4534 return;
4535 }
4536 }
4537 }
4538
4539 static void
_ephysics_body_face_obj_unset(Evas_Object * obj,Evas_Object_Event_Cb resize_func)4540 _ephysics_body_face_obj_unset(Evas_Object *obj, Evas_Object_Event_Cb resize_func)
4541 {
4542 evas_object_map_enable_set(obj, EINA_FALSE);
4543 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
4544 _ephysics_body_face_obj_del_cb);
4545 evas_object_event_callback_del(obj, EVAS_CALLBACK_RESIZE, resize_func);
4546 }
4547
4548 static void
_ephysics_body_face_evas_object_del(EPhysics_Body * body,EPhysics_Body_Face_Obj * face_obj,Evas_Object_Event_Cb resize_func)4549 _ephysics_body_face_evas_object_del(EPhysics_Body *body, EPhysics_Body_Face_Obj *face_obj, Evas_Object_Event_Cb resize_func)
4550 {
4551 _ephysics_body_face_obj_unset(face_obj->obj, resize_func);
4552 body->face_objs = eina_list_remove(body->face_objs, face_obj);
4553 free(face_obj);
4554 }
4555
4556 static void
_ephysics_body_face_evas_object_add(EPhysics_Body * body,EPhysics_Body_Face face,Evas_Object * evas_obj,Evas_Object_Event_Cb resize_func)4557 _ephysics_body_face_evas_object_add(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Evas_Object_Event_Cb resize_func)
4558 {
4559 EPhysics_Body_Face_Obj *face_obj;
4560 Eina_List *l;
4561 void *ldata;
4562
4563 EINA_LIST_FOREACH(body->face_objs, l, ldata)
4564 {
4565 face_obj = (EPhysics_Body_Face_Obj *)ldata;
4566 if (face_obj->face == face)
4567 {
4568 _ephysics_body_face_obj_unset(face_obj->obj, resize_func);
4569 face_obj->obj = evas_obj;
4570 return;
4571 }
4572 }
4573
4574 face_obj = (EPhysics_Body_Face_Obj *)calloc(1,
4575 sizeof(EPhysics_Body_Face_Obj));
4576 if (!face_obj)
4577 {
4578 ERR("Failed to create face object");
4579 return;
4580 }
4581
4582 face_obj->face = face;
4583 face_obj->obj = evas_obj;
4584 body->face_objs = eina_list_append(body->face_objs, face_obj);
4585 }
4586
4587 static void
_ephysics_body_box_face_obj_resize_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)4588 _ephysics_body_box_face_obj_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
4589 {
4590 EPhysics_Body_Face face = EPHYSICS_BODY_FACE_LAST;
4591 EPhysics_Body *body = (EPhysics_Body *) data;
4592 EPhysics_Body_Face_Obj *face_obj;
4593 int w, h, bw, bh, bd;
4594 Eina_List *l;
4595 void *ldata;
4596
4597 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
4598 EINA_LIST_FOREACH(body->face_objs, l, ldata)
4599 {
4600 face_obj = (EPhysics_Body_Face_Obj *)ldata;
4601 if (face_obj->obj == obj)
4602 {
4603 face = face_obj->face;
4604 break;
4605 }
4606 }
4607
4608 switch(face)
4609 {
4610 case EPHYSICS_BODY_BOX_FACE_FRONT:
4611 case EPHYSICS_BODY_BOX_FACE_BACK:
4612 case EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT:
4613 case EPHYSICS_BODY_BOX_FACE_MIDDLE_BACK:
4614 if ((w == body->size.w) && (h == body->size.h))
4615 return;
4616 bw = w;
4617 bh = h;
4618 bd = body->size.d;
4619 break;
4620 case EPHYSICS_BODY_BOX_FACE_RIGHT:
4621 case EPHYSICS_BODY_BOX_FACE_LEFT:
4622 if ((w == body->size.d) && (h == body->size.h))
4623 return;
4624 bw = body->size.w;
4625 bh = h;
4626 bd = w;
4627 break;
4628 case EPHYSICS_BODY_BOX_FACE_TOP:
4629 case EPHYSICS_BODY_BOX_FACE_BOTTOM:
4630 if ((w == body->size.w) && (h == body->size.d))
4631 return;
4632 bw = w;
4633 bh = body->size.h;
4634 bd = h;
4635 default:
4636 return;
4637 }
4638
4639 DBG("Resizing body %p to w=%i, h=%i, d=%i", body, bw, bh, bd);
4640 ephysics_world_lock_take(body->world);
4641 _ephysics_body_resize(body, bw, bh, bd);
4642 ephysics_world_lock_release(body->world);
4643 }
4644
4645 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)4646 _ephysics_body_box_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
4647 {
4648 int obj_x, obj_y, obj_w, obj_h, bx, by, bz, bw, bh, bd;
4649 double rate;
4650
4651 if ((face < EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT) ||
4652 (face > EPHYSICS_BODY_BOX_FACE_BOTTOM))
4653 {
4654 ERR("Can't set evas object to body, face is invalid.");
4655 return;
4656 }
4657
4658 if (body->soft_body)
4659 {
4660 ERR("Not implemented for soft bodies yet.");
4661 return;
4662 }
4663
4664 _ephysics_body_face_evas_object_add(body, face, evas_obj,
4665 _ephysics_body_box_face_obj_resize_cb);
4666 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
4667 _ephysics_body_face_obj_del_cb, body);
4668
4669 if (!use_obj_pos)
4670 return;
4671
4672 rate = ephysics_world_rate_get(body->world);
4673 evas_object_geometry_get(evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
4674 ephysics_body_geometry_get(body, &bx, &by, &bz, &bw, &bh, &bd);
4675
4676 ephysics_world_lock_take(body->world);
4677
4678 switch(face)
4679 {
4680 case EPHYSICS_BODY_BOX_FACE_FRONT:
4681 case EPHYSICS_BODY_BOX_FACE_BACK:
4682 case EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT:
4683 case EPHYSICS_BODY_BOX_FACE_MIDDLE_BACK:
4684 _ephysics_body_geometry_set(body, obj_x, obj_y, bz,
4685 obj_w, obj_h, bd, rate);
4686 break;
4687 case EPHYSICS_BODY_BOX_FACE_RIGHT:
4688 case EPHYSICS_BODY_BOX_FACE_LEFT:
4689 _ephysics_body_geometry_set(body, bx, by, bz,
4690 bw, obj_h, obj_w, rate);
4691 break;
4692 case EPHYSICS_BODY_BOX_FACE_TOP:
4693 case EPHYSICS_BODY_BOX_FACE_BOTTOM:
4694 _ephysics_body_geometry_set(body, bx, by, bz,
4695 obj_w, bh, obj_h, rate);
4696 break;
4697 default:
4698 break;
4699 }
4700
4701 ephysics_world_lock_release(body->world);
4702 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESIZE,
4703 _ephysics_body_box_face_obj_resize_cb,
4704 body);
4705 }
4706
4707 static Evas_Object *
_ephysics_body_box_face_evas_object_get(const EPhysics_Body * body,EPhysics_Body_Face face)4708 _ephysics_body_box_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
4709 {
4710 EPhysics_Body_Face_Obj *face_obj;
4711 Eina_List *l;
4712 void *ldata;
4713
4714 if ((face < EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT) ||
4715 (face > EPHYSICS_BODY_BOX_FACE_BOTTOM))
4716 {
4717 ERR("Can't get evas object from body, face is invalid.");
4718 return NULL;
4719 }
4720
4721 EINA_LIST_FOREACH(body->face_objs, l, ldata)
4722 {
4723 face_obj = (EPhysics_Body_Face_Obj *)ldata;
4724 if (face_obj->face == face)
4725 return face_obj->obj;
4726 }
4727
4728 ERR("Couldn't find an object associated to face %i.", face);
4729 return NULL;
4730 }
4731
4732 static Evas_Object *
_ephysics_body_box_face_evas_object_unset(EPhysics_Body * body,EPhysics_Body_Face face)4733 _ephysics_body_box_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
4734 {
4735 EPhysics_Body_Face_Obj *face_obj;
4736 Eina_List *l;
4737 void *ldata;
4738
4739 if ((face < EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT) ||
4740 (face > EPHYSICS_BODY_BOX_FACE_BOTTOM))
4741 {
4742 ERR("Can't unset evas object from body, face is invalid.");
4743 return NULL;
4744 }
4745
4746 EINA_LIST_FOREACH(body->face_objs, l, ldata)
4747 {
4748 face_obj = (EPhysics_Body_Face_Obj *)ldata;
4749 if (face_obj->face == face)
4750 {
4751 Evas_Object *obj = face_obj->obj;
4752 _ephysics_body_face_obj_unset(
4753 obj, _ephysics_body_box_face_obj_resize_cb);
4754 body->face_objs = eina_list_remove(body->face_objs, face_obj);
4755 free(face_obj);
4756 return obj;
4757 }
4758 }
4759
4760 ERR("Couldn't find an object associated to face %i.", face);
4761 return NULL;
4762 }
4763
4764 static void
_ephysics_body_cylinder_face_obj_resize_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)4765 _ephysics_body_cylinder_face_obj_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
4766 {
4767 EPhysics_Body_Face face = EPHYSICS_BODY_FACE_LAST;
4768 EPhysics_Body *body = (EPhysics_Body *) data;
4769 EPhysics_Body_Face_Obj *face_obj;
4770 int w, h, bw, bh, bd;
4771 Eina_List *l;
4772 void *ldata;
4773
4774 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
4775 EINA_LIST_FOREACH(body->face_objs, l, ldata)
4776 {
4777 face_obj = (EPhysics_Body_Face_Obj *)ldata;
4778 if (face_obj->obj == obj)
4779 {
4780 face = face_obj->face;
4781 break;
4782 }
4783 }
4784
4785 switch(face)
4786 {
4787 case EPHYSICS_BODY_CYLINDER_FACE_FRONT:
4788 case EPHYSICS_BODY_CYLINDER_FACE_BACK:
4789 case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT:
4790 case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_BACK:
4791 if ((w == body->size.w) && (h == body->size.h))
4792 return;
4793 bw = w;
4794 bh = h;
4795 bd = body->size.d;
4796 break;
4797 case EPHYSICS_BODY_CYLINDER_FACE_CURVED:
4798 if (h == body->size.d)
4799 return;
4800 bw = body->size.w;
4801 bh = body->size.h;
4802 bd = h;
4803 default:
4804 return;
4805 }
4806
4807 DBG("Resizing body %p to w=%i, h=%i, d=%i", body, bw, bh, bd);
4808 ephysics_world_lock_take(body->world);
4809 _ephysics_body_resize(body, bw, bh, bd);
4810 ephysics_world_lock_release(body->world);
4811 }
4812
4813 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)4814 _ephysics_body_cylinder_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
4815 {
4816 int obj_x, obj_y, obj_w, obj_h, bx, by, bz, bw, bh, bd;
4817 double rate;
4818
4819 if ((face < EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT) ||
4820 (face > EPHYSICS_BODY_CYLINDER_FACE_CURVED))
4821 {
4822 ERR("Can't set evas object to body, face is invalid.");
4823 return;
4824 }
4825
4826 if (body->soft_body)
4827 {
4828 ERR("Not implemented for soft bodies yet.");
4829 return;
4830 }
4831
4832 _ephysics_body_face_evas_object_add(
4833 body, face, evas_obj, _ephysics_body_cylinder_face_obj_resize_cb);
4834 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
4835 _ephysics_body_face_obj_del_cb, body);
4836
4837 if (!use_obj_pos)
4838 return;
4839
4840 rate = ephysics_world_rate_get(body->world);
4841 evas_object_geometry_get(evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
4842 ephysics_body_geometry_get(body, &bx, &by, &bz, &bw, &bh, &bd);
4843
4844 ephysics_world_lock_take(body->world);
4845
4846 switch(face)
4847 {
4848 case EPHYSICS_BODY_CYLINDER_FACE_FRONT:
4849 case EPHYSICS_BODY_CYLINDER_FACE_BACK:
4850 case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT:
4851 case EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_BACK:
4852 _ephysics_body_geometry_set(body, obj_x, obj_y, bz,
4853 obj_w, obj_h, bd, rate);
4854 break;
4855 case EPHYSICS_BODY_CYLINDER_FACE_CURVED:
4856 _ephysics_body_geometry_set(body, bx, by, bz,
4857 bw, bh, obj_h, rate);
4858 default:
4859 break;
4860 }
4861
4862 ephysics_world_lock_release(body->world);
4863 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESIZE,
4864 _ephysics_body_cylinder_face_obj_resize_cb,
4865 body);
4866 }
4867
4868 static Evas_Object *
_ephysics_body_cylinder_face_evas_object_get(const EPhysics_Body * body,EPhysics_Body_Face face)4869 _ephysics_body_cylinder_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
4870 {
4871 EPhysics_Body_Face_Obj *face_obj;
4872 Eina_List *l;
4873 void *ldata;
4874
4875 if ((face < EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT) ||
4876 (face > EPHYSICS_BODY_CYLINDER_FACE_CURVED))
4877 {
4878 ERR("Can't get evas object from body, face is invalid.");
4879 return NULL;
4880 }
4881
4882 EINA_LIST_FOREACH(body->face_objs, l, ldata)
4883 {
4884 face_obj = (EPhysics_Body_Face_Obj *)ldata;
4885 if (face_obj->face == face)
4886 return face_obj->obj;
4887 }
4888
4889 ERR("Couldn't find an object associated to face %i.", face);
4890 return NULL;
4891 }
4892
4893 static Evas_Object *
_ephysics_body_cylinder_face_evas_object_unset(EPhysics_Body * body,EPhysics_Body_Face face)4894 _ephysics_body_cylinder_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
4895 {
4896 EPhysics_Body_Face_Obj *face_obj;
4897 Eina_List *l;
4898 void *ldata;
4899
4900 if ((face < EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT) ||
4901 (face > EPHYSICS_BODY_CYLINDER_FACE_CURVED))
4902 {
4903 ERR("Can't unset evas object from body, face is invalid.");
4904 return NULL;
4905 }
4906
4907 EINA_LIST_FOREACH(body->face_objs, l, ldata)
4908 {
4909 face_obj = (EPhysics_Body_Face_Obj *)ldata;
4910 if (face_obj->face == face)
4911 {
4912 Evas_Object *obj = face_obj->obj;
4913 _ephysics_body_face_obj_unset(
4914 obj, _ephysics_body_cylinder_face_obj_resize_cb);
4915 body->face_objs = eina_list_remove(body->face_objs, face_obj);
4916 free(face_obj);
4917 return obj;
4918 }
4919 }
4920
4921 ERR("Couldn't find an object associated to face %i.", face);
4922 return NULL;
4923 }
4924
4925 static void
_ephysics_body_soft_body_face_resize_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)4926 _ephysics_body_soft_body_face_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
4927 {
4928 int w, h;
4929 EPhysics_Body_Face_Obj *face;
4930 EPhysics_Body_Face_Slice *face_slice = (EPhysics_Body_Face_Slice *)data;
4931 EPhysics_Body *body = face_slice->body;
4932
4933 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
4934 if ((w == body->size.w) && (h == body->size.h))
4935 return;
4936
4937 DBG("Resizing body %p to w=%i, h=%i, d=%i", body, w, h, body->size.d);
4938
4939 face = _ephysics_body_face_evas_object_get(body, face_slice->face);
4940
4941 ephysics_world_lock_take(body->world);
4942 _ephysics_body_resize(body, w, h, body->size.d);
4943
4944 if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
4945 {
4946 _ephysics_body_soft_body_slices_clean(face_slice->slices);
4947 _ephysics_body_soft_body_slices_init(body, face->obj,
4948 face_slice->slices);
4949 }
4950
4951 ephysics_world_lock_release(body->world);
4952 }
4953
4954 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)4955 _ephysics_body_cloth_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
4956 {
4957 EPhysics_Body_Face_Slice *face_slice;
4958 int obj_x, obj_y, obj_w, obj_h, bz, bd;
4959 double rate;
4960
4961 if ((face < EPHYSICS_BODY_CLOTH_FACE_FRONT) ||
4962 (face > EPHYSICS_BODY_CLOTH_FACE_BACK))
4963 {
4964 ERR("Can't set evas object to body, face is invalid.");
4965 return;
4966 }
4967
4968 _ephysics_body_face_evas_object_add(body, face, evas_obj,
4969 _ephysics_body_soft_body_face_resize_cb);
4970 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
4971 _ephysics_body_face_obj_del_cb, body);
4972
4973 if (!use_obj_pos)
4974 return;
4975
4976 face_slice = _ephysics_body_face_slice_get(body, face);
4977
4978 rate = ephysics_world_rate_get(body->world);
4979 evas_object_geometry_get(evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
4980
4981 ephysics_world_lock_take(body->world);
4982 ephysics_body_geometry_get(body, NULL, NULL, &bz, NULL, NULL, &bd);
4983 _ephysics_body_geometry_set(body, obj_x, obj_y, bz, obj_w, obj_h, bd, rate);
4984 ephysics_world_lock_release(body->world);
4985 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESIZE,
4986 _ephysics_body_soft_body_face_resize_cb,
4987 face_slice);
4988 }
4989
4990 static Evas_Object *
_ephysics_body_cloth_face_evas_object_get(const EPhysics_Body * body,EPhysics_Body_Face face)4991 _ephysics_body_cloth_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
4992 {
4993 EPhysics_Body_Face_Obj *face_obj;
4994 Eina_List *l;
4995 void *ldata;
4996
4997 if ((face < EPHYSICS_BODY_CLOTH_FACE_FRONT) ||
4998 (face > EPHYSICS_BODY_CLOTH_FACE_BACK))
4999 {
5000 ERR("Can't get evas object from body, face is invalid.");
5001 return NULL;
5002 }
5003
5004 EINA_LIST_FOREACH(body->face_objs, l, ldata)
5005 {
5006 face_obj = (EPhysics_Body_Face_Obj *)ldata;
5007 if (face_obj->face == face)
5008 return face_obj->obj;
5009 }
5010
5011 ERR("Couldn't find an object associated to face %i.", face);
5012 return NULL;
5013 }
5014
5015 static Evas_Object *
_ephysics_body_cloth_face_evas_object_unset(EPhysics_Body * body,EPhysics_Body_Face face)5016 _ephysics_body_cloth_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
5017 {
5018 EPhysics_Body_Face_Obj *face_obj;
5019 Eina_List *l;
5020 void *ldata;
5021
5022 if ((face < EPHYSICS_BODY_CLOTH_FACE_FRONT) ||
5023 (face > EPHYSICS_BODY_CLOTH_FACE_BACK))
5024 {
5025 ERR("Can't unset evas object from body, face is invalid.");
5026 return NULL;
5027 }
5028
5029 EINA_LIST_FOREACH(body->face_objs, l, ldata)
5030 {
5031 face_obj = (EPhysics_Body_Face_Obj *)ldata;
5032 if (face_obj->face == face)
5033 {
5034 Evas_Object *obj = face_obj->obj;
5035 _ephysics_body_face_obj_unset(
5036 obj, _ephysics_body_soft_body_face_resize_cb);
5037 body->face_objs = eina_list_remove(body->face_objs, face_obj);
5038 free(face_obj);
5039 return obj;
5040 }
5041 }
5042
5043 ERR("Couldn't find an object associated to face %i.", face);
5044 return NULL;
5045 }
5046
5047 static void
_ephysics_body_soft_sphere_face_obj_resize_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)5048 _ephysics_body_soft_sphere_face_obj_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5049 {
5050 EPhysics_Body *body = (EPhysics_Body *) data;
5051 Evas_Coord bd, w, h;
5052
5053 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
5054 ephysics_body_geometry_get(body, NULL, NULL, NULL, NULL, NULL, &bd);
5055 ephysics_world_lock_take(body->world);
5056 ephysics_body_resize(body, w, h, bd);
5057 ephysics_world_lock_release(body->world);
5058 }
5059
5060 static void
_ephysics_body_soft_sphere_face_evas_object_del_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)5061 _ephysics_body_soft_sphere_face_evas_object_del_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
5062 {
5063 Eina_List *l;
5064 void *ldata;
5065 EPhysics_Body_Face_Obj *face_obj = NULL;
5066 EPhysics_Body_Face_Slice *face_slice = (EPhysics_Body_Face_Slice *)data;
5067 EPhysics_Body *body = face_slice->body;
5068
5069 EINA_LIST_FOREACH(body->face_objs, l, ldata)
5070 {
5071 if (((EPhysics_Body_Face_Obj *)ldata)->face == face_slice->face)
5072 {
5073 face_obj = (EPhysics_Body_Face_Obj *)ldata;
5074 break;
5075 }
5076 }
5077 if (!face_obj) return;
5078
5079 _ephysics_body_face_evas_object_del(body, face_obj,
5080 _ephysics_body_soft_sphere_face_obj_resize_cb);
5081 _ephysics_body_soft_body_slices_clean(face_slice->slices);
5082
5083 DBG("Soft sphere's face cleaned up.");
5084 }
5085
5086 static void
_ephysics_body_soft_sphere_face_evas_object_clean(EPhysics_Body * body,EPhysics_Body_Face_Obj * face_obj,Eina_List * slices)5087 _ephysics_body_soft_sphere_face_evas_object_clean(EPhysics_Body *body, EPhysics_Body_Face_Obj *face_obj, Eina_List *slices)
5088 {
5089 evas_object_map_enable_set(face_obj->obj, EINA_FALSE);
5090 evas_object_event_callback_del(face_obj->obj, EVAS_CALLBACK_DEL,
5091 _ephysics_body_soft_sphere_face_evas_object_del_cb);
5092
5093 evas_object_event_callback_del(face_obj->obj, EVAS_CALLBACK_RESTACK,
5094 _ephysics_body_soft_body_evas_restack_cb);
5095 _ephysics_body_soft_body_slices_clean(slices);
5096
5097 _ephysics_body_face_evas_object_del(body, face_obj,
5098 _ephysics_body_soft_sphere_face_obj_resize_cb);
5099 }
5100
5101 static void
_ephysics_body_soft_sphere_face_evas_object_set(EPhysics_Body * body,EPhysics_Body_Face face,Evas_Object * evas_obj,Eina_Bool use_obj_pos)5102 _ephysics_body_soft_sphere_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
5103 {
5104 int obj_x, obj_y, obj_w, obj_h, bz, bd;
5105 double rate;
5106 EPhysics_Body_Face_Slice *face_slice = NULL;
5107 EPhysics_Body_Face_Obj *face_obj;
5108
5109 if ((face < EPHYSICS_BODY_SPHERE_FACE_FRONT) ||
5110 (face > EPHYSICS_BODY_SPHERE_FACE_BACK))
5111 {
5112 ERR("Can't set evas object to body, face is invalid.");
5113 return;
5114 }
5115
5116 if (!body)
5117 {
5118 ERR("Can't set evas object to body, the last wasn't provided.");
5119 return;
5120 }
5121
5122 if (!evas_obj)
5123 {
5124 ERR("Can't set evas object to body, the first wasn't provided.");
5125 return;
5126 }
5127
5128 face_slice = _ephysics_body_face_slice_get(body, face);
5129 if (!face_slice)
5130 {
5131 ERR("Could not find pre initialized face slice for the wanted face.");
5132 return;
5133 }
5134
5135 face_obj = _ephysics_body_face_evas_object_get(body, face);
5136
5137 if (face_obj)
5138 _ephysics_body_soft_sphere_face_evas_object_clean(body, face_obj,
5139 face_slice->slices);
5140
5141 evas_object_geometry_get(evas_obj, NULL, NULL, &obj_w, &obj_h);
5142 if (!obj_w && !obj_h) evas_object_resize(evas_obj, 1, 1);
5143
5144 _ephysics_body_face_evas_object_add(body, face, evas_obj,
5145 _ephysics_body_soft_sphere_face_obj_resize_cb);
5146
5147 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
5148 _ephysics_body_soft_sphere_face_evas_object_del_cb, face_slice);
5149
5150 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESTACK,
5151 _ephysics_body_soft_body_evas_restack_cb,
5152 body);
5153
5154 _ephysics_body_soft_body_slices_init(body, evas_obj, face_slice->slices);
5155
5156 if (!use_obj_pos)
5157 return;
5158
5159 rate = ephysics_world_rate_get(body->world);
5160 evas_object_geometry_get(evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
5161 ephysics_body_geometry_get(body, NULL, NULL, &bz, NULL, NULL, &bd);
5162
5163 ephysics_world_lock_take(body->world);
5164 _ephysics_body_geometry_set(body, obj_x, obj_y, bz, obj_w, obj_h, bd, rate);
5165 ephysics_world_lock_release(body->world);
5166 evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESIZE,
5167 _ephysics_body_efl_canvas_object_resize_cb, body);
5168
5169 DBG("Soft sphere's face evas object set.");
5170 }
5171
5172 static Evas_Object *
_ephysics_body_soft_sphere_face_evas_object_get(const EPhysics_Body * body,EPhysics_Body_Face face)5173 _ephysics_body_soft_sphere_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
5174 {
5175 EPhysics_Body_Face_Obj *face_obj = NULL;
5176
5177 if ((face < EPHYSICS_BODY_SPHERE_FACE_FRONT) ||
5178 (face > EPHYSICS_BODY_SPHERE_FACE_BACK))
5179 {
5180 ERR("Can't get evas object from body, face is invalid.");
5181 return NULL;
5182 }
5183
5184 face_obj = _ephysics_body_face_evas_object_get((EPhysics_Body *)body, face);
5185 if (face_obj) return face_obj->obj;
5186
5187 ERR("Couldn't find an object associated to face %i.", face);
5188 return NULL;
5189 }
5190
5191 static Evas_Object *
_ephysics_body_soft_sphere_face_evas_object_unset(EPhysics_Body * body,EPhysics_Body_Face face)5192 _ephysics_body_soft_sphere_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
5193 {
5194 EPhysics_Body_Face_Slice *face_slice;
5195 EPhysics_Body_Face_Obj *face_obj = NULL;
5196 Evas_Object *obj;
5197
5198 if ((face < EPHYSICS_BODY_SPHERE_FACE_FRONT) ||
5199 (face > EPHYSICS_BODY_SPHERE_FACE_BACK))
5200 {
5201 ERR("Can't unset evas object from body, face is invalid.");
5202 return NULL;
5203 }
5204
5205 face_obj = _ephysics_body_face_evas_object_get(body, face);
5206
5207 if (!face_obj) return NULL;
5208
5209 obj = face_obj->obj;
5210 face_slice = _ephysics_body_face_slice_get(body, face);
5211 _ephysics_body_soft_sphere_face_evas_object_clean(body, face_obj,
5212 face_slice->slices);
5213
5214 DBG("EPhysics Body face unset.");
5215 return obj;
5216 }
5217
5218 EAPI void
ephysics_body_face_evas_object_set(EPhysics_Body * body,EPhysics_Body_Face face,Evas_Object * evas_obj,Eina_Bool use_obj_pos)5219 ephysics_body_face_evas_object_set(EPhysics_Body *body, EPhysics_Body_Face face, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
5220 {
5221 if (!body)
5222 {
5223 ERR("Can't set evas object to body, the last wasn't provided.");
5224 return;
5225 }
5226
5227 if (!evas_obj)
5228 {
5229 ERR("Can't set evas object to body, the first wasn't provided.");
5230 return;
5231 }
5232
5233 if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
5234 return _ephysics_body_cloth_face_evas_object_set(body, face, evas_obj,
5235 use_obj_pos);
5236 if (body->type == EPHYSICS_BODY_TYPE_RIGID &&
5237 body->shape == EPHYSICS_BODY_SHAPE_CYLINDER)
5238 return _ephysics_body_cylinder_face_evas_object_set(body, face, evas_obj,
5239 use_obj_pos);
5240 if (body->type == EPHYSICS_BODY_TYPE_RIGID &&
5241 body->shape == EPHYSICS_BODY_SHAPE_BOX)
5242 return _ephysics_body_box_face_evas_object_set(body, face, evas_obj,
5243 use_obj_pos);
5244 if (body->type == EPHYSICS_BODY_TYPE_SOFT &&
5245 body->shape == EPHYSICS_BODY_SHAPE_SPHERE)
5246 return _ephysics_body_soft_sphere_face_evas_object_set(body, face, evas_obj,
5247 use_obj_pos);
5248
5249 ERR("Can't handle body %p type.", body);
5250 }
5251
5252 EAPI Evas_Object *
ephysics_body_face_evas_object_get(const EPhysics_Body * body,EPhysics_Body_Face face)5253 ephysics_body_face_evas_object_get(const EPhysics_Body *body, EPhysics_Body_Face face)
5254 {
5255 if (!body)
5256 {
5257 ERR("Can't get evas object from body, it wasn't provided.");
5258 return NULL;
5259 }
5260
5261 if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
5262 return _ephysics_body_cloth_face_evas_object_get(body, face);
5263 if (body->type == EPHYSICS_BODY_TYPE_RIGID &&
5264 body->shape == EPHYSICS_BODY_SHAPE_CYLINDER)
5265 return _ephysics_body_cylinder_face_evas_object_get(body, face);
5266 if (body->type == EPHYSICS_BODY_TYPE_RIGID &&
5267 body->shape == EPHYSICS_BODY_SHAPE_BOX)
5268 return _ephysics_body_box_face_evas_object_get(body, face);
5269 if (body->type == EPHYSICS_BODY_TYPE_SOFT &&
5270 body->shape == EPHYSICS_BODY_SHAPE_SPHERE)
5271 return _ephysics_body_soft_sphere_face_evas_object_get(body, face);
5272
5273 ERR("Can't handle body %p type.", body);
5274 return NULL;
5275 }
5276
5277 EAPI Evas_Object *
ephysics_body_face_evas_object_unset(EPhysics_Body * body,EPhysics_Body_Face face)5278 ephysics_body_face_evas_object_unset(EPhysics_Body *body, EPhysics_Body_Face face)
5279 {
5280 if (!body)
5281 {
5282 ERR("Can't unset evas object from body, it wasn't provided.");
5283 return NULL;
5284 }
5285
5286 if (body->type == EPHYSICS_BODY_TYPE_CLOTH)
5287 return _ephysics_body_cloth_face_evas_object_unset(body, face);
5288 if (body->type == EPHYSICS_BODY_TYPE_RIGID &&
5289 body->shape == EPHYSICS_BODY_SHAPE_CYLINDER)
5290 return _ephysics_body_cylinder_face_evas_object_unset(body, face);
5291 if (body->type == EPHYSICS_BODY_TYPE_RIGID &&
5292 body->shape == EPHYSICS_BODY_SHAPE_BOX)
5293 return _ephysics_body_box_face_evas_object_unset(body, face);
5294 if (body->type == EPHYSICS_BODY_TYPE_SOFT &&
5295 body->shape == EPHYSICS_BODY_SHAPE_SPHERE)
5296 return _ephysics_body_soft_sphere_face_evas_object_unset(body, face);
5297
5298 ERR("Can't handle body %p type.", body);
5299 return NULL;
5300 }
5301
5302 #ifdef __cplusplus
5303 }
5304 #endif
5305