1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <math.h>
5 
6 #include <btBulletCollisionCommon.h>
7 #include <btBulletDynamicsCommon.h>
8 #include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
9 #include <BulletCollision/CollisionShapes/btCollisionShape.h>
10 #include <BulletDynamics/ConstraintSolver/btTypedConstraint.h>
11 #include <BulletCollision/CollisionDispatch/btGhostObject.h>
12 #include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h>
13 #include <BulletCollision/NarrowPhaseCollision/btRaycastCallback.h>
14 
15 #include "../core/gl_util.h"
16 #include "../core/gl_font.h"
17 #include "../core/gl_text.h"
18 #include "../core/console.h"
19 #include "../core/vmath.h"
20 #include "../core/obb.h"
21 #include "../render/render.h"
22 #include "../script/script.h"
23 #include "../engine.h"
24 #include "../mesh.h"
25 #include "../skeletal_model.h"
26 #include "../character_controller.h"
27 #include "../entity.h"
28 #include "../resource.h"
29 #include "../room.h"
30 #include "../world.h"
31 #include "physics.h"
32 #include "ragdoll.h"
33 #include "hair.h"
34 
35 
36 /*
37  * INTERNAL BHYSICS CLASSES
38  */
39 class bt_engine_ClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
40 {
41 public:
bt_engine_ClosestRayResultCallback(engine_container_p cont,float from[3],float to[3],int16_t filter)42     bt_engine_ClosestRayResultCallback(engine_container_p cont, float from[3], float to[3], int16_t filter) :
43         btCollisionWorld::ClosestRayResultCallback(btVector3(from[0], from[1], from[2]), btVector3(to[0], to[1], to[2])),
44         m_cont(cont),
45         m_filter(filter)
46     {
47         m_collisionFilterGroup = btBroadphaseProxy::SensorTrigger;
48         m_collisionFilterMask = (filter & (COLLISION_GROUP_STATIC_OBLECT | COLLISION_GROUP_STATIC_ROOM)) ? (btBroadphaseProxy::StaticFilter) : 0x0000;
49         m_collisionFilterMask |= (filter & COLLISION_GROUP_KINEMATIC) ? (btBroadphaseProxy::KinematicFilter) : 0x0000;
50         m_collisionFilterMask |= (filter & (COLLISION_GROUP_CHARACTERS | COLLISION_GROUP_VEHICLE)) ? (btBroadphaseProxy::CharacterFilter) : 0x0000;
51         m_collisionFilterMask |= (filter & COLLISION_GROUP_DYNAMICS) ? (btBroadphaseProxy::DefaultFilter) : 0x0000;
52     }
53 
addSingleResult(btCollisionWorld::LocalRayResult & rayResult,bool normalInWorldSpace)54     virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) override
55     {
56         room_p r0 = NULL, r1 = NULL;
57         engine_container_p c1;
58 
59         r0 = (m_cont) ? (m_cont->room) : (NULL);
60         c1 = (engine_container_p)rayResult.m_collisionObject->getUserPointer();
61         r1 = (c1) ? (c1->room) : (NULL);
62 
63         if(c1 && (((c1->collision_group & m_filter) == 0x0000) || (c1 == m_cont)))
64         {
65             return 1.0f;
66         }
67 
68         if(!r0 || !r1)
69         {
70             return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
71         }
72 
73         if(r0 && r1)
74         {
75             if(Room_IsInOverlappedRoomsList(r0, r1))
76             {
77                 return 1.0f;
78             }
79             if(Room_IsInNearRoomsList(r0, r1))
80             {
81                 if(m_cont->collision_heavy && (r0 != r1) && (!m_cont->sector || ((m_cont->sector->room_above != r1) && (m_cont->sector->room_below != r1))))
82                 {
83                     btVector3 pt = this->m_rayFromWorld.lerp(this->m_rayToWorld, rayResult.m_hitFraction);
84                     room_sector_p ps0 = Room_GetSectorRaw(r1, m_cont->sector->pos);
85                     room_sector_p ps1 = Room_GetSectorRaw(r0, pt.m_floats);
86                     if((!ps0 || !ps1 || (ps0->portal_to_room != r0) || (ps1->portal_to_room != r1)) &&
87                        (!ps0 || ((ps0->room_above != r0) && (ps0->room_below != r0))) &&
88                        (!ps1 || ((ps1->room_above != r0) && (ps1->room_below != r0))))
89                     {
90                         return 1.0f;
91                     }
92                 }
93                 return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
94             }
95         }
96 
97         return 1.0f;
98     }
99 
100     engine_container_p m_cont;
101     int16_t            m_filter;
102 };
103 
104 
105 class bt_engine_ClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
106 {
107 public:
bt_engine_ClosestConvexResultCallback(engine_container_p cont,float from[3],float to[3],int16_t filter)108     bt_engine_ClosestConvexResultCallback(engine_container_p cont, float from[3], float to[3], int16_t filter) :
109         btCollisionWorld::ClosestConvexResultCallback(btVector3(from[0], from[1], from[2]), btVector3(to[0], to[1], to[2])),
110         m_cont(cont),
111         m_filter(filter)
112     {
113         m_collisionFilterGroup = btBroadphaseProxy::SensorTrigger;
114         m_collisionFilterMask = (filter & (COLLISION_GROUP_STATIC_OBLECT | COLLISION_GROUP_STATIC_ROOM)) ? (btBroadphaseProxy::StaticFilter) : 0x0000;
115         m_collisionFilterMask |= (filter & COLLISION_GROUP_KINEMATIC) ? (btBroadphaseProxy::KinematicFilter) : 0x0000;
116         m_collisionFilterMask |= (filter & (COLLISION_GROUP_CHARACTERS | COLLISION_GROUP_VEHICLE)) ? (btBroadphaseProxy::CharacterFilter) : 0x0000;
117         m_collisionFilterMask |= (filter & COLLISION_GROUP_DYNAMICS) ? (btBroadphaseProxy::DefaultFilter) : 0x0000;
118     }
119 
addSingleResult(btCollisionWorld::LocalConvexResult & convexResult,bool normalInWorldSpace)120     virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace)
121     {
122         room_p r0 = NULL, r1 = NULL;
123         engine_container_p c1;
124 
125         r0 = (m_cont)?(m_cont->room):(NULL);
126         c1 = (engine_container_p)convexResult.m_hitCollisionObject->getUserPointer();
127         r1 = (c1) ? (c1->room) : (NULL);
128 
129         if(c1 && (((c1->collision_group & m_filter) == 0x0000) || (c1 == m_cont)))
130         {
131             return 1.0f;
132         }
133 
134         if(!r0 || !r1)
135         {
136             return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
137         }
138 
139         if(r0 && r1)
140         {
141             if(Room_IsInOverlappedRoomsList(r0, r1))
142             {
143                 return 1.0f;
144             }
145             if(Room_IsInNearRoomsList(r0, r1))
146             {
147                 if(m_cont->collision_heavy && (r0 != r1) && (!m_cont->sector || ((m_cont->sector->room_above != r1) && (m_cont->sector->room_below != r1))))
148                 {
149                     room_sector_p ps0 = Room_GetSectorRaw(r1, m_cont->sector->pos);
150                     room_sector_p ps1 = Room_GetSectorRaw(r0, convexResult.m_hitPointLocal.m_floats);
151                     if((!ps0 || !ps1 || (ps0->portal_to_room != r0) || (ps1->portal_to_room != r1)) &&
152                        (!ps0 || ((ps0->room_above != r0) && (ps0->room_below != r0))) &&
153                        (!ps1 || ((ps1->room_above != r0) && (ps1->room_below != r0))))
154                     {
155                         return 1.0f;
156                     }
157                 }
158                 return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
159             }
160         }
161 
162         return 1.0f;
163     }
164 
165 private:
166     engine_container_p m_cont;
167     int16_t            m_filter;
168 };
169 
170 
171 struct bt_engine_OverlapFilterCallback : public btOverlapFilterCallback
172 {
173     // return true when pairs need collision
needBroadphaseCollisionbt_engine_OverlapFilterCallback174     virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
175     {
176         bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) &&
177                         (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
178 
179         if(collides)
180         {
181             btCollisionObject *obj0 = (btCollisionObject*)proxy0->m_clientObject;
182             btCollisionObject *obj1 = (btCollisionObject*)proxy1->m_clientObject;
183             engine_container_p c0 = (engine_container_p)obj0->getUserPointer();
184             engine_container_p c1 = (engine_container_p)obj1->getUserPointer();;
185             room_p r0 = (c0) ? (c0->room) : (NULL);
186             room_p r1 = (c1) ? (c1->room) : (NULL);
187 
188             int num_ghosts = (proxy0->m_collisionFilterGroup == btBroadphaseProxy::SensorTrigger) +
189                              (proxy1->m_collisionFilterGroup == btBroadphaseProxy::SensorTrigger);
190 
191             if(num_ghosts == 2)
192             {
193                 return false;
194             }
195 
196             if(c1 && c1 == c0)                                                  // No self interaction
197             {
198                 return false;
199             }
200 
201             if((c0 && c0->collision_group == COLLISION_GROUP_TRIGGERS && !obj1->isStaticOrKinematicObject()) ||
202                (c1 && c1->collision_group == COLLISION_GROUP_TRIGGERS && !obj0->isStaticOrKinematicObject()))
203             {
204                 return false;
205             }
206 
207             collides = ((!r0 && !r1) || (Room_IsInNearRoomsList(r0, r1) && !Room_IsInOverlappedRoomsList(r0, r1) &&
208                         (num_ghosts || ((c0->collision_group & c1->collision_mask) && (c1->collision_group & c0->collision_mask)))));
209 
210             if(collides && (r0 != r1) && c0 && c1 && (r0->content->overlapped_room_list || r1->content->overlapped_room_list || c0->collision_heavy || c1->collision_heavy))
211             {
212                 if(c0->sector && c1->sector)
213                 {
214                     room_sector_p ps0 = Room_GetSectorRaw(r1, c0->sector->pos);
215                     room_sector_p ps1 = Room_GetSectorRaw(r0, c1->sector->pos);
216                     collides = (ps0 && ps1 && (ps0->portal_to_room == r0) && (ps1->portal_to_room == r1)) ||
217                                (ps0 && ((ps0->room_above == r0) || (ps0->room_below == r0))) ||
218                                (ps1 && ((ps1->room_above == r0) || (ps1->room_below == r0)));
219                 }
220                 else if(c0->sector && !c1->sector)
221                 {
222                     room_sector_p pc0 = Room_GetSectorRaw(r1, c0->sector->pos);
223                     collides = pc0 && (pc0->portal_to_room == r0);
224                 }
225                 else if(!c0->sector && c1->sector)
226                 {
227                     room_sector_p pc1 = Room_GetSectorRaw(r0, c1->sector->pos);
228                     collides = pc1 && (pc1->portal_to_room == r1);
229                 }
230             }
231         }
232 
233         return collides;
234     }
235 } bt_engine_overlap_filter_callback;
236 
237 
238 struct physics_object_s
239 {
240     btRigidBody    *bt_body;
241 };
242 
243 struct kinematic_info_s
244 {
245     bool        has_collisions;
246 };
247 
248 typedef struct physics_data_s
249 {
250     // kinematic
251     btRigidBody                       **bt_body;
252     struct kinematic_info_s            *bt_info;
253 
254     // dynamic
255     struct ghost_shape_s               *ghosts_info;
256     btPairCachingGhostObject          **ghost_objects;          // like Bullet character controller for penetration resolving.
257     btManifoldArray                    *manifoldArray;          // keep track of the contact manifolds
258     struct collision_node_s            *collision_track;
259     uint16_t                            objects_count;          // Ragdoll joints
260     uint16_t                            bt_joint_count;         // Ragdoll joints
261     btTypedConstraint                 **bt_joints;              // Ragdoll joints
262 
263     int16_t                             collision_group;
264     int16_t                             collision_mask;
265     struct engine_container_s          *cont;
266 }physics_data_t, *physics_data_p;
267 
268 
269 class CBulletDebugDrawer : public btIDebugDraw
270 {
271 public:
CBulletDebugDrawer()272     CBulletDebugDrawer() :
273     m_debugMode(0)
274     {
275     }
276 
~CBulletDebugDrawer()277    ~CBulletDebugDrawer(){}
278 
drawLine(const btVector3 & from,const btVector3 & to,const btVector3 & color)279     virtual void   drawLine(const btVector3& from,const btVector3& to,const btVector3& color) override
280     {
281         renderer.debugDrawer->DrawLine(from.m_floats, to.m_floats, color.m_floats, color.m_floats);
282     }
283 
drawLine(const btVector3 & from,const btVector3 & to,const btVector3 & fromColor,const btVector3 & toColor)284     virtual void   drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor) override
285     {
286         renderer.debugDrawer->DrawLine(from.m_floats, to.m_floats, fromColor.m_floats, toColor.m_floats);
287     }
288 
drawContactPoint(const btVector3 & PointOnB,const btVector3 & normalOnB,btScalar distance,int lifeTime,const btVector3 & color)289     virtual void   drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) override
290     {
291 
292     }
293 
reportErrorWarning(const char * warningString)294     virtual void   reportErrorWarning(const char* warningString) override
295     {
296         Con_AddLine(warningString, FONTSTYLE_CONSOLE_WARNING);
297     }
298 
draw3dText(const btVector3 & location,const char * textString)299     virtual void   draw3dText(const btVector3& location, const char* textString) override
300     {
301         renderer.OutTextXYZ(location.m_floats[0], location.m_floats[1], location.m_floats[2], textString);
302     }
303 
setDebugMode(int debugMode)304     virtual void   setDebugMode(int debugMode) override
305     {
306         m_debugMode = debugMode;
307     }
308 
getDebugMode() const309     virtual int    getDebugMode() const override
310     {
311         return m_debugMode;
312     }
313 
314 private:
315     int32_t m_debugMode;
316 };
317 
318 btDefaultCollisionConfiguration         *bt_engine_collisionConfiguration = NULL;
319 btCollisionDispatcher                   *bt_engine_dispatcher = NULL;
320 btGhostPairCallback                     *bt_engine_ghostPairCallback = NULL;
321 btBroadphaseInterface                   *bt_engine_overlappingPairCache = NULL;
322 btSequentialImpulseConstraintSolver     *bt_engine_solver = NULL;
323 btDiscreteDynamicsWorld                 *bt_engine_dynamicsWorld = NULL;
324 
325 CBulletDebugDrawer                       bt_debug_drawer;
326 
327 /* bullet collision model calculation */
328 btCollisionShape* BT_CSfromBBox(btScalar *bb_min, btScalar *bb_max);
329 btCollisionShape* BT_CSfromMesh(struct base_mesh_s *mesh, bool useCompression, bool buildBvh, bool is_static = true);
330 btCollisionShape* BT_CSfromHeightmap(struct room_sector_s *heightmap, uint32_t sectors_count, struct sector_tween_s *tweens, uint32_t tweens_count, bool useCompression, bool buildBvh);
331 
332 uint32_t BT_AddFloorAndCeilingToTrimesh(btTriangleMesh *trimesh, struct room_sector_s *sector);
333 uint32_t BT_AddSectorTweenToTrimesh(btTriangleMesh *trimesh, struct sector_tween_s *tween);
334 
335 void Physics_DeleteRigidBody(struct physics_data_s *physics);                   // only for internal usage
336 
getInnerBBRadius(btScalar bb_min[3],btScalar bb_max[3])337 btScalar getInnerBBRadius(btScalar bb_min[3], btScalar bb_max[3])
338 {
339     btScalar r = bb_max[0] - bb_min[0];
340     btScalar t = bb_max[1] - bb_min[1];
341     r = ((t > r) && (r != 0.0f)) ? (r) : (t);
342     t = bb_max[2] - bb_min[2];
343     return ((t > r) && (r != 0.0f)) ? (0.5f * r) : (0.5f * t);
344 }
345 
346 // Bullet Physics initialization.
Physics_Init()347 void Physics_Init()
348 {
349     ///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
350     bt_engine_collisionConfiguration = new btDefaultCollisionConfiguration();
351 
352     ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
353     bt_engine_dispatcher = new btCollisionDispatcher(bt_engine_collisionConfiguration);
354 
355     ///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
356     bt_engine_overlappingPairCache = new btDbvtBroadphase();
357     bt_engine_ghostPairCallback = new btGhostPairCallback();
358     bt_engine_overlappingPairCache->getOverlappingPairCache()->setInternalGhostPairCallback(bt_engine_ghostPairCallback);
359 
360     ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
361     bt_engine_solver = new btSequentialImpulseConstraintSolver;
362 
363     bt_engine_dynamicsWorld = new btDiscreteDynamicsWorld(bt_engine_dispatcher, bt_engine_overlappingPairCache, bt_engine_solver, bt_engine_collisionConfiguration);
364     bt_engine_dynamicsWorld->getPairCache()->setOverlapFilterCallback(&bt_engine_overlap_filter_callback);
365     bt_engine_dynamicsWorld->setGravity(btVector3(0, 0, -4500.0));
366 
367     bt_debug_drawer.setDebugMode(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawConstraints);
368     bt_engine_dynamicsWorld->setDebugDrawer(&bt_debug_drawer);
369 }
370 
371 
Physics_Destroy()372 void Physics_Destroy()
373 {
374     //delete dynamics world
375     delete bt_engine_dynamicsWorld;
376 
377     //delete solver
378     delete bt_engine_solver;
379 
380     //delete broadphase
381     delete bt_engine_overlappingPairCache;
382 
383     //delete dispatcher
384     delete bt_engine_dispatcher;
385 
386     delete bt_engine_collisionConfiguration;
387 
388     delete bt_engine_ghostPairCallback;
389 }
390 
391 
Physics_StepSimulation(float time)392 void Physics_StepSimulation(float time)
393 {
394     time = (time < 0.1f) ? (time) : (0.0f);
395     bt_engine_dynamicsWorld->stepSimulation(time, 0);
396 }
397 
Physics_DebugDrawWorld()398 void Physics_DebugDrawWorld()
399 {
400     bt_engine_dynamicsWorld->debugDrawWorld();
401 }
402 
Physics_CleanUpObjects()403 void Physics_CleanUpObjects()
404 {
405     if(bt_engine_dynamicsWorld != NULL)
406     {
407         int num_obj = bt_engine_dynamicsWorld->getNumCollisionObjects();
408         for(int i = 0; i < num_obj; i++)
409         {
410             btCollisionObject* obj = bt_engine_dynamicsWorld->getCollisionObjectArray()[i];
411             btRigidBody* body = btRigidBody::upcast(obj);
412             if(body != NULL)
413             {
414                 engine_container_p cont = (engine_container_p)body->getUserPointer();
415                 body->setUserPointer(NULL);
416 
417                 if(cont && (cont->object_type == OBJECT_BULLET_MISC))
418                 {
419                     if(body->getMotionState())
420                     {
421                         delete body->getMotionState();
422                         body->setMotionState(NULL);
423                     }
424 
425                     if(body->getCollisionShape())
426                     {
427                         delete body->getCollisionShape();
428                         body->setCollisionShape(NULL);
429                     }
430 
431                     bt_engine_dynamicsWorld->removeRigidBody(body);
432                     cont->room = NULL;
433                     free(cont);
434                     delete body;
435                 }
436             }
437         }
438     }
439 }
440 
Physics_CreatePhysicsData(struct engine_container_s * cont)441 struct physics_data_s *Physics_CreatePhysicsData(struct engine_container_s *cont)
442 {
443     struct physics_data_s *ret = (struct physics_data_s*)malloc(sizeof(struct physics_data_s));
444 
445     ret->bt_body = NULL;
446     ret->bt_info = NULL;
447     ret->bt_joints = NULL;
448     ret->objects_count = 0;
449     ret->bt_joint_count = 0;
450     ret->manifoldArray = NULL;
451     ret->ghosts_info = NULL;
452     ret->ghost_objects = NULL;
453     ret->collision_track = NULL;
454     ret->collision_group = btBroadphaseProxy::KinematicFilter;
455     ret->collision_mask = btBroadphaseProxy::AllFilter;
456     ret->cont = cont;
457 
458     return ret;
459 }
460 
461 
Physics_DeletePhysicsData(struct physics_data_s * physics)462 void Physics_DeletePhysicsData(struct physics_data_s *physics)
463 {
464     if(physics)
465     {
466         for(collision_node_p cn = physics->collision_track; cn;)
467         {
468             collision_node_p next = cn->next;
469             free(cn);
470             cn = next;
471         }
472         physics->collision_track = NULL;
473 
474         if(physics->bt_info)
475         {
476             free(physics->bt_info);
477             physics->bt_info = NULL;
478         }
479 
480         if(physics->bt_joints)
481         {
482             for(uint32_t i = 0; i < physics->bt_joint_count; i++)
483             {
484                 if(physics->bt_joints[i])
485                 {
486                     bt_engine_dynamicsWorld->removeConstraint(physics->bt_joints[i]);
487                     delete physics->bt_joints[i];
488                     physics->bt_joints[i] = NULL;
489                 }
490             }
491 
492             free(physics->bt_joints);
493             physics->bt_joints = NULL;
494             physics->bt_joint_count = 0;
495         }
496 
497         if(physics->ghost_objects)
498         {
499             for(int i = 0; i < physics->objects_count; i++)
500             {
501                 physics->ghost_objects[i]->setUserPointer(NULL);
502                 if(physics->ghost_objects[i]->getCollisionShape())
503                 {
504                     delete physics->ghost_objects[i]->getCollisionShape();
505                     physics->ghost_objects[i]->setCollisionShape(NULL);
506                 }
507                 bt_engine_dynamicsWorld->removeCollisionObject(physics->ghost_objects[i]);
508                 delete physics->ghost_objects[i];
509                 physics->ghost_objects[i] = NULL;
510             }
511             free(physics->ghost_objects);
512             physics->ghost_objects = NULL;
513         }
514 
515         if(physics->ghosts_info)
516         {
517             free(physics->ghosts_info);
518             physics->ghosts_info = NULL;
519         }
520 
521         if(physics->manifoldArray)
522         {
523             physics->manifoldArray->clear();
524             delete physics->manifoldArray;
525             physics->manifoldArray = NULL;
526         }
527 
528         Physics_DeleteRigidBody(physics);
529 
530         physics->objects_count = 0;
531         free(physics);
532     }
533 }
534 
535 
536 /* Common physics functions */
Physics_GetGravity(float g[3])537 void Physics_GetGravity(float g[3])
538 {
539     btVector3 bt_g = bt_engine_dynamicsWorld->getGravity();
540     vec3_copy(g, bt_g.m_floats);
541 }
542 
543 
Physics_SetGravity(float g[3])544 void Physics_SetGravity(float g[3])
545 {
546     btVector3 bt_g(g[0], g[1], g[2]);
547     bt_engine_dynamicsWorld->setGravity(bt_g);
548 }
549 
550 
Physics_RayTest(struct collision_result_s * result,float from[3],float to[3],struct engine_container_s * cont,int16_t filter)551 int  Physics_RayTest(struct collision_result_s *result, float from[3], float to[3], struct engine_container_s *cont, int16_t filter)
552 {
553     bt_engine_ClosestRayResultCallback cb(cont, from, to, filter);
554     btVector3 vFrom(from[0], from[1], from[2]), vTo(to[0], to[1], to[2]);
555 
556     if(result)
557     {
558         result->hit = 0x00;
559         result->obj = NULL;
560         result->fraction = 1.0f;
561         bt_engine_dynamicsWorld->rayTest(vFrom, vTo, cb);
562         if(cb.hasHit())
563         {
564             result->obj      = (struct engine_container_s *)cb.m_collisionObject->getUserPointer();
565             result->hit      = 0x01;
566             result->bone_num = cb.m_collisionObject->getUserIndex();
567             vec3_copy(result->normale, cb.m_hitNormalWorld.m_floats);
568             vFrom.setInterpolate3(vFrom, vTo, cb.m_closestHitFraction);
569             vec3_copy(result->point, vFrom.m_floats);
570             result->fraction = cb.m_closestHitFraction;
571             return 1;
572         }
573     }
574     else
575     {
576         bt_engine_dynamicsWorld->rayTest(vFrom, vTo, cb);
577         return cb.hasHit();
578     }
579 
580     return 0;
581 }
582 
583 
Physics_RayTestFiltered(struct collision_result_s * result,float from[3],float to[3],struct engine_container_s * cont,int16_t filter)584 int  Physics_RayTestFiltered(struct collision_result_s *result, float from[3], float to[3], struct engine_container_s *cont, int16_t filter)
585 {
586     bt_engine_ClosestRayResultCallback cb(cont, from, to, filter);
587     btVector3 vFrom(from[0], from[1], from[2]), vTo(to[0], to[1], to[2]);
588 
589     cb.m_flags |= btTriangleRaycastCallback::kF_FilterBackfaces;
590     cb.m_flags |= btTriangleRaycastCallback::kF_KeepUnflippedNormal;
591 
592     if(result)
593     {
594         result->hit = 0x00;
595         result->obj = NULL;
596         result->fraction = 1.0f;
597         bt_engine_dynamicsWorld->rayTest(vFrom, vTo, cb);
598         if(cb.hasHit())
599         {
600             result->obj      = (struct engine_container_s *)cb.m_collisionObject->getUserPointer();
601             result->hit      = 0x01;
602             result->bone_num = cb.m_collisionObject->getUserIndex();
603             vec3_copy(result->normale, cb.m_hitNormalWorld.m_floats);
604             vFrom.setInterpolate3(vFrom, vTo, cb.m_closestHitFraction);
605             vec3_copy(result->point, vFrom.m_floats);
606             result->fraction = cb.m_closestHitFraction;
607             return 1;
608         }
609     }
610     else
611     {
612         bt_engine_dynamicsWorld->rayTest(vFrom, vTo, cb);
613         return cb.hasHit();
614     }
615 
616     return 0;
617 }
618 
619 
Physics_SphereTest(struct collision_result_s * result,float from[3],float to[3],float R,struct engine_container_s * cont,int16_t filter)620 int  Physics_SphereTest(struct collision_result_s *result, float from[3], float to[3], float R, struct engine_container_s *cont, int16_t filter)
621 {
622     bt_engine_ClosestConvexResultCallback cb(cont, from, to, filter);
623     btVector3 vFrom(from[0], from[1], from[2]), vTo(to[0], to[1], to[2]);
624     btTransform tFrom, tTo;
625     btSphereShape sphere(R);
626 
627     tFrom.setIdentity();
628     tFrom.setOrigin(vFrom);
629     tTo.setIdentity();
630     tTo.setOrigin(vTo);
631 
632     if(result)
633     {
634         result->obj = NULL;
635         result->hit = 0x00;
636         result->fraction = 1.0f;
637         bt_engine_dynamicsWorld->convexSweepTest(&sphere, tFrom, tTo, cb);
638         if(cb.hasHit())
639         {
640             result->obj      = (struct engine_container_s *)cb.m_hitCollisionObject->getUserPointer();
641             result->hit      = 0x01;
642             result->bone_num = cb.m_hitCollisionObject->getUserIndex();
643             vec3_copy(result->normale, cb.m_hitNormalWorld.m_floats);
644             vec3_copy(result->point, cb.m_hitPointWorld.m_floats);
645             result->fraction = cb.m_closestHitFraction;
646             return 1;
647         }
648     }
649     else
650     {
651         bt_engine_dynamicsWorld->convexSweepTest(&sphere, tFrom, tTo, cb);
652         return cb.hasHit();
653     }
654 
655     return 0;
656 }
657 
658 
Physics_IsBodyesInited(struct physics_data_s * physics)659 int Physics_IsBodyesInited(struct physics_data_s *physics)
660 {
661     return physics && physics->bt_body;
662 }
663 
664 
Physics_IsGhostsInited(struct physics_data_s * physics)665 int Physics_IsGhostsInited(struct physics_data_s *physics)
666 {
667     return physics && physics->ghost_objects;
668 }
669 
Physics_GetBodiesCount(struct physics_data_s * physics)670 int  Physics_GetBodiesCount(struct physics_data_s *physics)
671 {
672     return (physics) ? (physics->objects_count) : (0);
673 }
674 
Physics_GetBodyWorldTransform(struct physics_data_s * physics,float tr[16],uint16_t index)675 void Physics_GetBodyWorldTransform(struct physics_data_s *physics, float tr[16], uint16_t index)
676 {
677     if(physics->bt_body[index])
678     {
679         physics->bt_body[index]->getWorldTransform().getOpenGLMatrix(tr);
680     }
681 }
682 
683 
Physics_SetBodyWorldTransform(struct physics_data_s * physics,float tr[16],uint16_t index)684 void Physics_SetBodyWorldTransform(struct physics_data_s *physics, float tr[16], uint16_t index)
685 {
686     if(physics->bt_body[index])
687     {
688         physics->bt_body[index]->getWorldTransform().setFromOpenGLMatrix(tr);
689     }
690 }
691 
692 
Physics_GetGhostWorldTransform(struct physics_data_s * physics,float tr[16],uint16_t index)693 void Physics_GetGhostWorldTransform(struct physics_data_s *physics, float tr[16], uint16_t index)
694 {
695     if(physics->ghost_objects && physics->ghost_objects[index])
696     {
697         float offset[3], pos[3];
698         offset[0] = -physics->ghosts_info[index].offset[0];
699         offset[1] = -physics->ghosts_info[index].offset[1];
700         offset[2] = -physics->ghosts_info[index].offset[2];
701         physics->ghost_objects[index]->getWorldTransform().getOpenGLMatrix(tr);
702         Mat4_vec3_mul_macro(pos, tr, offset);
703         vec3_copy(tr + 12, pos);
704     }
705 }
706 
707 
Physics_SetGhostWorldTransform(struct physics_data_s * physics,float tr[16],uint16_t index)708 void Physics_SetGhostWorldTransform(struct physics_data_s *physics, float tr[16], uint16_t index)
709 {
710     if(physics->ghost_objects && physics->ghost_objects[index])
711     {
712         btVector3 origin;
713         Mat4_vec3_mul_macro(origin.m_floats, tr, physics->ghosts_info[index].offset);
714         physics->ghost_objects[index]->getWorldTransform().setFromOpenGLMatrix(tr);
715         physics->ghost_objects[index]->getWorldTransform().setOrigin(origin);
716     }
717 }
718 
719 
Physics_GetGhostShapeInfo(struct physics_data_s * physics,uint16_t index)720 ghost_shape_p Physics_GetGhostShapeInfo(struct physics_data_s *physics, uint16_t index)
721 {
722     return physics->ghosts_info + index;
723 }
724 
725 
726 /**
727  * It is from bullet_character_controller
728  */
Physics_GetGhostCurrentCollision(struct physics_data_s * physics,uint16_t index,int16_t filter)729 collision_node_p Physics_GetGhostCurrentCollision(struct physics_data_s *physics, uint16_t index, int16_t filter)
730 {
731     // Here we must refresh the overlapping paircache as the penetrating movement itself or the
732     // previous recovery iteration might have used setWorldTransform and pushed us into an object
733     // that is not in the previous cache contents from the last timestep, as will happen if we
734     // are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck.
735     //
736     // Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase
737     // paircache and the ghostobject's internal paircache at the same time.    /BW
738 
739     collision_node_p *cn = &(physics->collision_track);
740     btPairCachingGhostObject *ghost = physics->ghost_objects[index];
741     if(ghost && ghost->getBroadphaseHandle())
742     {
743         int num_pairs, manifolds_size;
744         btBroadphasePairArray &pairArray = ghost->getOverlappingPairCache()->getOverlappingPairArray();
745         btVector3 aabb_min, aabb_max;
746 
747         ghost->getCollisionShape()->getAabb(ghost->getWorldTransform(), aabb_min, aabb_max);
748         bt_engine_dynamicsWorld->getBroadphase()->setAabb(ghost->getBroadphaseHandle(), aabb_min, aabb_max, bt_engine_dynamicsWorld->getDispatcher());
749         bt_engine_dynamicsWorld->getDispatcher()->dispatchAllCollisionPairs(ghost->getOverlappingPairCache(), bt_engine_dynamicsWorld->getDispatchInfo(), bt_engine_dynamicsWorld->getDispatcher());
750 
751         num_pairs = pairArray.size();
752         for(int i = 0; i < num_pairs; i++)
753         {
754             // do not use commented code: it prevents to collision skips.
755             //btBroadphasePair &pair = pairArray[i];
756             //btBroadphasePair* collisionPair = bt_engine_dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
757             btBroadphasePair *collisionPair = &pairArray[i];
758             if(collisionPair && collisionPair->m_algorithm)
759             {
760                 physics->manifoldArray->clear();
761                 collisionPair->m_algorithm->getAllContactManifolds(*(physics->manifoldArray));
762                 manifolds_size = physics->manifoldArray->size();
763                 for(int j = 0; j < manifolds_size; j++)
764                 {
765                     btPersistentManifold* manifold = (*(physics->manifoldArray))[j];
766                     btCollisionObject *obj = (btCollisionObject*)manifold->getBody0();
767                     btScalar directionSign = btScalar(1.0);
768                     if(obj == ghost)
769                     {
770                         obj = (btCollisionObject*)manifold->getBody1();
771                         directionSign = btScalar(-1.0);
772                     }
773 
774                     engine_container_p cont = (engine_container_p)obj->getUserPointer();
775                     if(cont && (cont->collision_group & filter))
776                     {
777                         for(int k = 0; k < manifold->getNumContacts(); k++)
778                         {
779                             const btManifoldPoint&pt = manifold->getContactPoint(k);
780                             btScalar dist = pt.getDistance();
781 
782                             if(dist < 0.0)
783                             {
784                                 if(*cn == NULL)
785                                 {
786                                     *cn = (collision_node_p)malloc(sizeof(collision_node_t));
787                                     (*cn)->next = NULL;
788                                 }
789 
790                                 (*cn)->obj = cont;
791                                 (*cn)->part_from = obj->getUserIndex();
792                                 (*cn)->part_self = i;
793                                 (*cn)->penetration[0] = pt.m_normalWorldOnB[0];
794                                 (*cn)->penetration[1] = pt.m_normalWorldOnB[1];
795                                 (*cn)->penetration[2] = pt.m_normalWorldOnB[2];
796                                 (*cn)->penetration[3] = dist * directionSign;
797                                 (*cn)->point[0] = pt.m_positionWorldOnA[0];
798                                 (*cn)->point[1] = pt.m_positionWorldOnA[1];
799                                 (*cn)->point[2] = pt.m_positionWorldOnA[2];
800 
801                                 cn = &((*cn)->next);
802                             }
803                         }
804                     }
805                 }
806             }
807         }
808         physics->manifoldArray->clear();
809     }
810 
811     if(*cn)
812     {
813         (*cn)->obj = NULL;
814     }
815 
816     return physics->collision_track;
817 }
818 
819 
BT_CSfromBBox(btScalar * bb_min,btScalar * bb_max)820 btCollisionShape *BT_CSfromBBox(btScalar *bb_min, btScalar *bb_max)
821 {
822     obb_p obb = OBB_Create();
823     polygon_p p = obb->base_polygons;
824     btTriangleMesh *trimesh = new btTriangleMesh;
825     btVector3 v0, v1, v2;
826     btCollisionShape* ret;
827     int cnt = 0;
828 
829     OBB_Rebuild(obb, bb_min, bb_max);
830     for(uint32_t i = 0; i < 6; i++, p++)
831     {
832         if(!Polygon_IsBroken(p))
833         {
834             for(uint32_t j = 1; j + 1 < p->vertex_count; j++)
835             {
836                 vec3_copy(v0.m_floats, p->vertices[j + 1].position);
837                 vec3_copy(v1.m_floats, p->vertices[j].position);
838                 vec3_copy(v2.m_floats, p->vertices[0].position);
839                 trimesh->addTriangle(v0, v1, v2, true);
840             }
841             cnt ++;
842         }
843     }
844 
845     OBB_Delete(obb);
846 
847     if(cnt == 0)
848     {
849         delete trimesh;
850         return NULL;
851     }
852 
853     ret = new btConvexTriangleMeshShape(trimesh, true);
854 
855     return ret;
856 }
857 
858 
BT_CSfromMesh(struct base_mesh_s * mesh,bool useCompression,bool buildBvh,bool is_static)859 btCollisionShape *BT_CSfromMesh(struct base_mesh_s *mesh, bool useCompression, bool buildBvh, bool is_static)
860 {
861     uint32_t cnt = 0;
862     polygon_p p;
863     btTriangleMesh *trimesh = new btTriangleMesh;
864     btCollisionShape* ret = NULL;
865     btVector3 v0, v1, v2;
866 
867     p = mesh->polygons;
868     for(uint32_t i = 0; i < mesh->polygons_count; i++, p++)
869     {
870         if(!Polygon_IsBroken(p))
871         {
872             for(uint32_t j = 1; j + 1 < p->vertex_count; j++)
873             {
874                 vec3_copy(v0.m_floats, p->vertices[j + 1].position);
875                 vec3_copy(v1.m_floats, p->vertices[j].position);
876                 vec3_copy(v2.m_floats, p->vertices[0].position);
877                 trimesh->addTriangle(v0, v1, v2, true);
878             }
879             cnt ++;
880         }
881     }
882 
883     if(cnt == 0)
884     {
885         delete trimesh;
886         return NULL;
887     }
888 
889     if(is_static)
890     {
891         ret = new btBvhTriangleMeshShape(trimesh, useCompression, buildBvh);
892     }
893     else
894     {
895         ret = new btConvexTriangleMeshShape(trimesh, true);
896     }
897 
898     return ret;
899 }
900 
901 
BT_AddFloorAndCeilingToTrimesh(btTriangleMesh * trimesh,struct room_sector_s * sector)902 uint32_t BT_AddFloorAndCeilingToTrimesh(btTriangleMesh *trimesh, struct room_sector_s *sector)
903 {
904     uint32_t cnt = 0;
905     float *v0, *v1, *v2, *v3;
906 
907     v0 = sector->floor_corners[0];
908     v1 = sector->floor_corners[1];
909     v2 = sector->floor_corners[2];
910     v3 = sector->floor_corners[3];
911     if( (sector->floor_penetration_config != TR_PENETRATION_CONFIG_GHOST) &&
912         (sector->floor_penetration_config != TR_PENETRATION_CONFIG_WALL )  )
913     {
914         if( (sector->floor_diagonal_type == TR_SECTOR_DIAGONAL_TYPE_NONE) ||
915             (sector->floor_diagonal_type == TR_SECTOR_DIAGONAL_TYPE_NW  )  )
916         {
917             if(sector->floor_penetration_config != TR_PENETRATION_CONFIG_DOOR_VERTICAL_A)
918             {
919                 trimesh->addTriangle(btVector3(v3[0], v3[1], v3[2]),
920                                      btVector3(v2[0], v2[1], v2[2]),
921                                      btVector3(v0[0], v0[1], v0[2]),
922                                      true);
923                 cnt++;
924             }
925 
926             if(sector->floor_penetration_config != TR_PENETRATION_CONFIG_DOOR_VERTICAL_B)
927             {
928                 trimesh->addTriangle(btVector3(v2[0], v2[1], v2[2]),
929                                      btVector3(v1[0], v1[1], v1[2]),
930                                      btVector3(v0[0], v0[1], v0[2]),
931                                      true);
932                 cnt++;
933             }
934         }
935         else
936         {
937             if(sector->floor_penetration_config != TR_PENETRATION_CONFIG_DOOR_VERTICAL_A)
938             {
939                 trimesh->addTriangle(btVector3(v3[0], v3[1], v3[2]),
940                                      btVector3(v2[0], v2[1], v2[2]),
941                                      btVector3(v1[0], v1[1], v1[2]),
942                                      true);
943                 cnt++;
944             }
945 
946             if(sector->floor_penetration_config != TR_PENETRATION_CONFIG_DOOR_VERTICAL_B)
947             {
948                 trimesh->addTriangle(btVector3(v3[0], v3[1], v3[2]),
949                                      btVector3(v1[0], v1[1], v1[2]),
950                                      btVector3(v0[0], v0[1], v0[2]),
951                                      true);
952                 cnt++;
953             }
954         }
955     }
956 
957     v0 = sector->ceiling_corners[0];
958     v1 = sector->ceiling_corners[1];
959     v2 = sector->ceiling_corners[2];
960     v3 = sector->ceiling_corners[3];
961     if( (sector->ceiling_penetration_config != TR_PENETRATION_CONFIG_GHOST) &&
962         (sector->ceiling_penetration_config != TR_PENETRATION_CONFIG_WALL )  )
963     {
964         if( (sector->ceiling_diagonal_type == TR_SECTOR_DIAGONAL_TYPE_NONE) ||
965             (sector->ceiling_diagonal_type == TR_SECTOR_DIAGONAL_TYPE_NW  )  )
966         {
967             if(sector->ceiling_penetration_config != TR_PENETRATION_CONFIG_DOOR_VERTICAL_A)
968             {
969                 trimesh->addTriangle(btVector3(v0[0], v0[1], v0[2]),
970                                      btVector3(v2[0], v2[1], v2[2]),
971                                      btVector3(v3[0], v3[1], v3[2]),
972                                      true);
973                 cnt++;
974             }
975 
976             if(sector->ceiling_penetration_config != TR_PENETRATION_CONFIG_DOOR_VERTICAL_B)
977             {
978                 trimesh->addTriangle(btVector3(v0[0], v0[1], v0[2]),
979                                      btVector3(v1[0], v1[1], v1[2]),
980                                      btVector3(v2[0], v2[1], v2[2]),
981                                      true);
982                 cnt++;
983             }
984         }
985         else
986         {
987             if(sector->ceiling_penetration_config != TR_PENETRATION_CONFIG_DOOR_VERTICAL_A)
988             {
989                 trimesh->addTriangle(btVector3(v0[0], v0[1], v0[2]),
990                                      btVector3(v1[0], v1[1], v1[2]),
991                                      btVector3(v3[0], v3[1], v3[2]),
992                                      true);
993                 cnt++;
994             }
995 
996             if(sector->ceiling_penetration_config != TR_PENETRATION_CONFIG_DOOR_VERTICAL_B)
997             {
998                 trimesh->addTriangle(btVector3(v1[0], v1[1], v1[2]),
999                                      btVector3(v2[0], v2[1], v2[2]),
1000                                      btVector3(v3[0], v3[1], v3[2]),
1001                                      true);
1002                 cnt++;
1003             }
1004         }
1005     }
1006 
1007     return cnt;
1008 }
1009 
1010 
BT_AddSectorTweenToTrimesh(btTriangleMesh * trimesh,struct sector_tween_s * tween)1011 uint32_t BT_AddSectorTweenToTrimesh(btTriangleMesh *trimesh, struct sector_tween_s *tween)
1012 {
1013     uint32_t cnt = 0;
1014     float *v0, *v1, *v2, *v3;
1015 
1016     if(tween->ceiling_tween_inverted == 0x00)
1017     {
1018         v0 = tween->ceiling_corners[0];
1019         v1 = tween->ceiling_corners[1];
1020         v2 = tween->ceiling_corners[2];
1021         v3 = tween->ceiling_corners[3];
1022     }
1023     else
1024     {
1025         v0 = tween->ceiling_corners[0];
1026         v1 = tween->ceiling_corners[3];
1027         v2 = tween->ceiling_corners[2];
1028         v3 = tween->ceiling_corners[1];
1029     }
1030 
1031     switch(tween->ceiling_tween_type)
1032     {
1033         case TR_SECTOR_TWEEN_TYPE_2TRIANGLES:
1034             {
1035                 btScalar t = fabs((tween->ceiling_corners[2][2] - tween->ceiling_corners[3][2]) /
1036                                   (tween->ceiling_corners[0][2] - tween->ceiling_corners[1][2]));
1037                 t = 1.0 / (1.0 + t);
1038                 btScalar o[3], t1 = 1.0 - t;
1039                 vec3_interpolate_macro(o, v0, v2, t, t1);
1040 
1041                 trimesh->addTriangle(btVector3(v0[0], v0[1], v0[2]),
1042                                      btVector3(v1[0], v1[1], v1[2]),
1043                                      btVector3(o[0], o[1], o[2]),
1044                                      true);
1045                 trimesh->addTriangle(btVector3(v3[0], v3[1], v3[2]),
1046                                      btVector3(v2[0], v2[1], v2[2]),
1047                                      btVector3(o[0], o[1], o[2]),
1048                                      true);
1049                 cnt += 2;
1050             }
1051             break;
1052 
1053         case TR_SECTOR_TWEEN_TYPE_TRIANGLE_LEFT:
1054             {
1055                 trimesh->addTriangle(btVector3(v0[0], v0[1], v0[2]),
1056                                      btVector3(v1[0], v1[1], v1[2]),
1057                                      btVector3(v3[0], v3[1], v3[2]),
1058                                      true);
1059                 cnt++;
1060             }
1061             break;
1062 
1063         case TR_SECTOR_TWEEN_TYPE_TRIANGLE_RIGHT:
1064             {
1065                 trimesh->addTriangle(btVector3(v1[0], v1[1], v1[2]),
1066                                      btVector3(v2[0], v2[1], v2[2]),
1067                                      btVector3(v3[0], v3[1], v3[2]),
1068                                      true);
1069                 cnt++;
1070             }
1071             break;
1072 
1073         case TR_SECTOR_TWEEN_TYPE_QUAD:
1074             {
1075                 trimesh->addTriangle(btVector3(v0[0], v0[1], v0[2]),
1076                                      btVector3(v1[0], v1[1], v1[2]),
1077                                      btVector3(v3[0], v3[1], v3[2]),
1078                                      true);
1079                 trimesh->addTriangle(btVector3(v1[0], v1[1], v1[2]),
1080                                      btVector3(v2[0], v2[1], v2[2]),
1081                                      btVector3(v3[0], v3[1], v3[2]),
1082                                      true);
1083                 cnt += 2;
1084             }
1085             break;
1086     };
1087 
1088     if(tween->floor_tween_inverted == 0x00)
1089     {
1090         v0 = tween->floor_corners[0];
1091         v1 = tween->floor_corners[1];
1092         v2 = tween->floor_corners[2];
1093         v3 = tween->floor_corners[3];
1094     }
1095     else
1096     {
1097         v0 = tween->floor_corners[0];
1098         v1 = tween->floor_corners[3];
1099         v2 = tween->floor_corners[2];
1100         v3 = tween->floor_corners[1];
1101     }
1102 
1103     switch(tween->floor_tween_type)
1104     {
1105         case TR_SECTOR_TWEEN_TYPE_2TRIANGLES:
1106             {
1107                 btScalar t = fabs((tween->floor_corners[2][2] - tween->floor_corners[3][2]) /
1108                                   (tween->floor_corners[0][2] - tween->floor_corners[1][2]));
1109                 t = 1.0 / (1.0 + t);
1110                 btScalar o[3], t1 = 1.0 - t;
1111                 vec3_interpolate_macro(o, v0, v2, t, t1);
1112 
1113                 trimesh->addTriangle(btVector3(v0[0], v0[1], v0[2]),
1114                                      btVector3(v1[0], v1[1], v1[2]),
1115                                      btVector3(o[0], o[1], o[2]),
1116                                      true);
1117                 trimesh->addTriangle(btVector3(v3[0], v3[1], v3[2]),
1118                                      btVector3(v2[0], v2[1], v2[2]),
1119                                      btVector3(o[0], o[1], o[2]),
1120                                      true);
1121                 cnt += 2;
1122             }
1123             break;
1124 
1125         case TR_SECTOR_TWEEN_TYPE_TRIANGLE_LEFT:
1126             {
1127                 trimesh->addTriangle(btVector3(v0[0], v0[1], v0[2]),
1128                                      btVector3(v1[0], v1[1], v1[2]),
1129                                      btVector3(v3[0], v3[1], v3[2]),
1130                                      true);
1131                 cnt++;
1132             }
1133             break;
1134 
1135         case TR_SECTOR_TWEEN_TYPE_TRIANGLE_RIGHT:
1136             {
1137                 trimesh->addTriangle(btVector3(v1[0], v1[1], v1[2]),
1138                                      btVector3(v2[0], v2[1], v2[2]),
1139                                      btVector3(v3[0], v3[1], v3[2]),
1140                                      true);
1141                 cnt++;
1142             }
1143             break;
1144 
1145         case TR_SECTOR_TWEEN_TYPE_QUAD:
1146             {
1147                 trimesh->addTriangle(btVector3(v0[0], v0[1], v0[2]),
1148                                      btVector3(v1[0], v1[1], v1[2]),
1149                                      btVector3(v3[0], v3[1], v3[2]),
1150                                      true);
1151                 trimesh->addTriangle(btVector3(v1[0], v1[1], v1[2]),
1152                                      btVector3(v2[0], v2[1], v2[2]),
1153                                      btVector3(v3[0], v3[1], v3[2]),
1154                                      true);
1155                 cnt += 2;
1156             }
1157             break;
1158     };
1159 
1160     return cnt;
1161 }
1162 
1163 
BT_CSfromHeightmap(struct room_sector_s * heightmap,uint32_t sectors_count,struct sector_tween_s * tweens,uint32_t tweens_count,bool useCompression,bool buildBvh)1164 btCollisionShape *BT_CSfromHeightmap(struct room_sector_s *heightmap, uint32_t sectors_count, struct sector_tween_s *tweens, uint32_t tweens_count, bool useCompression, bool buildBvh)
1165 {
1166     uint32_t cnt = 0;
1167     btTriangleMesh *trimesh = new btTriangleMesh;
1168     btCollisionShape* ret = NULL;
1169 
1170     for(uint32_t i = 0; i < sectors_count; i++)
1171     {
1172         cnt += BT_AddFloorAndCeilingToTrimesh(trimesh, heightmap + i);
1173     }
1174 
1175     for(uint32_t i = 0; i < tweens_count; i++)
1176     {
1177         cnt += BT_AddSectorTweenToTrimesh(trimesh, tweens + i);
1178     }
1179 
1180     if(cnt == 0)
1181     {
1182         delete trimesh;
1183         return NULL;
1184     }
1185 
1186     ret = new btBvhTriangleMeshShape(trimesh, useCompression, buildBvh);
1187     return ret;
1188 }
1189 
1190 /*
1191  * =============================================================================
1192  */
1193 
Physics_GenRigidBody(struct physics_data_s * physics,struct ss_bone_frame_s * bf)1194 void Physics_GenRigidBody(struct physics_data_s *physics, struct ss_bone_frame_s *bf)
1195 {
1196     btVector3 localInertia(0, 0, 0);
1197     btTransform startTransform;
1198     btCollisionShape *cshape = NULL;
1199 
1200     Physics_DeleteRigidBody(physics);
1201     if(physics->bt_info)
1202     {
1203         free(physics->bt_info);
1204         physics->bt_info = NULL;
1205     }
1206 
1207     switch(physics->cont->collision_shape)
1208     {
1209         case COLLISION_SHAPE_SINGLE_BOX:
1210             {
1211                 physics->objects_count = 1;
1212                 physics->bt_body = (btRigidBody**)malloc(physics->objects_count * sizeof(btRigidBody*));
1213                 physics->bt_info = (struct kinematic_info_s*)malloc(physics->objects_count * sizeof(struct kinematic_info_s));
1214                 physics->bt_info->has_collisions = true;
1215 
1216                 float hx = (bf->bb_max[0] - bf->bb_min[0]) * 0.5f;
1217                 float hy = (bf->bb_max[1] - bf->bb_min[1]) * 0.5f;
1218                 float hz = (bf->bb_max[2] - bf->bb_min[2]) * 0.5f;
1219                 cshape = new btBoxShape(btVector3(hx, hy, hz));
1220                 cshape->calculateLocalInertia(0.0, localInertia);
1221                 cshape->setMargin(COLLISION_MARGIN_DEFAULT);
1222                 startTransform.setIdentity();
1223                 btDefaultMotionState* motionState = new btDefaultMotionState(startTransform);
1224                 physics->bt_body[0] = new btRigidBody(0.0, motionState, cshape, localInertia);
1225                 physics->bt_body[0]->setUserPointer(physics->cont);
1226                 physics->bt_body[0]->setUserIndex(0);
1227                 physics->bt_body[0]->setRestitution(1.0);
1228                 physics->bt_body[0]->setFriction(1.0);
1229                 bt_engine_dynamicsWorld->addRigidBody(physics->bt_body[0], btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::AllFilter);
1230             }
1231             break;
1232 
1233         case COLLISION_SHAPE_SINGLE_SPHERE:
1234             {
1235                 physics->objects_count = 1;
1236                 physics->bt_body = (btRigidBody**)malloc(physics->objects_count * sizeof(btRigidBody*));
1237                 physics->bt_info = (struct kinematic_info_s*)malloc(physics->objects_count * sizeof(struct kinematic_info_s));
1238                 physics->bt_info->has_collisions = true;
1239 
1240                 cshape = new btSphereShape(getInnerBBRadius(bf->bb_min, bf->bb_max));
1241                 cshape->calculateLocalInertia(0.0, localInertia);
1242                 cshape->setMargin(COLLISION_MARGIN_DEFAULT);
1243                 startTransform.setIdentity();
1244                 btDefaultMotionState* motionState = new btDefaultMotionState(startTransform);
1245                 physics->bt_body[0] = new btRigidBody(0.0, motionState, cshape, localInertia);
1246                 physics->bt_body[0]->setUserPointer(physics->cont);
1247                 physics->bt_body[0]->setUserIndex(0);
1248                 physics->bt_body[0]->setRestitution(1.0);
1249                 physics->bt_body[0]->setFriction(1.0);
1250                 bt_engine_dynamicsWorld->addRigidBody(physics->bt_body[0], btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::AllFilter);
1251             }
1252             break;
1253 
1254         default:
1255             {
1256                 physics->objects_count = bf->bone_tag_count;
1257                 physics->bt_body = (btRigidBody**)malloc(physics->objects_count * sizeof(btRigidBody*));
1258                 physics->bt_info = (struct kinematic_info_s*)malloc(physics->objects_count * sizeof(struct kinematic_info_s));
1259 
1260                 for(uint32_t i = 0; i < physics->objects_count; i++)
1261                 {
1262                     base_mesh_p mesh = bf->bone_tags[i].mesh_base;
1263                     cshape = NULL;
1264                     physics->bt_info[i].has_collisions = false;
1265                     switch(physics->cont->collision_shape)
1266                     {
1267                         case COLLISION_SHAPE_TRIMESH_CONVEX:
1268                             cshape = BT_CSfromMesh(mesh, true, true, false);
1269                             break;
1270 
1271                         case COLLISION_SHAPE_TRIMESH:
1272                             cshape = BT_CSfromMesh(mesh, true, true, true);
1273                             break;
1274 
1275                         case COLLISION_SHAPE_BOX:
1276                             cshape = BT_CSfromBBox(mesh->bb_min, mesh->bb_max);
1277                             break;
1278 
1279                             ///@TODO: add other shapes implementation; may be change default;
1280                         default:
1281                              cshape = BT_CSfromMesh(mesh, true, true, true);
1282                              break;
1283                     };
1284 
1285                     physics->bt_body[i] = NULL;
1286 
1287                     if(cshape)
1288                     {
1289                         physics->bt_info[i].has_collisions = true;
1290                         cshape->calculateLocalInertia(0.0, localInertia);
1291                         cshape->setMargin(COLLISION_MARGIN_DEFAULT);
1292 
1293                         startTransform.setIdentity();
1294                         btDefaultMotionState* motionState = new btDefaultMotionState(startTransform);
1295                         physics->bt_body[i] = new btRigidBody(0.0, motionState, cshape, localInertia);
1296                         physics->bt_body[i]->setUserPointer(physics->cont);
1297                         physics->bt_body[i]->setUserIndex(i);
1298                         physics->bt_body[i]->setRestitution(1.0);
1299                         physics->bt_body[i]->setFriction(1.0);
1300                         bt_engine_dynamicsWorld->addRigidBody(physics->bt_body[i], btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::AllFilter);
1301                     }
1302                 }
1303             }
1304             break;
1305     };
1306 }
1307 
1308 
Physics_DeleteRigidBody(struct physics_data_s * physics)1309 void Physics_DeleteRigidBody(struct physics_data_s *physics)
1310 {
1311     if(physics->bt_body)
1312     {
1313         for(int i = 0; i < physics->objects_count; i++)
1314         {
1315             btRigidBody *body = physics->bt_body[i];
1316             if(body)
1317             {
1318                 body->setUserPointer(NULL);
1319                 if(body->getMotionState())
1320                 {
1321                     delete body->getMotionState();
1322                     body->setMotionState(NULL);
1323                 }
1324                 if(body->getCollisionShape())
1325                 {
1326                     delete body->getCollisionShape();
1327                     body->setCollisionShape(NULL);
1328                 }
1329 
1330                 bt_engine_dynamicsWorld->removeRigidBody(body);
1331                 delete body;
1332                 physics->bt_body[i] = NULL;
1333             }
1334         }
1335         free(physics->bt_body);
1336         physics->bt_body = NULL;
1337     }
1338 }
1339 
1340 
1341 /*
1342  * 80% boxes hack now is default, but may be rewritten;
1343  */
Physics_CreateGhosts(struct physics_data_s * physics,struct ss_bone_frame_s * bf,struct ghost_shape_s * shape_info)1344 void Physics_CreateGhosts(struct physics_data_s *physics, struct ss_bone_frame_s *bf, struct ghost_shape_s *shape_info)
1345 {
1346     if(physics->objects_count > 0)
1347     {
1348         btTransform tr;
1349         if(!physics->manifoldArray)
1350         {
1351             physics->manifoldArray = new btManifoldArray();
1352         }
1353 
1354         switch(physics->cont->collision_shape)
1355         {
1356             case COLLISION_SHAPE_SINGLE_BOX:
1357                 {
1358                     physics->ghosts_info = (ghost_shape_p)malloc(sizeof(ghost_shape_t));
1359                     physics->ghosts_info[0].shape_id = COLLISION_SHAPE_SINGLE_BOX;
1360                     vec3_copy(physics->ghosts_info[0].bb_max, bf->bb_max);
1361                     vec3_copy(physics->ghosts_info[0].bb_min, bf->bb_min);
1362                     physics->ghosts_info[0].radius = getInnerBBRadius(bf->bb_min, bf->bb_max);
1363                     vec3_set_zero(physics->ghosts_info[0].offset);
1364 
1365                     physics->ghost_objects = (btPairCachingGhostObject**)malloc(bf->bone_tag_count * sizeof(btPairCachingGhostObject*));
1366                     physics->ghost_objects[0] = new btPairCachingGhostObject();
1367                     physics->ghost_objects[0]->setIgnoreCollisionCheck(physics->bt_body[0], true);
1368                     tr.setIdentity();
1369                     physics->ghost_objects[0]->setWorldTransform(tr);
1370                     physics->ghost_objects[0]->setUserPointer(physics->cont);
1371                     physics->ghost_objects[0]->setUserIndex(-1);
1372 
1373                     float hx = (bf->bb_max[0] - bf->bb_min[0]) * 0.5f;
1374                     float hy = (bf->bb_max[1] - bf->bb_min[1]) * 0.5f;
1375                     float hz = (bf->bb_max[2] - bf->bb_min[2]) * 0.5f;
1376                     physics->ghost_objects[0]->setCollisionShape(new btBoxShape(btVector3(hx, hy, hz)));
1377                     physics->ghost_objects[0]->getCollisionShape()->setMargin(COLLISION_MARGIN_DEFAULT);
1378                     bt_engine_dynamicsWorld->addCollisionObject(physics->ghost_objects[0], btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::SensorTrigger);
1379                 }
1380                 break;
1381 
1382             case COLLISION_SHAPE_SINGLE_SPHERE:
1383                 {
1384                     physics->ghosts_info = (ghost_shape_p)malloc(sizeof(ghost_shape_t));
1385                     physics->ghosts_info[0].shape_id = COLLISION_SHAPE_SINGLE_SPHERE;
1386                     vec3_copy(physics->ghosts_info[0].bb_max, bf->bb_max);
1387                     vec3_copy(physics->ghosts_info[0].bb_min, bf->bb_min);
1388                     physics->ghosts_info[0].radius = getInnerBBRadius(bf->bb_min, bf->bb_max);
1389                     vec3_set_zero(physics->ghosts_info[0].offset);
1390 
1391                     physics->ghost_objects = (btPairCachingGhostObject**)malloc(bf->bone_tag_count * sizeof(btPairCachingGhostObject*));
1392                     physics->ghost_objects[0] = new btPairCachingGhostObject();
1393                     physics->ghost_objects[0]->setIgnoreCollisionCheck(physics->bt_body[0], true);
1394                     tr.setIdentity();
1395                     physics->ghost_objects[0]->setWorldTransform(tr);
1396                     physics->ghost_objects[0]->setUserPointer(physics->cont);
1397                     physics->ghost_objects[0]->setUserIndex(-1);
1398                     physics->ghost_objects[0]->setCollisionShape(new btSphereShape(physics->ghosts_info[0].radius));
1399                     physics->ghost_objects[0]->getCollisionShape()->setMargin(COLLISION_MARGIN_DEFAULT);
1400                     bt_engine_dynamicsWorld->addCollisionObject(physics->ghost_objects[0], btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::SensorTrigger);
1401                 }
1402                 break;
1403 
1404             default:
1405                 {
1406                     physics->ghosts_info = (ghost_shape_p)malloc(bf->bone_tag_count * sizeof(ghost_shape_t));
1407                     physics->ghost_objects = (btPairCachingGhostObject**)malloc(bf->bone_tag_count * sizeof(btPairCachingGhostObject*));
1408                     for(uint32_t i = 0; i < physics->objects_count; i++)
1409                     {
1410                         ss_bone_tag_p b_tag = bf->bone_tags + i;
1411 
1412                         physics->ghost_objects[i] = new btPairCachingGhostObject();
1413                         physics->ghost_objects[i]->setIgnoreCollisionCheck(physics->bt_body[i], true);
1414                         tr.setIdentity();
1415                         physics->ghost_objects[i]->setWorldTransform(tr);
1416                         physics->ghost_objects[i]->setUserPointer(physics->cont);
1417                         physics->ghost_objects[i]->setUserIndex(i);
1418                         if(shape_info)
1419                         {
1420                             float hx = (shape_info[i].bb_max[0] - shape_info[i].bb_min[0]) * 0.5f;
1421                             float hy = (shape_info[i].bb_max[1] - shape_info[i].bb_min[1]) * 0.5f;
1422                             float hz = (shape_info[i].bb_max[2] - shape_info[i].bb_min[2]) * 0.5f;
1423                             physics->ghosts_info[i] = shape_info[i];
1424                             switch(shape_info[i].shape_id)
1425                             {
1426                                 case COLLISION_SHAPE_BOX:
1427                                     physics->ghost_objects[i]->setCollisionShape(new btBoxShape(btVector3(hx, hy, hz)));
1428                                     break;
1429 
1430                                 case COLLISION_SHAPE_SPHERE:
1431                                     physics->ghost_objects[i]->setCollisionShape(new btSphereShape(hx));
1432                                     break;
1433 
1434                                 default:
1435                                     vec3_set_zero(physics->ghosts_info[i].offset);
1436                                     physics->ghost_objects[i]->setCollisionShape(BT_CSfromMesh(b_tag->mesh_base, true, true, false));
1437                                     break;
1438                             };
1439                         }
1440                         else
1441                         {
1442                             physics->ghosts_info[i].shape_id = COLLISION_SHAPE_TRIMESH_CONVEX;
1443                             vec3_copy(physics->ghosts_info[i].bb_max, b_tag->mesh_base->bb_max);
1444                             vec3_copy(physics->ghosts_info[i].bb_min, b_tag->mesh_base->bb_min);
1445                             vec3_set_zero(physics->ghosts_info[i].offset);
1446                             physics->ghost_objects[i]->setCollisionShape(BT_CSfromMesh(b_tag->mesh_base, true, true, false));
1447                         }
1448                         physics->ghosts_info[i].radius = getInnerBBRadius(physics->ghosts_info[i].bb_min, physics->ghosts_info[i].bb_max);
1449                         physics->ghost_objects[i]->getCollisionShape()->setMargin(COLLISION_MARGIN_DEFAULT);
1450                         bt_engine_dynamicsWorld->addCollisionObject(physics->ghost_objects[i], btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::SensorTrigger);
1451                     }
1452                 }
1453         };
1454     }
1455 }
1456 
1457 
Physics_SetGhostCollisionShape(struct physics_data_s * physics,struct ss_bone_frame_s * bf,uint16_t index,struct ghost_shape_s * shape_info)1458 void Physics_SetGhostCollisionShape(struct physics_data_s *physics, struct ss_bone_frame_s *bf, uint16_t index, struct ghost_shape_s *shape_info)
1459 {
1460     if(physics->ghost_objects && (index < physics->objects_count) && physics->ghost_objects[index])
1461     {
1462         btCollisionShape *new_shape = NULL;
1463         float hx = (shape_info->bb_max[0] - shape_info->bb_min[0]) * 0.5f;
1464         float hy = (shape_info->bb_max[1] - shape_info->bb_min[1]) * 0.5f;
1465         float hz = (shape_info->bb_max[2] - shape_info->bb_min[2]) * 0.5f;
1466         shape_info->radius = getInnerBBRadius(shape_info->bb_min, shape_info->bb_max);
1467         if((hx <= 0.0f) || (hy <= 0.0f) || (hz <= 0.0f))
1468         {
1469             shape_info->shape_id = COLLISION_NONE;
1470             physics->ghosts_info[index].shape_id = COLLISION_NONE;
1471         }
1472 
1473         switch(shape_info->shape_id)
1474         {
1475             case COLLISION_SHAPE_BOX:
1476                 new_shape = new btBoxShape(btVector3(hx, hy, hz));
1477                 break;
1478 
1479             case COLLISION_SHAPE_SPHERE:
1480                 new_shape = new btSphereShape(hx);
1481                 break;
1482 
1483             case COLLISION_SHAPE_TRIMESH:
1484                 new_shape = BT_CSfromMesh(bf->bone_tags[index].mesh_base, true, true, false);
1485                 break;
1486 
1487             case COLLISION_NONE:
1488                 bt_engine_dynamicsWorld->removeCollisionObject(physics->ghost_objects[index]);
1489                 break;
1490         };
1491 
1492         if(new_shape)
1493         {
1494             btCollisionShape *old_shape = physics->ghost_objects[index]->getCollisionShape();
1495             physics->ghosts_info[index] = *shape_info;
1496             physics->ghost_objects[index]->setCollisionShape(new_shape);
1497             physics->ghost_objects[index]->getCollisionShape()->setMargin(COLLISION_MARGIN_DEFAULT);
1498             if(!physics->ghost_objects[index]->getBroadphaseHandle())
1499             {
1500                 bt_engine_dynamicsWorld->addCollisionObject(physics->ghost_objects[index], btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::SensorTrigger);
1501             }
1502             if(old_shape)
1503             {
1504                 delete old_shape;
1505             }
1506         }
1507     }
1508 }
1509 
1510 
Physics_GenStaticMeshRigidBody(struct static_mesh_s * smesh)1511 void Physics_GenStaticMeshRigidBody(struct static_mesh_s *smesh)
1512 {
1513     btCollisionShape *cshape = NULL;
1514 
1515     if(smesh->self->collision_group == COLLISION_NONE)
1516     {
1517         return;
1518     }
1519 
1520     smesh->physics_body = NULL;
1521     switch(smesh->self->collision_shape)
1522     {
1523         case COLLISION_SHAPE_BOX:
1524             cshape = BT_CSfromBBox(smesh->cbb_min, smesh->cbb_max);
1525             break;
1526 
1527         case COLLISION_SHAPE_BOX_BASE:
1528             cshape = BT_CSfromBBox(smesh->mesh->bb_min, smesh->mesh->bb_max);
1529             break;
1530 
1531         case COLLISION_SHAPE_TRIMESH:
1532             cshape = BT_CSfromMesh(smesh->mesh, true, true, true);
1533             break;
1534 
1535         case COLLISION_SHAPE_TRIMESH_CONVEX:
1536             cshape = BT_CSfromMesh(smesh->mesh, true, true, false);
1537             break;
1538 
1539         default:
1540             cshape = NULL;
1541             break;
1542     };
1543 
1544     if(cshape)
1545     {
1546         btVector3 localInertia(0, 0, 0);
1547         btTransform startTransform;
1548         startTransform.setFromOpenGLMatrix(smesh->transform);
1549         smesh->physics_body = (struct physics_object_s*)malloc(sizeof(struct physics_object_s));
1550         btDefaultMotionState* motionState = new btDefaultMotionState(startTransform);
1551         smesh->physics_body->bt_body = new btRigidBody(0.0, motionState, cshape, localInertia);
1552         cshape->setMargin(COLLISION_MARGIN_DEFAULT);
1553         smesh->physics_body->bt_body->setRestitution(1.0);
1554         smesh->physics_body->bt_body->setFriction(1.0);
1555         bt_engine_dynamicsWorld->addRigidBody(smesh->physics_body->bt_body, btBroadphaseProxy::StaticFilter, btBroadphaseProxy::AllFilter);
1556         smesh->physics_body->bt_body->setUserPointer(smesh->self);
1557     }
1558 }
1559 
1560 
Physics_GenRoomRigidBody(struct room_s * room,struct room_sector_s * heightmap,uint32_t sectors_count,struct sector_tween_s * tweens,int num_tweens)1561 struct physics_object_s* Physics_GenRoomRigidBody(struct room_s *room, struct room_sector_s *heightmap, uint32_t sectors_count, struct sector_tween_s *tweens, int num_tweens)
1562 {
1563     btCollisionShape *cshape = BT_CSfromHeightmap(heightmap, sectors_count, tweens, num_tweens, true, true);
1564     struct physics_object_s *ret = NULL;
1565 
1566     if(cshape)
1567     {
1568         btVector3 localInertia(0, 0, 0);
1569         btTransform tr;
1570         tr.setFromOpenGLMatrix(room->transform);
1571         ret = (struct physics_object_s*)malloc(sizeof(struct physics_object_s));
1572         btDefaultMotionState* motionState = new btDefaultMotionState(tr);
1573         cshape->setMargin(COLLISION_MARGIN_DEFAULT);
1574         ret->bt_body = new btRigidBody(0.0, motionState, cshape, localInertia);
1575         bt_engine_dynamicsWorld->addRigidBody(ret->bt_body, btBroadphaseProxy::StaticFilter, btBroadphaseProxy::AllFilter);
1576         ret->bt_body->setUserPointer(room->self);
1577         ret->bt_body->setUserIndex(0);
1578         ret->bt_body->setRestitution(1.0);
1579         ret->bt_body->setFriction(1.0);
1580     }
1581 
1582     return ret;
1583 }
1584 
1585 
Physics_SetOwnerObject(struct physics_object_s * obj,struct engine_container_s * self)1586 void Physics_SetOwnerObject(struct physics_object_s *obj, struct engine_container_s *self)
1587 {
1588     if(obj && obj->bt_body)
1589     {
1590         obj->bt_body->setUserPointer(self);
1591     }
1592 }
1593 
1594 
Physics_DeleteObject(struct physics_object_s * obj)1595 void Physics_DeleteObject(struct physics_object_s *obj)
1596 {
1597     if(obj)
1598     {
1599         obj->bt_body->setUserPointer(NULL);
1600         if(obj->bt_body->getMotionState())
1601         {
1602             delete obj->bt_body->getMotionState();
1603             obj->bt_body->setMotionState(NULL);
1604         }
1605         if(obj->bt_body->getCollisionShape())
1606         {
1607             delete obj->bt_body->getCollisionShape();
1608             obj->bt_body->setCollisionShape(NULL);
1609         }
1610 
1611         bt_engine_dynamicsWorld->removeRigidBody(obj->bt_body);
1612         delete obj->bt_body;
1613         free(obj);
1614     }
1615 }
1616 
1617 
Physics_EnableObject(struct physics_object_s * obj)1618 void Physics_EnableObject(struct physics_object_s *obj)
1619 {
1620     if(obj->bt_body && !obj->bt_body->isInWorld())
1621     {
1622         bt_engine_dynamicsWorld->addRigidBody(obj->bt_body, btBroadphaseProxy::StaticFilter, btBroadphaseProxy::AllFilter);
1623     }
1624 }
1625 
1626 
Physics_DisableObject(struct physics_object_s * obj)1627 void Physics_DisableObject(struct physics_object_s *obj)
1628 {
1629     if(obj->bt_body && obj->bt_body->isInWorld())
1630     {
1631         bt_engine_dynamicsWorld->removeRigidBody(obj->bt_body);
1632     }
1633 }
1634 
1635 
1636 /**
1637  * This function enables collision for entity_p in all cases exept NULL models.
1638  * If collision models does not exists, function will create them;
1639  * @param ent - pointer to the entity.
1640  */
Physics_EnableCollision(struct physics_data_s * physics)1641 void Physics_EnableCollision(struct physics_data_s *physics)
1642 {
1643     if(physics->bt_body)
1644     {
1645         for(uint32_t i = 0; i < physics->objects_count; i++)
1646         {
1647             btRigidBody *b = physics->bt_body[i];
1648             if(b && physics->bt_info[i].has_collisions && !b->isInWorld())
1649             {
1650                 bt_engine_dynamicsWorld->addRigidBody(b, physics->collision_group, physics->collision_mask);
1651             }
1652             if(physics->ghost_objects && physics->ghost_objects[i] &&
1653                (physics->ghosts_info[i].shape_id != COLLISION_NONE) &&
1654                !physics->ghost_objects[i]->getBroadphaseHandle())
1655             {
1656                 bt_engine_dynamicsWorld->addCollisionObject(physics->ghost_objects[i], btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::SensorTrigger);
1657             }
1658         }
1659     }
1660 }
1661 
1662 
Physics_DisableCollision(struct physics_data_s * physics)1663 void Physics_DisableCollision(struct physics_data_s *physics)
1664 {
1665     if(physics->bt_body != NULL)
1666     {
1667         for(uint32_t i = 0; i < physics->objects_count; i++)
1668         {
1669             btRigidBody *b = physics->bt_body[i];
1670             if(b && b->isInWorld())
1671             {
1672                 bt_engine_dynamicsWorld->removeRigidBody(b);
1673             }
1674 
1675             if(physics->ghost_objects && physics->ghost_objects[i] &&
1676                physics->ghost_objects[i]->getBroadphaseHandle())
1677             {
1678                 bt_engine_dynamicsWorld->removeCollisionObject(physics->ghost_objects[i]);
1679             }
1680         }
1681     }
1682 }
1683 
1684 
Physics_SetBoneCollision(struct physics_data_s * physics,int bone_index,int collision)1685 void Physics_SetBoneCollision(struct physics_data_s *physics, int bone_index, int collision)
1686 {
1687     if(physics->bt_body && (bone_index >= 0) && (bone_index < physics->objects_count))
1688     {
1689         btRigidBody *b = physics->bt_body[bone_index];
1690         physics->bt_info[bone_index].has_collisions = collision;
1691 
1692         if(b && !collision && b->isInWorld())
1693         {
1694             bt_engine_dynamicsWorld->removeRigidBody(b);
1695         }
1696     }
1697 }
1698 
1699 
Physics_SetCollisionGroupAndMask(struct physics_data_s * physics,int16_t group,int16_t mask)1700 void Physics_SetCollisionGroupAndMask(struct physics_data_s *physics, int16_t group, int16_t mask)
1701 {
1702     if(physics->bt_body != NULL)
1703     {
1704         physics->collision_group = (group & (COLLISION_GROUP_STATIC_OBLECT | COLLISION_GROUP_STATIC_ROOM)) ? (btBroadphaseProxy::StaticFilter) : 0x0000;
1705         physics->collision_group |= (group & COLLISION_GROUP_KINEMATIC) ? (btBroadphaseProxy::KinematicFilter) : 0x0000;
1706         physics->collision_group |= (group & (COLLISION_GROUP_CHARACTERS | COLLISION_GROUP_VEHICLE)) ? (btBroadphaseProxy::CharacterFilter) : 0x0000;
1707         physics->collision_group |= (group & COLLISION_GROUP_DYNAMICS) ? (btBroadphaseProxy::DefaultFilter) : 0x0000;
1708 
1709         physics->collision_mask = btBroadphaseProxy::SensorTrigger;
1710         physics->collision_mask |= (mask & (COLLISION_GROUP_STATIC_OBLECT | COLLISION_GROUP_STATIC_ROOM)) ? (btBroadphaseProxy::StaticFilter) : 0x0000;
1711         physics->collision_mask |= (mask & COLLISION_GROUP_KINEMATIC) ? (btBroadphaseProxy::KinematicFilter) : 0x0000;
1712         physics->collision_mask |= (mask & (COLLISION_GROUP_CHARACTERS | COLLISION_GROUP_VEHICLE)) ? (btBroadphaseProxy::CharacterFilter) : 0x0000;
1713         physics->collision_mask |= (mask & COLLISION_GROUP_DYNAMICS) ? (btBroadphaseProxy::DefaultFilter) : 0x0000;
1714         physics->collision_mask = (mask == COLLISION_MASK_ALL) ? (btBroadphaseProxy::AllFilter) : physics->collision_mask;
1715 
1716         for(uint32_t i = 0; i < physics->objects_count; i++)
1717         {
1718             btRigidBody *b = physics->bt_body[i];
1719             if(b && b->getBroadphaseHandle())
1720             {
1721                 b->getBroadphaseHandle()->m_collisionFilterGroup = physics->collision_group;
1722                 b->getBroadphaseHandle()->m_collisionFilterMask = physics->collision_mask;
1723             }
1724         }
1725     }
1726 }
1727 
1728 
Physics_SetCollisionScale(struct physics_data_s * physics,float scaling[3])1729 void Physics_SetCollisionScale(struct physics_data_s *physics, float scaling[3])
1730 {
1731     for(int i = 0; i < physics->objects_count; i++)
1732     {
1733         bt_engine_dynamicsWorld->removeRigidBody(physics->bt_body[i]);
1734             physics->bt_body[i]->getCollisionShape()->setLocalScaling(btVector3(scaling[0], scaling[1], scaling[2]));
1735         bt_engine_dynamicsWorld->addRigidBody(physics->bt_body[i]);
1736 
1737         physics->bt_body[i]->activate();
1738     }
1739 }
1740 
1741 
Physics_SetBodyMass(struct physics_data_s * physics,float mass,uint16_t index)1742 void Physics_SetBodyMass(struct physics_data_s *physics, float mass, uint16_t index)
1743 {
1744     btVector3 inertia (0.0, 0.0, 0.0);
1745     bt_engine_dynamicsWorld->removeRigidBody(physics->bt_body[index]);
1746 
1747         physics->bt_body[index]->getCollisionShape()->calculateLocalInertia(mass, inertia);
1748 
1749         physics->bt_body[index]->setMassProps(mass, inertia);
1750 
1751         physics->bt_body[index]->updateInertiaTensor();
1752         physics->bt_body[index]->clearForces();
1753 
1754         btVector3 factor = (mass > 0.0) ? (btVector3(1.0, 1.0, 1.0)) : (btVector3(0.0, 0.0, 0.0));
1755         physics->bt_body[index]->setLinearFactor (factor);
1756         physics->bt_body[index]->setAngularFactor(factor);
1757 
1758     bt_engine_dynamicsWorld->addRigidBody(physics->bt_body[index]);
1759 
1760     physics->bt_body[index]->activate();
1761 }
1762 
1763 
Physics_PushBody(struct physics_data_s * physics,float speed[3],uint16_t index)1764 void Physics_PushBody(struct physics_data_s *physics, float speed[3], uint16_t index)
1765 {
1766     physics->bt_body[index]->setLinearVelocity(btVector3(speed[0], speed[1], speed[2]));
1767 }
1768 
1769 
Physics_SetLinearFactor(struct physics_data_s * physics,float factor[3],uint16_t index)1770 void Physics_SetLinearFactor(struct physics_data_s *physics, float factor[3], uint16_t index)
1771 {
1772     physics->bt_body[index]->setLinearFactor(btVector3(factor[0], factor[1], factor[2]));
1773 }
1774 
1775 
1776 /* *****************************************************************************
1777  * ************************  HAIR DATA  ****************************************
1778  * ****************************************************************************/
1779 
1780 typedef struct hair_element_s
1781 {
1782     struct base_mesh_s         *mesh;              // Pointer to rendered mesh.
1783     btCollisionShape           *shape;             // Pointer to collision shape.
1784     btRigidBody                *body;              // Pointer to dynamic body.
1785     btGeneric6DofConstraint    *joint;             // Array of joints.
1786 }hair_element_t, *hair_element_p;
1787 
1788 
1789 typedef struct hair_s
1790 {
1791     engine_container_p        container;
1792     uint32_t                  owner_body;         // Owner entity's body ID.
1793 
1794     uint8_t                   root_index;         // Index of "root" element.
1795     uint8_t                   tail_index;         // Index of "tail" element.
1796 
1797     uint8_t                   element_count;      // Overall amount of elements.
1798     hair_element_s           *elements;           // Array of elements.
1799 
1800     uint8_t                   vertex_map_count;
1801     uint32_t                 *hair_vertex_map;    // Hair vertex indices to link
1802     uint32_t                 *head_vertex_map;    // Head vertex indices to link
1803 
1804 }hair_t, *hair_p;
1805 
1806 
Hair_Create(struct hair_setup_s * setup,struct physics_data_s * physics)1807 struct hair_s *Hair_Create(struct hair_setup_s *setup, struct physics_data_s *physics)
1808 {
1809     // No setup or parent to link to - bypass function.
1810 
1811     if(!physics || !setup || (setup->link_body >= physics->objects_count) ||
1812        !physics->bt_body[setup->link_body])
1813     {
1814         return NULL;
1815     }
1816 
1817     skeletal_model_p model = World_GetModelByID(setup->model_id);
1818     if((!model) || (model->mesh_count == 0))
1819     {
1820         return NULL;
1821     }
1822 
1823     // Setup engine container. FIXME: DOESN'T WORK PROPERLY ATM.
1824     struct hair_s *hair = (struct hair_s*)calloc(1, sizeof(struct hair_s));
1825     hair->container = Container_Create();
1826     hair->container->collision_group = COLLISION_GROUP_DYNAMICS_NI;
1827     hair->container->collision_mask = COLLISION_GROUP_STATIC_ROOM | COLLISION_GROUP_STATIC_OBLECT | COLLISION_GROUP_KINEMATIC | COLLISION_GROUP_CHARACTERS;
1828     hair->container->collision_shape = COLLISION_SHAPE_TRIMESH;
1829     hair->container->object_type = OBJECT_HAIR;
1830     hair->container->object = hair;
1831     hair->container->room = physics->cont->room;
1832 
1833     // Setup initial hair parameters.
1834     hair->owner_body = setup->link_body;    // Entity body to refer to.
1835 
1836     // Setup initial position / angles.
1837     btTransform startTransform = physics->bt_body[hair->owner_body]->getWorldTransform();
1838     // Number of elements (bodies) is equal to number of hair meshes.
1839 
1840     hair->element_count = model->mesh_count;
1841     hair->elements      = (hair_element_p)calloc(hair->element_count, sizeof(hair_element_t));
1842 
1843     // Root index should be always zero, as it is how engine determines that it is
1844     // connected to head and renders it properly. Tail index should be always the
1845     // last element of the hair, as it indicates absence of "child" constraint.
1846 
1847     hair->root_index = 0;
1848     hair->tail_index = hair->element_count - 1;
1849 
1850     // Weight step is needed to determine the weight of each hair body.
1851     // It is derived from root body weight and tail body weight.
1852 
1853     btScalar weight_step = ((setup->root_weight - setup->tail_weight) / hair->element_count);
1854     btScalar current_weight = setup->root_weight;
1855 
1856     for(uint32_t i = 0; i < hair->element_count; i++)
1857     {
1858         // Point to corresponding mesh.
1859 
1860         hair->elements[i].mesh = model->mesh_tree[i].mesh_base;
1861 
1862         // Begin creating ACTUAL physical hair mesh.
1863         btVector3   localInertia(0, 0, 0);
1864 
1865         // Make collision shape out of mesh.
1866         hair->elements[i].shape = BT_CSfromMesh(hair->elements[i].mesh, true, true, false);
1867         hair->elements[i].shape->calculateLocalInertia((current_weight * setup->hair_inertia), localInertia);
1868         hair->elements[i].joint = NULL;
1869 
1870         // Decrease next body weight to weight_step parameter.
1871         current_weight -= weight_step;
1872 
1873         // Initialize motion state for body.
1874         btDefaultMotionState* motionState = new btDefaultMotionState(startTransform);
1875 
1876         // Make rigid body.
1877         hair->elements[i].body = new btRigidBody(current_weight, motionState, hair->elements[i].shape, localInertia);
1878 
1879         // Damping makes body stop in space by itself, to prevent it from continous movement.
1880         hair->elements[i].body->setDamping(setup->hair_damping[0], setup->hair_damping[1]);
1881 
1882         // Restitution and friction parameters define "bounciness" and "dullness" of hair.
1883         hair->elements[i].body->setRestitution(setup->hair_restitution);
1884         hair->elements[i].body->setFriction(setup->hair_friction);
1885 
1886         // Since hair is always moving with Lara, even if she's in still state (like, hanging
1887         // on a ledge), hair bodies shouldn't deactivate over time.
1888         hair->elements[i].body->forceActivationState(DISABLE_DEACTIVATION);
1889 
1890         // Hair bodies must not collide with each other, and also collide ONLY with kinematic
1891         // bodies (e. g. animated meshes), or else Lara's ghost object or anything else will be able to
1892         // collide with hair!
1893         hair->elements[i].body->setUserPointer(hair->container);
1894         bt_engine_dynamicsWorld->addRigidBody(hair->elements[i].body, btBroadphaseProxy::DebrisFilter, btBroadphaseProxy::DefaultFilter | btBroadphaseProxy::StaticFilter | btBroadphaseProxy::KinematicFilter | btBroadphaseProxy::CharacterFilter);
1895 
1896         hair->elements[i].body->activate();
1897     }
1898 
1899     // GENERATE CONSTRAINTS.
1900     // All constraints are generic 6-DOF type, as they seem perfect fit for hair.
1901 
1902     // If multiple joints per body is specified, joints are placed in circular manner,
1903     // with obvious step of (SIMD_2_PI) / joint count. It means that all joints will form
1904     // circle-like figure.
1905 
1906     for(uint32_t i = 0; i < hair->element_count; i++)
1907     {
1908         btRigidBody* prev_body;
1909         btScalar     body_length;
1910 
1911         // Each body width and height are used to calculate position of each joint.
1912 
1913         //btScalar body_width = fabs(hair->elements[i].mesh->bb_max[0] - hair->elements[i].mesh->bb_min[0]);
1914         //btScalar body_depth = fabs(hair->elements[i].mesh->bb_max[3] - hair->elements[i].mesh->bb_min[3]);
1915 
1916         btTransform localA; localA.setIdentity();
1917         btTransform localB; localB.setIdentity();
1918 
1919         btScalar joint_x = 0.0;
1920         btScalar joint_y = 0.0;
1921 
1922         if(i == 0)  // First joint group
1923         {
1924             // Adjust pivot point A to parent body.
1925             localA.setOrigin(btVector3(setup->head_offset[0] + joint_x, setup->head_offset[1], setup->head_offset[2] + joint_y));
1926             localA.getBasis().setEulerZYX(setup->root_angle[0], setup->root_angle[1], setup->root_angle[2]);
1927 
1928             localB.setOrigin(btVector3(joint_x, 0.0, joint_y));
1929             localB.getBasis().setEulerZYX(0,-SIMD_HALF_PI,0);
1930 
1931             prev_body = physics->bt_body[hair->owner_body];                     // Previous body is parent body.
1932         }
1933         else
1934         {
1935             // Adjust pivot point A to previous mesh's length, considering mesh overlap multiplier.
1936 
1937             body_length = fabs(hair->elements[i-1].mesh->bb_max[1] - hair->elements[i-1].mesh->bb_min[1]) * setup->joint_overlap;
1938 
1939             localA.setOrigin(btVector3(joint_x, body_length, joint_y));
1940             localA.getBasis().setEulerZYX(0,SIMD_HALF_PI,0);
1941 
1942             // Pivot point B is automatically adjusted by Bullet.
1943 
1944             localB.setOrigin(btVector3(joint_x, 0.0, joint_y));
1945             localB.getBasis().setEulerZYX(0,SIMD_HALF_PI,0);
1946 
1947             prev_body = hair->elements[i-1].body;   // Previous body is preceiding hair mesh.
1948         }
1949 
1950         // Create 6DOF constraint.
1951         hair->elements[i].joint = new btGeneric6DofConstraint(*prev_body, *(hair->elements[i].body), localA, localB, true);
1952 
1953         // CFM and ERP parameters are critical for making joint "hard" and link
1954         // to Lara's head. With wrong values, constraints may become "elastic".
1955         for(int axis = 0; axis <= 5; axis++)
1956         {
1957             hair->elements[i].joint->setParam(BT_CONSTRAINT_STOP_CFM, setup->joint_cfm, axis);
1958             hair->elements[i].joint->setParam(BT_CONSTRAINT_STOP_ERP, setup->joint_erp, axis);
1959         }
1960 
1961         if(i == 0)
1962         {
1963             // First joint group should be more limited in motion, as it is connected
1964             // right to the head. NB: Should we make it scriptable as well?
1965             hair->elements[i].joint->setLinearLowerLimit(btVector3(0., 0., 0.));
1966             hair->elements[i].joint->setLinearUpperLimit(btVector3(0., 0., 0.));
1967             hair->elements[i].joint->setAngularLowerLimit(btVector3(-SIMD_HALF_PI,     0., -SIMD_HALF_PI*0.4));
1968             hair->elements[i].joint->setAngularUpperLimit(btVector3(-SIMD_HALF_PI*0.3, 0.,  SIMD_HALF_PI*0.4));
1969 
1970             // Increased solver iterations make constraint even more stable.
1971             hair->elements[i].joint->setOverrideNumSolverIterations(100);
1972         }
1973         else
1974         {
1975             // Normal joint with more movement freedom.
1976             hair->elements[i].joint->setLinearLowerLimit(btVector3(0., 0., 0.));
1977             hair->elements[i].joint->setLinearUpperLimit(btVector3(0., 0., 0.));
1978             hair->elements[i].joint->setAngularLowerLimit(btVector3(-SIMD_HALF_PI*0.5, 0., -SIMD_HALF_PI*0.5));
1979             hair->elements[i].joint->setAngularUpperLimit(btVector3( SIMD_HALF_PI*0.5, 0.,  SIMD_HALF_PI*0.5));
1980         }
1981         hair->elements[i].joint->setDbgDrawSize(btScalar(5.f));    // Draw constraint axes.
1982 
1983         // Add constraint to the world.
1984         bt_engine_dynamicsWorld->addConstraint(hair->elements[i].joint, true);
1985     }
1986 
1987     return hair;
1988 }
1989 
1990 
Hair_Delete(struct hair_s * hair)1991 void Hair_Delete(struct hair_s *hair)
1992 {
1993     if(hair)
1994     {
1995         for(int i = 0; i < hair->element_count; i++)
1996         {
1997             if(hair->elements[i].joint)
1998             {
1999                 bt_engine_dynamicsWorld->removeConstraint(hair->elements[i].joint);
2000                 delete hair->elements[i].joint;
2001                 hair->elements[i].joint = NULL;
2002             }
2003         }
2004 
2005         for(int i = 0; i < hair->element_count; i++)
2006         {
2007             if(hair->elements[i].body)
2008             {
2009                 hair->elements[i].body->setUserPointer(NULL);
2010                 bt_engine_dynamicsWorld->removeRigidBody(hair->elements[i].body);
2011                 delete hair->elements[i].body;
2012                 hair->elements[i].body = NULL;
2013             }
2014             if(hair->elements[i].shape)
2015             {
2016                 delete hair->elements[i].shape;
2017                 hair->elements[i].shape = NULL;
2018             }
2019         }
2020         free(hair->elements);
2021         hair->elements = NULL;
2022         hair->element_count = 0;
2023 
2024         hair->container = NULL;
2025         hair->owner_body = 0;
2026 
2027         hair->root_index = 0;
2028         hair->tail_index = 0;
2029 
2030         free(hair->container);
2031         hair->container = NULL;
2032 
2033         free(hair);
2034     }
2035 }
2036 
2037 
Hair_Update(struct hair_s * hair,struct physics_data_s * physics)2038 void Hair_Update(struct hair_s *hair, struct physics_data_s *physics)
2039 {
2040     if(hair && (hair->element_count > 0))
2041     {
2042         hair->container->room = physics->cont->room;
2043     }
2044 }
2045 
Hair_GetElementsCount(struct hair_s * hair)2046 int Hair_GetElementsCount(struct hair_s *hair)
2047 {
2048     return (hair)?(hair->element_count):(0);
2049 }
2050 
Hair_GetElementInfo(struct hair_s * hair,int element,struct base_mesh_s ** mesh,float tr[16])2051 void Hair_GetElementInfo(struct hair_s *hair, int element, struct base_mesh_s **mesh, float tr[16])
2052 {
2053     hair->elements[element].body->getWorldTransform().getOpenGLMatrix(tr);
2054     *mesh = hair->elements[element].mesh;
2055 }
2056 
2057 
2058 /* *****************************************************************************
2059  * ************************  RAGDOLL DATA  *************************************
2060  * ****************************************************************************/
2061 
Ragdoll_Create(struct physics_data_s * physics,struct ss_bone_frame_s * bf,struct rd_setup_s * setup)2062 bool Ragdoll_Create(struct physics_data_s *physics, struct ss_bone_frame_s *bf, struct rd_setup_s *setup)
2063 {
2064     // No entity, setup or body count overflow - bypass function.
2065 
2066     if(!physics || !setup || (setup->body_count > physics->objects_count))
2067     {
2068         return false;
2069     }
2070 
2071     bool result = true;
2072 
2073     // If ragdoll already exists, overwrite it with new one.
2074 
2075     if(physics->bt_joint_count > 0)
2076     {
2077         result = Ragdoll_Delete(physics);
2078     }
2079 
2080     // Setup bodies.
2081     physics->bt_joint_count = 0;
2082     // update current character animation and full fix body to avoid starting ragdoll partially inside the wall or floor...
2083     for(uint32_t i = 0; i < setup->body_count; i++)
2084     {
2085         if(physics->bt_body[i] == NULL)
2086         {
2087             result = false;
2088             continue;   // If body is absent, return false and bypass this body setup.
2089         }
2090 
2091         btVector3 inertia (0.0, 0.0, 0.0);
2092         btScalar  mass = setup->body_setup[i].mass;
2093 
2094         if(physics->bt_body[i]->isInWorld())
2095         {
2096             bt_engine_dynamicsWorld->removeRigidBody(physics->bt_body[i]);
2097         }
2098         physics->bt_body[i]->getCollisionShape()->calculateLocalInertia(mass, inertia);
2099         physics->bt_body[i]->setMassProps(mass, inertia);
2100 
2101         physics->bt_body[i]->updateInertiaTensor();
2102         physics->bt_body[i]->clearForces();
2103 
2104         physics->bt_body[i]->setLinearFactor (btVector3(1.0, 1.0, 1.0));
2105         physics->bt_body[i]->setAngularFactor(btVector3(1.0, 1.0, 1.0));
2106 
2107         physics->bt_body[i]->setDamping(setup->body_setup[i].damping[0], setup->body_setup[i].damping[1]);
2108         physics->bt_body[i]->setRestitution(setup->body_setup[i].restitution);
2109         physics->bt_body[i]->setFriction(setup->body_setup[i].friction);
2110         physics->bt_body[i]->setSleepingThresholds(RD_DEFAULT_SLEEPING_THRESHOLD, RD_DEFAULT_SLEEPING_THRESHOLD);
2111 
2112         if(bf->bone_tags[i].parent == NULL)
2113         {
2114             btScalar r = getInnerBBRadius(bf->bone_tags[i].mesh_base->bb_min, bf->bone_tags[i].mesh_base->bb_max);
2115             physics->bt_body[i]->setCcdMotionThreshold(0.8 * r);
2116             physics->bt_body[i]->setCcdSweptSphereRadius(r);
2117         }
2118     }
2119 
2120     for(uint32_t i = 0; i < setup->body_count; i++)
2121     {
2122         bt_engine_dynamicsWorld->addRigidBody(physics->bt_body[i], btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::StaticFilter | btBroadphaseProxy::KinematicFilter);
2123         physics->bt_body[i]->activate();
2124         physics->bt_body[i]->setLinearVelocity(btVector3(0.0, 0.0, 0.0));
2125     }
2126 
2127     // Setup constraints.
2128     physics->bt_joint_count = setup->joint_count;
2129     physics->bt_joints = (btTypedConstraint**)calloc(physics->bt_joint_count, sizeof(btTypedConstraint*));
2130 
2131     for(int i = 0; i < physics->bt_joint_count; i++)
2132     {
2133         if( (setup->joint_setup[i].body_index >= setup->body_count) ||
2134             (physics->bt_body[setup->joint_setup[i].body_index] == NULL) )
2135         {
2136             result = false;
2137             break;       // If body 1 or body 2 are absent, return false and bypass this joint.
2138         }
2139 
2140         btTransform localA, localB;
2141         ss_bone_tag_p btB = bf->bone_tags + setup->joint_setup[i].body_index;
2142         ss_bone_tag_p btA = btB->parent;
2143         if(btA == NULL)
2144         {
2145             result = false;
2146             break;
2147         }
2148 #if 0
2149         localA.setFromOpenGLMatrix(btB->transform);
2150         localB.setIdentity();
2151 #else
2152         localA.getBasis().setEulerZYX(setup->joint_setup[i].body1_angle[0], setup->joint_setup[i].body1_angle[1], setup->joint_setup[i].body1_angle[2]);
2153         //localA.setOrigin(setup->joint_setup[i].body1_offset);
2154         localA.setOrigin(btVector3(btB->transform[12+0], btB->transform[12+1], btB->transform[12+2]));
2155 
2156         localB.getBasis().setEulerZYX(setup->joint_setup[i].body2_angle[0], setup->joint_setup[i].body2_angle[1], setup->joint_setup[i].body2_angle[2]);
2157         //localB.setOrigin(setup->joint_setup[i].body2_offset);
2158         localB.setOrigin(btVector3(0.0, 0.0, 0.0));
2159 #endif
2160 
2161         switch(setup->joint_setup[i].joint_type)
2162         {
2163             case RD_CONSTRAINT_POINT:
2164                 {
2165                     btPoint2PointConstraint* pointC = new btPoint2PointConstraint(*physics->bt_body[btA->index], *physics->bt_body[btB->index], localA.getOrigin(), localB.getOrigin());
2166                     physics->bt_joints[i] = pointC;
2167                 }
2168                 break;
2169 
2170             case RD_CONSTRAINT_HINGE:
2171                 {
2172                     btHingeConstraint* hingeC = new btHingeConstraint(*physics->bt_body[btA->index], *physics->bt_body[btB->index], localA, localB);
2173                     hingeC->setLimit(setup->joint_setup[i].joint_limit[0], setup->joint_setup[i].joint_limit[1], 0.9, 0.3, 0.3);
2174                     physics->bt_joints[i] = hingeC;
2175                 }
2176                 break;
2177 
2178             case RD_CONSTRAINT_CONE:
2179                 {
2180                     btConeTwistConstraint* coneC = new btConeTwistConstraint(*physics->bt_body[btA->index], *physics->bt_body[btB->index], localA, localB);
2181                     coneC->setLimit(setup->joint_setup[i].joint_limit[0], setup->joint_setup[i].joint_limit[1], setup->joint_setup[i].joint_limit[2], 0.9, 0.3, 0.7);
2182                     physics->bt_joints[i] = coneC;
2183                 }
2184                 break;
2185         }
2186 
2187         physics->bt_joints[i]->setParam(BT_CONSTRAINT_STOP_CFM, setup->joint_cfm, -1);
2188         physics->bt_joints[i]->setParam(BT_CONSTRAINT_STOP_ERP, setup->joint_erp, -1);
2189 
2190         physics->bt_joints[i]->setDbgDrawSize(64.0);
2191         bt_engine_dynamicsWorld->addConstraint(physics->bt_joints[i], true);
2192     }
2193 
2194     if(result == false)
2195     {
2196         Ragdoll_Delete(physics);  // PARANOID: Clean up the mess, if something went wrong.
2197     }
2198 
2199     physics->cont->collision_group = COLLISION_GROUP_DYNAMICS_NI;
2200 
2201     return result;
2202 }
2203 
2204 
Ragdoll_Delete(struct physics_data_s * physics)2205 bool Ragdoll_Delete(struct physics_data_s *physics)
2206 {
2207     if(physics->bt_joint_count == 0)
2208     {
2209         return false;
2210     }
2211 
2212     for(uint32_t i = 0; i < physics->bt_joint_count; i++)
2213     {
2214         if(physics->bt_joints[i])
2215         {
2216             bt_engine_dynamicsWorld->removeConstraint(physics->bt_joints[i]);
2217             delete physics->bt_joints[i];
2218             physics->bt_joints[i] = NULL;
2219         }
2220     }
2221 
2222     for(uint32_t i = 0; i < physics->objects_count; i++)
2223     {
2224         if(physics->bt_body[i]->isInWorld())
2225         {
2226             bt_engine_dynamicsWorld->removeRigidBody(physics->bt_body[i]);
2227         }
2228         physics->bt_body[i]->setMassProps(0, btVector3(0.0, 0.0, 0.0));
2229         bt_engine_dynamicsWorld->addRigidBody(physics->bt_body[i], btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::AllFilter);
2230     }
2231 
2232     free(physics->bt_joints);
2233     physics->bt_joints = NULL;
2234     physics->bt_joint_count = 0;
2235     physics->cont->collision_group = COLLISION_GROUP_CHARACTERS;
2236 
2237     return true;
2238 
2239     // NB! Bodies remain in the same state!
2240     // To make them static again, additionally call setEntityBodyMass script function.
2241 }
2242