source: trunk/test/Physics/Include/BulletCharacterController.h @ 1834

Last change on this file since 1834 was 1834, checked in by touky, 7 years ago

small tweak on BtPhysTest. does not work better.

File size: 9.8 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
5//            (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com>
6//   This program is free software; you can redistribute it and/or
7//   modify it under the terms of the Do What The Fuck You Want To
8//   Public License, Version 2, as published by Sam Hocevar. See
9//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
10//
11
12//
13// The BulletCharacterController class
14// ------------------
15// This class is a equivalent of btKinematicCharacterController, but more useful for Lol.
16//
17
18#if !defined __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__
19#define __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__
20
21#ifdef HAVE_PHYS_USE_BULLET
22#include "core.h"
23#include "EasyPhysics.h"
24//#include "BulletDynamics\Character\btCharacterControllerInterface.h"
25#endif
26
27#define USE_LOL_CTRLR_CHARAC
28
29namespace lol
30{
31
32        namespace phys
33        {
34
35#ifdef USE_LOL_CTRLR_CHARAC
36#ifdef HAVE_PHYS_USE_BULLET
37
38        //SweepCallback used for Swweep Tests.
39        class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
40        {
41        public:
42                ClosestNotMeConvexResultCallback(btCollisionObject* NewMe, const vec3& NewUp, float MinSlopeDot) :
43                                                btCollisionWorld::ClosestConvexResultCallback(LOL2BTU_VEC3(vec3(.0f)), LOL2BTU_VEC3(vec3(.0f))),
44                                                m_me(NewMe),
45                                                m_up(NewUp),
46                                                m_min_slope_dot(MinSlopeDot) { }
47
48                virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& ConvexResult, bool NormalInWorld)
49                {
50                        //We hit ourselves, FAIL
51                        if (ConvexResult.m_hitCollisionObject == m_me)
52                                return btScalar(1.f);
53
54                        vec3 WorldHitNomal(.0f);
55                        if (NormalInWorld)
56                                WorldHitNomal = BT2LOL_VEC3(ConvexResult.m_hitNormalLocal);
57                        else //need to transform Normal into worldspace
58                        {
59                                btVector3 TmpWorldHitNormal = ConvexResult.m_hitCollisionObject->getWorldTransform().getBasis() * ConvexResult.m_hitNormalLocal;
60                                WorldHitNomal = BT2LOL_VEC3(TmpWorldHitNormal);
61                        }
62
63                        float DotUp = dot(m_up, WorldHitNomal);
64                        //We hit below the accepted slope_dot, FAIL
65                        if (DotUp < m_min_slope_dot)
66                                return btScalar(1.f);
67
68                        //Continue to next.
69                        return ClosestConvexResultCallback::addSingleResult(ConvexResult, NormalInWorld);
70                }
71        protected:
72                btCollisionObject*      m_me;
73                const vec3                      m_up;
74                float                           m_min_slope_dot;
75        };
76
77                ///BulletKinematicCharacterController is an object that supports a sliding motion in a world.
78                ///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
79                ///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
80                class BulletKinematicCharacterController : public btActionInterface
81                {
82                public:
83                        BulletKinematicCharacterController(btPairCachingGhostObject* NewGhostObject, btConvexShape* NewConvexShape, float NewStepHeight, int NewUpAxis=1)
84                        {
85                                m_convex_shape = NewConvexShape;       
86                                m_i_up_axis = NewUpAxis;
87                                m_ghost_object = NewGhostObject;
88                                m_step_height = NewStepHeight;
89
90                                m_added_margin = 0.02f;
91                                m_walk_direction = vec3(.0f, .0f, .0f);
92                                m_do_gobject_sweep_test = true;
93                                m_turn_angle = .0f;
94                                m_use_walk_direction = false; // Should remove walk direction, this doesn't work correctly.
95                                m_velocity_time_interval = .0f;
96                                m_vertical_velocity = .0f;
97                                m_vertical_offset = .0f;
98                                m_f_gravity = 9.8f * 3.f; // 3G acceleration.
99                                m_fall_speed = 55.f; // Terminal velocity of a sky diver in m/s.
100                                m_jump_speed = 10.f; // ?
101                                m_was_on_ground = false;
102                                m_was_jumping = false;
103                                SetMaxSlope(45.f);
104                        }
105                        ~BulletKinematicCharacterController() { }
106
107                protected:
108
109                        static vec3* GetUpAxisDirections()
110                        {
111                                static vec3 sUpAxisDirection[3] = { vec3(1.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f) };
112       
113                                return sUpAxisDirection;
114                        }
115
116                        //--------------------------
117                        //CONVENIENCE FUNCTIONS
118                        //--
119
120                        //Returns the reflection Direction of a ray going 'Direction' hitting a surface with Normal 'Normal' from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
121                        vec3 GetReflectedDir(const vec3& Direction, const vec3& Normal)
122                        {
123                                return Direction - (2.f * dot(Direction, Normal) * Normal);
124                        }
125                        //Returns the portion of 'direction' that is parallel to 'normal'
126                        vec3 ProjectDirOnNorm(const vec3& Direction, const vec3& Normal)
127                        {
128                                return Normal * dot(Direction, Normal);
129                        }
130                        //Returns the portion of 'Direction' that is perpindicular to 'Normal'
131                        vec3 ProjectDirOnNormPerpindicular(const vec3& Direction, const vec3& Normal)
132                        {
133                                return Direction - ProjectDirOnNorm(Direction, Normal);
134                        }
135                        //Returns Ghost Object. -duh-
136                        btPairCachingGhostObject* GetGhostObject()
137                        {
138                                return m_ghost_object;
139                        }
140
141                        //"Real" war functions
142                        bool RecoverFromPenetration(btCollisionWorld* CollisionWorld);
143                        void UpdateTargetOnHit(const vec3& hit_normal, float TangentMag = .0f, float NormalMag = 1.f);
144                        void DoMove(btCollisionWorld* CollisionWorld, const vec3& MoveStep, float DeltaTime);
145
146                public:
147                        ///btActionInterface interface : KEEP IN camelCase
148                        virtual void updateAction(btCollisionWorld* CollisionWorld, float deltaTime)
149                        {
150                                PreStep(CollisionWorld);
151                                PlayerStep(CollisionWorld, deltaTime);
152                        }
153
154                        //not in the interface, but called above
155                        void PreStep(btCollisionWorld* CollisionWorld);
156                        void PlayerStep(btCollisionWorld* CollisionWorld, float DeltaTime);
157
158                        ///btActionInterface interface : KEEP IN camelCase
159                        void debugDraw(btIDebugDraw* debugDrawer) { }
160                       
161                        void SetUpAxis(int NewAxis)
162                        {
163                                if (NewAxis < 0)
164                                        NewAxis = 0;
165                                if (NewAxis > 2)
166                                        NewAxis = 2;
167                                m_i_up_axis = NewAxis;
168                        }
169
170                        //!!!!!! SHOULD DITCH THAT !!!!!!
171                        //This should probably be called setPositionIncrementPerSimulatorStep.
172                        //This is neither a Direction nor a velocity, but the amount to
173                        //increment the position each simulation iteration, regardless
174                        //of DeltaTime.
175                        //This call will Reset any velocity set by SetVelocityForTimeInterval().
176                        virtual void SetWalkDirection(const vec3& walkDirection)
177                        {
178                                m_use_walk_direction = true;
179                                m_walk_direction = walkDirection;
180                                m_normalized_direction = normalize(m_walk_direction);
181                        }
182
183                        //Caller provides a velocity with which the character should MoveStep for
184                        //the given time period.  After the time period, velocity is Reset
185                        //to zero.
186                        //This call will Reset any walk Direction set by SetWalkDirection().
187                        //Negative time intervals will result in no motion.
188                        virtual void SetVelocityForTimeInterval(const vec3& velocity, float timeInterval)
189                        {
190                                m_use_walk_direction = false;
191                                m_walk_direction = velocity;
192                                m_normalized_direction = normalize(m_walk_direction);
193                                m_velocity_time_interval = timeInterval;
194                        }
195
196                        //Usefulness ?
197                        void Reset() { }
198                        void Warp(const vec3& NewOrigin)
199                        {
200                                btTransform NewTransform;
201                                NewTransform.setIdentity();
202                                NewTransform.setOrigin(LOL2BTU_VEC3(NewOrigin));
203                                m_ghost_object->setWorldTransform(NewTransform);
204                        }
205
206                        //External Setup
207                        //--
208
209                        void SetFallSpeed(float NewFallSpeed)                   { m_fall_speed = NewFallSpeed; }
210                        void SetJumpSpeed(float NewJumpSpeed)                   { m_jump_speed = NewJumpSpeed; }
211                        void SetMaxJumpHeight(float NewMaxJumpHeight)   { m_max_jump_height = NewMaxJumpHeight; }
212
213                        //Jump logic will go in EasyCC
214                        bool CanJump() const                                                    { return OnGround(); }
215                        void Jump();
216
217                        //NewGravity functions
218                        void SetGravity(float NewGravity)                               { m_f_gravity = NewGravity; }
219                        float GetGravity() const                                                { return m_f_gravity; }
220
221                        //The max slope determines the maximum angle that the controller can walk up.
222                        //The slope angle is measured in radians.
223                        void SetMaxSlope(float NewSlopeRadians)                 { m_max_slope_radians = NewSlopeRadians; m_max_slope_cosine = lol::cos(NewSlopeRadians); }
224                        float GetMaxSlope() const                                               { return m_max_slope_radians; }
225
226                        void SetUseGhostSweepTest(bool UseGObjectSweepTest) { m_do_gobject_sweep_test = UseGObjectSweepTest; }
227
228                        bool OnGround() const                                                   { return m_vertical_velocity == .0f && m_vertical_offset == .0f; }
229
230                private:
231
232                        btPairCachingGhostObject*       m_ghost_object;
233                        btConvexShape*                          m_convex_shape; //is also in m_ghost_object, but it needs to be convex, so we store it here to avoid upcast
234
235                        //keep track of the contact manifolds
236                        btManifoldArray                         m_manifold_array;
237
238                        float                                           m_half_height;
239                        float                                           m_velocity_time_interval;
240                        float                                           m_vertical_velocity;
241                        float                                           m_vertical_offset;
242                        float                                           m_fall_speed;
243                        float                                           m_jump_speed;
244                        float                                           m_max_jump_height;
245                        float                                           m_max_slope_radians; // Slope angle that is set (used for returning the exact value)
246                        float                                           m_max_slope_cosine;  // Cosine equivalent of m_max_slope_radians (calculated once when set, for optimization)
247                        float                                           m_f_gravity;
248                        float                                           m_turn_angle;
249                        float                                           m_step_height;
250                        float                                           m_added_margin;//@todo: remove this and fix the code
251
252                        ///this is the desired walk Direction, set by the user
253                        vec3                                            m_walk_direction;
254                        vec3                                            m_normalized_direction;
255
256                        //some internal variables
257                        vec3                                            m_current_position;
258                        float                                           m_current_step_offset;
259                        vec3                                            m_target_position;
260
261                        vec3                                            m_touching_normal;
262                        bool                                            m_touching_contact;
263
264                        bool                                            m_was_on_ground;
265                        bool                                            m_was_jumping;
266                        bool                                            m_do_gobject_sweep_test;
267                        bool                                            m_use_walk_direction;
268                        int                                                     m_i_up_axis;
269
270                        //---------------------------------------------------------------------
271                        //NEW INTERNAL VARS
272                        //---------------------------------------------------------------------
273
274                        //Gravity in vec3
275                        vec3                                            m_gravity;
276
277                        //Current Velocity
278                        vec3                                            m_velocity;
279                };
280
281#endif // HAVE_PHYS_USE_BULLET
282#endif // USE_LOL_CTRLR_CHARAC
283
284        } /* namespace phys */
285
286} /* namespace lol */
287
288#endif /* __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__ */
289
Note: See TracBrowser for help on using the repository browser.