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

Last change on this file since 1768 was 1768, checked in by touky, 8 years ago

Added Attachment/base logic with working attachment with EasyCharacterController.
Added RayCastResult & a naïve integration for EasyCharacterController.
Enjoy !

File size: 9.7 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        //Reap-Off of the btKinematicClosestNotMeRayResultCallback
122        class LolClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
123        {
124        public:
125                LolClosestNotMeRayResultCallback(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 LolClosestNotMeRayResultCallback(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        friend class EasyPhysic;
324        friend class EasyConstraint;
325
326        //Adds the given EasyPhysic to the correct list.
327        void AddToDynamic(EasyPhysic* NewEPDynamic)     { m_dynamic_list << NewEPDynamic; }
328        void AddToStatic(EasyPhysic* NewEPStatic)       { m_static_list << NewEPStatic; }
329        void AddToGhost(EasyPhysic* NewEPGhost)         { m_ghost_list << NewEPGhost; }
330        void AddToConstraint(EasyConstraint* NewEC)     { m_constraint_list     << NewEC; }
331
332        //Easy Physics body List
333        Array<EasyPhysic*>                                              m_dynamic_list;
334        Array<EasyPhysic*>                                              m_static_list;
335        Array<EasyPhysic*>                                              m_ghost_list;
336        Array<EasyConstraint*>                                  m_constraint_list;
337
338        //Easy Physics data storage
339        float                                                                   m_timestep;
340        bool                                                                    m_using_CCD;
341        vec3                                                                    m_gravity;
342        vec3                                                                    m_world_min;
343        vec3                                                                    m_world_max;
344};
345
346} /* namespace phys */
347
348} /* namespace lol */
349
350#endif // __LOLPHYSICS_H__
351
Note: See TracBrowser for help on using the repository browser.