source: trunk/test/Physics/Include/LolPhysics.h @ 1888

Last change on this file since 1888 was 1888, checked in by lolbot, 8 years ago

fixed 23 files out of 277:

  • fixed 1270 CR characters
  • fixed 56 trailing spaces
  • fixed 5085 tabs
File size: 13.2 KB
Line 
1//
2// LolPhysics
3//
4// Copyright: (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com>
5//            (c) 2012 Sam Hocevar <sam@hocevar.net>
6//
7
8#if !defined __LOLPHYSICS_H__
9#define __LOLPHYSICS_H__
10
11#ifdef HAVE_PHYS_USE_BULLET
12#include <cstring>
13#include <bullet/btBulletDynamicsCommon.h>
14#include <bullet/btBulletCollisionCommon.h>
15#include <BulletDynamics/Character/btKinematicCharacterController.h>
16#include "LolBtPhysicsIntegration.h"
17#include "EasyPhysics.h"
18#include "EasyConstraint.h"
19#endif
20
21namespace lol
22{
23
24namespace phys
25{
26
27enum eRaycastType
28{
29    ERT_Closest,
30    ERT_AllHit,
31    ERT_AnyHit, //Will stop at the first hit. Hit data are supposed to be irrelevant
32
33    ERT_MAX
34};
35
36struct RayCastResult
37{
38    RayCastResult(int CollisionFilterGroup=1, int CollisionFilterMask=(0xFF))
39    {
40        memset(this, 0, sizeof(RayCastResult));
41
42        m_collision_filter_group = CollisionFilterGroup;
43        m_collision_filter_mask = CollisionFilterMask;
44    }
45    void Reset()
46    {
47        m_collider_list.Empty();
48        m_hit_normal_list.Empty();
49        m_hit_point_list.Empty();
50        m_hit_fraction_list.Empty();
51    }
52
53    Array<EasyPhysic*>        m_collider_list;
54    Array<vec3>                m_hit_normal_list;
55    Array<vec3>                m_hit_point_list;
56    Array<float>            m_hit_fraction_list;
57
58    short int                m_collision_filter_group;
59    short int                 m_collision_filter_mask;
60    unsigned int             m_flags; //???
61};
62
63class Simulation : public Entity
64{
65public:
66    Simulation() :
67        m_broadphase(0),
68        m_collision_configuration(0),
69        m_dispatcher(0),
70        m_solver(0),
71        m_dynamics_world(0),
72        m_timestep(1.f/60.f)
73    {
74        m_gamegroup = GAMEGROUP_SIMULATION;
75    }
76    ~Simulation()
77    {
78        Exit();
79    }
80
81    char const *GetName() { return "<Simulation>"; }
82
83#ifdef HAVE_PHYS_USE_BULLET
84public:
85    void Init()
86    {
87        // Build the broadphase
88        if (1)
89        {
90            m_Sweep_broadphase = new btAxisSweep3(LOL2BT_VEC3(m_world_min), LOL2BT_VEC3(m_world_max));
91            m_Sweep_broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
92            m_broadphase = m_Sweep_broadphase;
93        }
94        else
95            m_broadphase = new btDbvtBroadphase();
96
97        // Set up the collision configuration and dispatcher
98        m_collision_configuration = new btDefaultCollisionConfiguration();
99        m_dispatcher = new btCollisionDispatcher(m_collision_configuration);
100
101        // The actual physics solver
102        m_solver = new btSequentialImpulseConstraintSolver;
103
104        // The world.
105        m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collision_configuration);
106    }
107
108    virtual void TickGame(float seconds)
109    {
110        Entity::TickGame(seconds);
111
112        //step the simulation
113        if (m_dynamics_world)
114        {
115            //the "+1" is to have at least one Timestep and to ensure float to int .5f conversion.
116            int steps = (int)(seconds / m_timestep) + 1;
117            m_dynamics_world->stepSimulation(seconds, steps, m_timestep);
118        }
119    }
120
121    //Rip-Off of the btKinematicClosestNotMeRayResultCallback
122    class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
123    {
124    public:
125        ClosestNotMeRayResultCallback(btCollisionObject* Me, const btVector3& rayFromWorld, const btVector3& rayToWorld) :
126          btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld)
127        {
128            m_me = Me;
129        }
130
131        virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
132        {
133            if (rayResult.m_collisionObject == m_me)
134                return 1.0;
135
136            return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
137        }
138    protected:
139        btCollisionObject* m_me;
140    };
141
142    //Will stop at the first hit. Hit data are supposed to be irrelevant
143    class AnyHitRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
144    {
145    public:
146        AnyHitRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld) :
147          btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld)
148        {
149        }
150
151        virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
152        {
153            return .0f;
154        }
155    };
156
157    //Returns true when hitting something. If SourceCaster is set, it will be ignored by Raycast.
158    bool RayHits(RayCastResult& HitResult, eRaycastType RaycastType, const vec3& RayFrom, const vec3& RayTo, EasyPhysic* SourceCaster=NULL)
159    {
160        bool bResult = false;
161
162        btCollisionWorld::RayResultCallback* BtRayResult = NULL;
163        btCollisionWorld::ClosestRayResultCallback* BtRayResult_Closest;
164        btCollisionWorld::AllHitsRayResultCallback* BtRayResult_AllHits;
165
166        switch (RaycastType)
167        {
168            case ERT_Closest:
169            {
170                if (SourceCaster)
171                    BtRayResult_Closest = new ClosestNotMeRayResultCallback(SourceCaster->m_collision_object, LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo));
172                else
173                    BtRayResult_Closest = new btCollisionWorld::ClosestRayResultCallback(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo));
174                BtRayResult = BtRayResult_Closest;
175                break;
176            }
177            case ERT_AllHit:
178            {
179                BtRayResult_AllHits = new btCollisionWorld::AllHitsRayResultCallback(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo));
180                BtRayResult = BtRayResult_AllHits;
181                break;
182            }
183            case ERT_AnyHit:
184            {
185                BtRayResult_Closest = new AnyHitRayResultCallback(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo));
186                BtRayResult = BtRayResult_Closest;
187                break;
188            }
189        }
190
191        m_dynamics_world->rayTest(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo), *BtRayResult);
192        if (BtRayResult->hasHit())
193        {
194            bResult = true;
195
196            switch (RaycastType)
197            {
198                case ERT_Closest:
199                {
200                    HitResult.m_collider_list        << (EasyPhysic*)BtRayResult_Closest->m_collisionObject->getUserPointer();
201                    HitResult.m_hit_normal_list        << BT2LOLU_VEC3(BtRayResult_Closest->m_hitNormalWorld);
202                    HitResult.m_hit_point_list        << BT2LOLU_VEC3(BtRayResult_Closest->m_hitPointWorld);
203                    HitResult.m_hit_fraction_list    << BtRayResult_Closest->m_closestHitFraction;
204                    break;
205                }
206                case ERT_AllHit:
207                {
208                    for (int i = 0; i < BtRayResult_AllHits->m_collisionObjects.size(); i++)
209                    {
210                        HitResult.m_collider_list        << (EasyPhysic*)BtRayResult_AllHits->m_collisionObjects[i]->getUserPointer();
211                        HitResult.m_hit_normal_list        << BT2LOLU_VEC3(BtRayResult_AllHits->m_hitNormalWorld[i]);
212                        HitResult.m_hit_point_list        << BT2LOLU_VEC3(BtRayResult_AllHits->m_hitPointWorld[i]);
213                        HitResult.m_hit_fraction_list    << BtRayResult_AllHits->m_hitFractions[i];
214                    }
215                    break;
216                }
217            }
218        }
219
220        delete BtRayResult;
221
222        return bResult;
223    }
224
225
226    void Exit()
227    {
228        delete m_dynamics_world;
229        delete m_solver;
230        delete m_dispatcher;
231        delete m_collision_configuration;
232        delete m_broadphase;
233    }
234
235    btDiscreteDynamicsWorld* GetWorld()
236    {
237        return m_dynamics_world;
238    }
239
240private:
241    void CustomSetContinuousDetection(bool ShouldUseCCD)
242    {
243        if (m_dynamics_world)
244            m_dynamics_world->getDispatchInfo().m_useContinuous = ShouldUseCCD;
245    }
246
247    void CustomSetGravity(vec3 &NewGravity)
248    {
249        if (m_dynamics_world)
250            m_dynamics_world->setGravity(LOL2BT_VEC3(NewGravity * LOL2BT_UNIT));
251    }
252
253    void CustomSetWorldLimit(vec3 const &NewWorldMin, vec3 const &NewWorldMax)
254    {
255    }
256
257    void CustomSetTimestep(float NewTimestep) { }
258
259    //broadphase
260    btBroadphaseInterface*                    m_broadphase;
261    btAxisSweep3*                            m_Sweep_broadphase;
262    // Set up the collision configuration and dispatc
263    btDefaultCollisionConfiguration*        m_collision_configuration;
264    btCollisionDispatcher*                    m_dispatcher;
265    // The actual physics solver
266    btSequentialImpulseConstraintSolver*    m_solver;
267    // The world.
268    btDiscreteDynamicsWorld*                m_dynamics_world;
269
270#else  // NO PHYSIC IMPLEMENTATION
271
272public:
273    void Init() { }
274    void TickGame(float seconds) { }
275    bool RayHits(RayCastResult& HitResult, eRaycastType RaycastType, const vec3& RayFrom, const vec3& RayTo, EasyPhysic* SourceCaster=NULL) { return false; }
276    void Exit() { }
277private:
278    void CustomSetContinuousDetection(bool ShouldUseCCD) { }
279    void CustomSetGravity(vec3 &NewGravity) { }
280    void CustomSetWorldLimit(vec3 &NewWorldMin, vec3 &NewWorldMax) { }
281    void CustomSetTimestep(float NewTimestep) { }
282
283#endif // PHYSIC IMPLEMENTATION
284
285public:
286    //Main logic :
287    //The Set*() functions do the all-lib-independent data storage.
288    //And then it calls the CustomSet*() which are the specialized versions.
289
290    //Sets the continuous collision detection flag.
291    void SetContinuousDetection(bool ShouldUseCCD)
292    {
293        m_using_CCD = ShouldUseCCD;
294        CustomSetContinuousDetection(ShouldUseCCD);
295    }
296
297    //Sets the simulation gravity.
298    void SetGravity(vec3 &NewGravity)
299    {
300        m_gravity = NewGravity;
301        CustomSetGravity(NewGravity);
302    }
303
304    //Sets the simulation gravity.
305    void SetWorldLimit(vec3 const &NewWorldMin, vec3 const &NewWorldMax)
306    {
307        m_world_min = NewWorldMin;
308        m_world_max = NewWorldMax;
309        CustomSetWorldLimit(NewWorldMin, NewWorldMax);
310    }
311
312    //Sets the simulation fixed timestep.
313    void SetTimestep(float NewTimestep)
314    {
315        if (NewTimestep > .0f)
316        {
317            m_timestep = NewTimestep;
318            CustomSetTimestep(NewTimestep);
319        }
320    }
321
322private:
323
324    friend class EasyPhysic;
325    friend class EasyCharacterController;
326    friend class EasyConstraint;
327
328    enum eEasyPhysicType
329    {
330        EEPT_Dynamic,
331        EEPT_Static,
332        EEPT_Ghost,
333        EEPT_CollisionObject,
334        EEPT_CharacterController,
335
336        EEPT_MAX
337    };
338
339    //m_owner_simulation
340    //Adds the given EasyPhysic to the correct list.
341    void ObjectRegistration(bool AddObject, EasyPhysic* NewEP, eEasyPhysicType CurType)
342    {
343        Array<EasyPhysic*>* SearchList = NULL;
344        switch(CurType)
345        {
346            case EEPT_Dynamic:
347            {
348                SearchList = &m_dynamic_list;
349                break;
350            }
351            case EEPT_Static:
352            {
353                SearchList = &m_static_list;
354                break;
355            }
356            case EEPT_Ghost:
357            {
358                SearchList = &m_ghost_list;
359                break;
360            }
361            case EEPT_CollisionObject:
362            {
363                SearchList = &m_collision_object_list;
364                break;
365            }
366            case EEPT_CharacterController:
367            {
368                SearchList = &m_character_controller_list;
369                break;
370            }
371        }
372
373        if (AddObject)
374        {
375            NewEP->m_owner_simulation = this;
376            (*SearchList) << NewEP;
377        }
378        else
379        {
380            NewEP->m_owner_simulation = NULL;
381            for (int i = 0; i < SearchList->Count(); ++i)
382            {
383                if ((*SearchList)[i] == NewEP)
384                {
385                    SearchList->Remove(i--);
386                    break;
387                }
388            }
389        }
390    }
391    void ObjectRegistration(bool AddObject, EasyConstraint* NewEC)
392    {
393        Array<EasyConstraint*>* SearchList = NULL;
394        SearchList = &m_constraint_list;
395
396        if (AddObject)
397        {
398            NewEC->m_owner_simulation = this;
399            (*SearchList) << NewEC;
400        }
401        else
402        {
403            NewEC->m_owner_simulation = NULL;
404            for (int i = 0; i < SearchList->Count(); ++i)
405            {
406                if ((*SearchList)[i] == NewEC)
407                {
408                    SearchList->Remove(i--);
409                    break;
410                }
411            }
412        }
413    }
414
415    //Easy Physics body List
416    Array<EasyPhysic*>                        m_dynamic_list;
417    Array<EasyPhysic*>                        m_static_list;
418    Array<EasyPhysic*>                        m_ghost_list;
419    Array<EasyPhysic*>                        m_collision_object_list;
420    Array<EasyPhysic*>                        m_character_controller_list;
421    Array<EasyConstraint*>                    m_constraint_list;
422
423    //Easy Physics data storage
424    float                                    m_timestep;
425    bool                                    m_using_CCD;
426    vec3                                    m_gravity;
427    vec3                                    m_world_min;
428    vec3                                    m_world_max;
429};
430
431} /* namespace phys */
432
433} /* namespace lol */
434
435#endif // __LOLPHYSICS_H__
436
Note: See TracBrowser for help on using the repository browser.