Changeset 1798


Ignore:
Timestamp:
Aug 23, 2012, 5:26:50 PM (11 years ago)
Author:
touky
Message:

Added BulletCharacter Dummy code.

Location:
trunk/test/Physics
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/test/Physics/Include/BulletCharacterController.h

    r1795 r1798  
    2222#include "core.h"
    2323#include "EasyPhysics.h"
     24//#include "BulletDynamics\Character\btCharacterControllerInterface.h"
    2425#endif
    2526
     
    3031        {
    3132
     33#define 0
     34#ifdef HAVE_PHYS_USE_BULLET
     35
     36                ///BulletKinematicCharacterController is an object that supports a sliding motion in a world.
     37                ///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.
     38                ///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
     39                class BulletKinematicCharacterController : public btCharacterControllerInterface
     40                {
     41                protected:
     42
     43                        btScalar m_halfHeight;
     44
     45                        btPairCachingGhostObject* m_ghostObject;
     46                        btConvexShape*  m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
     47
     48                        btScalar m_verticalVelocity;
     49                        btScalar m_verticalOffset;
     50                        btScalar m_fallSpeed;
     51                        btScalar m_jumpSpeed;
     52                        btScalar m_maxJumpHeight;
     53                        btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
     54                        btScalar m_maxSlopeCosine;  // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
     55                        btScalar m_gravity;
     56
     57                        btScalar m_turnAngle;
     58
     59                        btScalar m_stepHeight;
     60
     61                        btScalar        m_addedMargin;//@todo: remove this and fix the code
     62
     63                        ///this is the desired walk direction, set by the user
     64                        btVector3       m_walkDirection;
     65                        btVector3       m_normalizedDirection;
     66
     67                        //some internal variables
     68                        btVector3 m_currentPosition;
     69                        btScalar  m_currentStepOffset;
     70                        btVector3 m_targetPosition;
     71
     72                        ///keep track of the contact manifolds
     73                        btManifoldArray m_manifoldArray;
     74
     75                        bool m_touchingContact;
     76                        btVector3 m_touchingNormal;
     77
     78                        bool  m_wasOnGround;
     79                        bool  m_wasJumping;
     80                        bool    m_useGhostObjectSweepTest;
     81                        bool    m_useWalkDirection;
     82                        btScalar        m_velocityTimeInterval;
     83                        int m_upAxis;
     84
     85                        static btVector3* getUpAxisDirections();
     86
     87                        btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
     88                        btVector3 parallelComponent (const btVector3& direction, const btVector3& normal);
     89                        btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal);
     90
     91                        bool recoverFromPenetration ( btCollisionWorld* collisionWorld);
     92                        void stepUp (btCollisionWorld* collisionWorld);
     93                        void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
     94                        void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove);
     95                        void stepDown (btCollisionWorld* collisionWorld, btScalar dt);
     96                public:
     97                        BulletKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis = 1);
     98                        ~BulletKinematicCharacterController ();
     99
     100
     101                        ///btActionInterface interface
     102                        virtual void updateAction( btCollisionWorld* collisionWorld,btScalar deltaTime)
     103                        {
     104                                preStep ( collisionWorld);
     105                                playerStep (collisionWorld, deltaTime);
     106                        }
     107
     108                        ///btActionInterface interface
     109                        void    debugDraw(btIDebugDraw* debugDrawer);
     110
     111                        void setUpAxis (int axis)
     112                        {
     113                                if (axis < 0)
     114                                        axis = 0;
     115                                if (axis > 2)
     116                                        axis = 2;
     117                                m_upAxis = axis;
     118                        }
     119
     120                        /// This should probably be called setPositionIncrementPerSimulatorStep.
     121                        /// This is neither a direction nor a velocity, but the amount to
     122                        ///     increment the position each simulation iteration, regardless
     123                        ///     of dt.
     124                        /// This call will reset any velocity set by setVelocityForTimeInterval().
     125                        virtual void    setWalkDirection(const btVector3& walkDirection);
     126
     127                        /// Caller provides a velocity with which the character should move for
     128                        ///     the given time period.  After the time period, velocity is reset
     129                        ///     to zero.
     130                        /// This call will reset any walk direction set by setWalkDirection().
     131                        /// Negative time intervals will result in no motion.
     132                        virtual void setVelocityForTimeInterval(const btVector3& velocity,
     133                                btScalar timeInterval);
     134
     135                        void reset ();
     136                        void warp (const btVector3& origin);
     137
     138                        void preStep (  btCollisionWorld* collisionWorld);
     139                        void playerStep ( btCollisionWorld* collisionWorld, btScalar dt);
     140
     141                        void setFallSpeed (btScalar fallSpeed);
     142                        void setJumpSpeed (btScalar jumpSpeed);
     143                        void setMaxJumpHeight (btScalar maxJumpHeight);
     144                        bool canJump () const;
     145
     146                        void jump ();
     147
     148                        void setGravity(btScalar gravity);
     149                        btScalar getGravity() const;
     150
     151                        /// The max slope determines the maximum angle that the controller can walk up.
     152                        /// The slope angle is measured in radians.
     153                        void setMaxSlope(btScalar slopeRadians);
     154                        btScalar getMaxSlope() const;
     155
     156                        btPairCachingGhostObject* getGhostObject();
     157                        void    setUseGhostSweepTest(bool useGhostObjectSweepTest)
     158                        {
     159                                m_useGhostObjectSweepTest = useGhostObjectSweepTest;
     160                        }
     161
     162                        bool onGround () const;
     163                };
     164
     165#endif // HAVE_PHYS_USE_BULLET
     166#endif // 0
     167
    32168        } /* namespace phys */
    33169
  • trunk/test/Physics/Src/BulletCharacterController.cpp

    r1795 r1798  
    1818#include "../Include/LolPhysics.h"
    1919#include "../Include/EasyCharacterController.h"
     20#include "../Include/BulletCharacterController.h"
     21//#include "LinearMath/btIDebugDraw.h"
     22//#include "BulletCollision/CollisionDispatch/btGhostObject.h"
     23//#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
     24//#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
     25//#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
     26//#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
     27//#include "LinearMath/btDefaultMotionState.h"
     28
    2029
    2130namespace lol
     
    2534        {
    2635
     36#define 0
    2737#ifdef HAVE_PHYS_USE_BULLET
    2838
     39// static helper method
     40static btVector3
     41getNormalizedVector(const btVector3& v)
     42{
     43        btVector3 n = v.normalized();
     44        if (n.length() < SIMD_EPSILON) {
     45                n.setValue(0, 0, 0);
     46        }
     47        return n;
     48}
     49
     50
     51///@todo Interact with dynamic objects,
     52///Ride kinematicly animated platforms properly
     53///More realistic (or maybe just a config option) falling
     54/// -> Should integrate falling velocity manually and use that in stepDown()
     55///Support jumping
     56///Support ducking
     57class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
     58{
     59public:
     60        btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
     61        {
     62                m_me = me;
     63        }
     64
     65        virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
     66        {
     67                if (rayResult.m_collisionObject == m_me)
     68                        return 1.0;
     69
     70                return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
     71        }
     72protected:
     73        btCollisionObject* m_me;
     74};
     75
     76class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
     77{
     78public:
     79        btKinematicClosestNotMeConvexResultCallback (btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
     80        : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
     81        , m_me(me)
     82        , m_up(up)
     83        , m_minSlopeDot(minSlopeDot)
     84        {
     85        }
     86
     87        virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
     88        {
     89                if (convexResult.m_hitCollisionObject == m_me)
     90                        return btScalar(1.0);
     91
     92                btVector3 hitNormalWorld;
     93                if (normalInWorldSpace)
     94                {
     95                        hitNormalWorld = convexResult.m_hitNormalLocal;
     96                } else
     97                {
     98                        ///need to transform normal into worldspace
     99                        hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
     100                }
     101
     102                btScalar dotUp = m_up.dot(hitNormalWorld);
     103                if (dotUp < m_minSlopeDot) {
     104                        return btScalar(1.0);
     105                }
     106
     107                return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
     108        }
     109protected:
     110        btCollisionObject* m_me;
     111        const btVector3 m_up;
     112        btScalar m_minSlopeDot;
     113};
     114
     115/*
     116 * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
     117 *
     118 * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
     119 */
     120btVector3 BulletKinematicCharacterController::computeReflectionDirection (const btVector3& direction, const btVector3& normal)
     121{
     122        return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
     123}
     124
     125/*
     126 * Returns the portion of 'direction' that is parallel to 'normal'
     127 */
     128btVector3 BulletKinematicCharacterController::parallelComponent (const btVector3& direction, const btVector3& normal)
     129{
     130        btScalar magnitude = direction.dot(normal);
     131        return normal * magnitude;
     132}
     133
     134/*
     135 * Returns the portion of 'direction' that is perpindicular to 'normal'
     136 */
     137btVector3 BulletKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal)
     138{
     139        return direction - parallelComponent(direction, normal);
     140}
     141
     142BulletKinematicCharacterController::BulletKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis)
     143{
     144        m_upAxis = upAxis;
     145        m_addedMargin = 0.02;
     146        m_walkDirection.setValue(0,0,0);
     147        m_useGhostObjectSweepTest = true;
     148        m_ghostObject = ghostObject;
     149        m_stepHeight = stepHeight;
     150        m_turnAngle = btScalar(0.0);
     151        m_convexShape=convexShape;     
     152        m_useWalkDirection = true;      // use walk direction by default, legacy behavior
     153        m_velocityTimeInterval = 0.0;
     154        m_verticalVelocity = 0.0;
     155        m_verticalOffset = 0.0;
     156        m_gravity = 9.8 * 3 ; // 3G acceleration.
     157        m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
     158        m_jumpSpeed = 10.0; // ?
     159        m_wasOnGround = false;
     160        m_wasJumping = false;
     161        setMaxSlope(btRadians(45.0));
     162}
     163
     164BulletKinematicCharacterController::~BulletKinematicCharacterController ()
     165{
     166}
     167
     168btPairCachingGhostObject* BulletKinematicCharacterController::getGhostObject()
     169{
     170        return m_ghostObject;
     171}
     172
     173bool BulletKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* collisionWorld)
     174{
     175
     176        bool penetration = false;
     177
     178        collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
     179
     180        m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
     181       
     182        btScalar maxPen = btScalar(0.0);
     183        for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
     184        {
     185                m_manifoldArray.resize(0);
     186
     187                btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
     188               
     189                if (collisionPair->m_algorithm)
     190                        collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
     191
     192               
     193                for (int j=0;j<m_manifoldArray.size();j++)
     194                {
     195                        btPersistentManifold* manifold = m_manifoldArray[j];
     196                        btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
     197                        for (int p=0;p<manifold->getNumContacts();p++)
     198                        {
     199                                const btManifoldPoint&pt = manifold->getContactPoint(p);
     200
     201                                btScalar dist = pt.getDistance();
     202
     203                                if (dist < 0.0)
     204                                {
     205                                        if (dist < maxPen)
     206                                        {
     207                                                maxPen = dist;
     208                                                m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
     209
     210                                        }
     211                                        m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
     212                                        penetration = true;
     213                                } else {
     214                                        //printf("touching %f\n", dist);
     215                                }
     216                        }
     217                       
     218                        //manifold->clearManifold();
     219                }
     220        }
     221        btTransform newTrans = m_ghostObject->getWorldTransform();
     222        newTrans.setOrigin(m_currentPosition);
     223        m_ghostObject->setWorldTransform(newTrans);
     224//      printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
     225        return penetration;
     226}
     227
     228void BulletKinematicCharacterController::stepUp ( btCollisionWorld* world)
     229{
     230        // phase 1: up
     231        btTransform start, end;
     232        m_targetPosition = m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_stepHeight + (m_verticalOffset > 0.f?m_verticalOffset:0.f));
     233
     234        start.setIdentity ();
     235        end.setIdentity ();
     236
     237        /* FIXME: Handle penetration properly */
     238        start.setOrigin (m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_convexShape->getMargin() + m_addedMargin));
     239        end.setOrigin (m_targetPosition);
     240
     241        btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, -getUpAxisDirections()[m_upAxis], btScalar(0.7071));
     242        callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
     243        callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
     244       
     245        if (m_useGhostObjectSweepTest)
     246        {
     247                m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
     248        }
     249        else
     250        {
     251                world->convexSweepTest (m_convexShape, start, end, callback);
     252        }
     253       
     254        if (callback.hasHit())
     255        {
     256                // Only modify the position if the hit was a slope and not a wall or ceiling.
     257                if(callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > 0.0)
     258                {
     259                        // we moved up only a fraction of the step height
     260                        m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction;
     261                        m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
     262                }
     263                m_verticalVelocity = 0.0;
     264                m_verticalOffset = 0.0;
     265        } else {
     266                m_currentStepOffset = m_stepHeight;
     267                m_currentPosition = m_targetPosition;
     268        }
     269}
     270
     271void BulletKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
     272{
     273        btVector3 movementDirection = m_targetPosition - m_currentPosition;
     274        btScalar movementLength = movementDirection.length();
     275        if (movementLength>SIMD_EPSILON)
     276        {
     277                movementDirection.normalize();
     278
     279                btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
     280                reflectDir.normalize();
     281
     282                btVector3 parallelDir, perpindicularDir;
     283
     284                parallelDir = parallelComponent (reflectDir, hitNormal);
     285                perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
     286
     287                m_targetPosition = m_currentPosition;
     288                if (0)//tangentMag != 0.0)
     289                {
     290                        btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength);
     291//                      printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
     292                        m_targetPosition +=  parComponent;
     293                }
     294
     295                if (normalMag != 0.0)
     296                {
     297                        btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength);
     298//                      printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
     299                        m_targetPosition += perpComponent;
     300                }
     301        } else
     302        {
     303//              printf("movementLength don't normalize a zero vector\n");
     304        }
     305}
     306
     307void BulletKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove)
     308{
     309        // printf("m_normalizedDirection=%f,%f,%f\n",
     310        //      m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
     311        // phase 2: forward and strafe
     312        btTransform start, end;
     313        m_targetPosition = m_currentPosition + walkMove;
     314
     315        start.setIdentity ();
     316        end.setIdentity ();
     317       
     318        btScalar fraction = 1.0;
     319        btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
     320//      printf("distance2=%f\n",distance2);
     321
     322        if (m_touchingContact)
     323        {
     324                if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0))
     325                {
     326                        updateTargetPositionBasedOnCollision (m_touchingNormal);
     327                }
     328        }
     329
     330        int maxIter = 10;
     331
     332        while (fraction > btScalar(0.01) && maxIter-- > 0)
     333        {
     334                start.setOrigin (m_currentPosition);
     335                end.setOrigin (m_targetPosition);
     336                btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
     337
     338                btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, sweepDirNegative, btScalar(0.0));
     339                callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
     340                callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
     341
     342
     343                btScalar margin = m_convexShape->getMargin();
     344                m_convexShape->setMargin(margin + m_addedMargin);
     345
     346
     347                if (m_useGhostObjectSweepTest)
     348                {
     349                        m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
     350                } else
     351                {
     352                        collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
     353                }
     354               
     355                m_convexShape->setMargin(margin);
     356
     357               
     358                fraction -= callback.m_closestHitFraction;
     359
     360                if (callback.hasHit())
     361                {       
     362                        // we moved only a fraction
     363                        btScalar hitDistance;
     364                        hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
     365
     366//                      m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
     367
     368                        updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld);
     369                        btVector3 currentDir = m_targetPosition - m_currentPosition;
     370                        distance2 = currentDir.length2();
     371                        if (distance2 > SIMD_EPSILON)
     372                        {
     373                                currentDir.normalize();
     374                                /* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
     375                                if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0))
     376                                {
     377                                        break;
     378                                }
     379                        } else
     380                        {
     381//                              printf("currentDir: don't normalize a zero vector\n");
     382                                break;
     383                        }
     384
     385                } else {
     386                        // we moved whole way
     387                        m_currentPosition = m_targetPosition;
     388                }
     389
     390        //      if (callback.m_closestHitFraction == 0.f)
     391        //              break;
     392
     393        }
     394}
     395
     396void BulletKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt)
     397{
     398        btTransform start, end;
     399
     400        // phase 3: down
     401        /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
     402        btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + additionalDownStep);
     403        btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt;
     404        btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity;
     405        m_targetPosition -= (step_drop + gravity_drop);*/
     406
     407        btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
     408        if(downVelocity > 0.0 && downVelocity < m_stepHeight
     409                && (m_wasOnGround || !m_wasJumping))
     410        {
     411                downVelocity = m_stepHeight;
     412        }
     413
     414        btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
     415        m_targetPosition -= step_drop;
     416
     417        start.setIdentity ();
     418        end.setIdentity ();
     419
     420        start.setOrigin (m_currentPosition);
     421        end.setOrigin (m_targetPosition);
     422
     423        btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine);
     424        callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
     425        callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
     426       
     427        if (m_useGhostObjectSweepTest)
     428        {
     429                m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
     430        } else
     431        {
     432                collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
     433        }
     434
     435        if (callback.hasHit())
     436        {
     437                // we dropped a fraction of the height -> hit floor
     438                m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
     439                m_verticalVelocity = 0.0;
     440                m_verticalOffset = 0.0;
     441                m_wasJumping = false;
     442        } else {
     443                // we dropped the full height
     444               
     445                m_currentPosition = m_targetPosition;
     446        }
     447}
     448
     449
     450
     451void BulletKinematicCharacterController::setWalkDirection
     452(
     453const btVector3& walkDirection
     454)
     455{
     456        m_useWalkDirection = true;
     457        m_walkDirection = walkDirection;
     458        m_normalizedDirection = getNormalizedVector(m_walkDirection);
     459}
     460
     461
     462
     463void BulletKinematicCharacterController::setVelocityForTimeInterval
     464(
     465const btVector3& velocity,
     466btScalar timeInterval
     467)
     468{
     469//      printf("setVelocity!\n");
     470//      printf("  interval: %f\n", timeInterval);
     471//      printf("  velocity: (%f, %f, %f)\n",
     472//               velocity.x(), velocity.y(), velocity.z());
     473
     474        m_useWalkDirection = false;
     475        m_walkDirection = velocity;
     476        m_normalizedDirection = getNormalizedVector(m_walkDirection);
     477        m_velocityTimeInterval = timeInterval;
     478}
     479
     480
     481
     482void BulletKinematicCharacterController::reset ()
     483{
     484}
     485
     486void BulletKinematicCharacterController::warp (const btVector3& origin)
     487{
     488        btTransform xform;
     489        xform.setIdentity();
     490        xform.setOrigin (origin);
     491        m_ghostObject->setWorldTransform (xform);
     492}
     493
     494
     495void BulletKinematicCharacterController::preStep (  btCollisionWorld* collisionWorld)
     496{
     497       
     498        int numPenetrationLoops = 0;
     499        m_touchingContact = false;
     500        while (recoverFromPenetration (collisionWorld))
     501        {
     502                numPenetrationLoops++;
     503                m_touchingContact = true;
     504                if (numPenetrationLoops > 4)
     505                {
     506                        //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
     507                        break;
     508                }
     509        }
     510
     511        m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
     512        m_targetPosition = m_currentPosition;
     513//      printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
     514
     515       
     516}
     517
     518#include <stdio.h>
     519
     520void BulletKinematicCharacterController::playerStep (  btCollisionWorld* collisionWorld, btScalar dt)
     521{
     522//      printf("playerStep(): ");
     523//      printf("  dt = %f", dt);
     524
     525        // quick check...
     526        if (!m_useWalkDirection && m_velocityTimeInterval <= 0.0) {
     527//              printf("\n");
     528                return;         // no motion
     529        }
     530
     531        m_wasOnGround = onGround();
     532
     533        // Update fall velocity.
     534        m_verticalVelocity -= m_gravity * dt;
     535        if(m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
     536        {
     537                m_verticalVelocity = m_jumpSpeed;
     538        }
     539        if(m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
     540        {
     541                m_verticalVelocity = -btFabs(m_fallSpeed);
     542        }
     543        m_verticalOffset = m_verticalVelocity * dt;
     544
     545
     546        btTransform xform;
     547        xform = m_ghostObject->getWorldTransform ();
     548
     549//      printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
     550//      printf("walkSpeed=%f\n",walkSpeed);
     551
     552        stepUp (collisionWorld);
     553        if (m_useWalkDirection) {
     554                stepForwardAndStrafe (collisionWorld, m_walkDirection);
     555        } else {
     556                //printf("  time: %f", m_velocityTimeInterval);
     557                // still have some time left for moving!
     558                btScalar dtMoving =
     559                        (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
     560                m_velocityTimeInterval -= dt;
     561
     562                // how far will we move while we are moving?
     563                btVector3 move = m_walkDirection * dtMoving;
     564
     565                //printf("  dtMoving: %f", dtMoving);
     566
     567                // okay, step
     568                stepForwardAndStrafe(collisionWorld, move);
     569        }
     570        stepDown (collisionWorld, dt);
     571
     572        // printf("\n");
     573
     574        xform.setOrigin (m_currentPosition);
     575        m_ghostObject->setWorldTransform (xform);
     576}
     577
     578void BulletKinematicCharacterController::setFallSpeed (btScalar fallSpeed)
     579{
     580        m_fallSpeed = fallSpeed;
     581}
     582
     583void BulletKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed)
     584{
     585        m_jumpSpeed = jumpSpeed;
     586}
     587
     588void BulletKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight)
     589{
     590        m_maxJumpHeight = maxJumpHeight;
     591}
     592
     593bool BulletKinematicCharacterController::canJump () const
     594{
     595        return onGround();
     596}
     597
     598void BulletKinematicCharacterController::jump ()
     599{
     600        if (!canJump())
     601                return;
     602
     603        m_verticalVelocity = m_jumpSpeed;
     604        m_wasJumping = true;
     605
     606#if 0
     607        currently no jumping.
     608        btTransform xform;
     609        m_rigidBody->getMotionState()->getWorldTransform (xform);
     610        btVector3 up = xform.getBasis()[1];
     611        up.normalize ();
     612        btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
     613        m_rigidBody->applyCentralImpulse (up * magnitude);
     614#endif
     615}
     616
     617void BulletKinematicCharacterController::setGravity(btScalar gravity)
     618{
     619        m_gravity = gravity;
     620}
     621
     622btScalar BulletKinematicCharacterController::getGravity() const
     623{
     624        return m_gravity;
     625}
     626
     627void BulletKinematicCharacterController::setMaxSlope(btScalar slopeRadians)
     628{
     629        m_maxSlopeRadians = slopeRadians;
     630        m_maxSlopeCosine = btCos(slopeRadians);
     631}
     632
     633btScalar BulletKinematicCharacterController::getMaxSlope() const
     634{
     635        return m_maxSlopeRadians;
     636}
     637
     638bool BulletKinematicCharacterController::onGround () const
     639{
     640        return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0;
     641}
     642
     643
     644btVector3* BulletKinematicCharacterController::getUpAxisDirections()
     645{
     646        static btVector3 sUpAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) };
     647       
     648        return sUpAxisDirection;
     649}
     650
     651void BulletKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
     652{
     653}
     654
     655
    29656#endif // HAVE_PHYS_USE_BULLET
     657#endif // 0
    30658
    31659        } /* namespace phys */
Note: See TracChangeset for help on using the changeset viewer.