Changeset 1798
- Timestamp:
- Aug 23, 2012, 5:26:50 PM (11 years ago)
- Location:
- trunk/test/Physics
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/test/Physics/Include/BulletCharacterController.h
r1795 r1798 22 22 #include "core.h" 23 23 #include "EasyPhysics.h" 24 //#include "BulletDynamics\Character\btCharacterControllerInterface.h" 24 25 #endif 25 26 … … 30 31 { 31 32 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 32 168 } /* namespace phys */ 33 169 -
trunk/test/Physics/Src/BulletCharacterController.cpp
r1795 r1798 18 18 #include "../Include/LolPhysics.h" 19 19 #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 20 29 21 30 namespace lol … … 25 34 { 26 35 36 #define 0 27 37 #ifdef HAVE_PHYS_USE_BULLET 28 38 39 // static helper method 40 static btVector3 41 getNormalizedVector(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 57 class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback 58 { 59 public: 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 } 72 protected: 73 btCollisionObject* m_me; 74 }; 75 76 class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback 77 { 78 public: 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 } 109 protected: 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 */ 120 btVector3 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 */ 128 btVector3 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 */ 137 btVector3 BulletKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal) 138 { 139 return direction - parallelComponent(direction, normal); 140 } 141 142 BulletKinematicCharacterController::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 164 BulletKinematicCharacterController::~BulletKinematicCharacterController () 165 { 166 } 167 168 btPairCachingGhostObject* BulletKinematicCharacterController::getGhostObject() 169 { 170 return m_ghostObject; 171 } 172 173 bool 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 228 void 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 271 void 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 307 void 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 396 void 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 451 void BulletKinematicCharacterController::setWalkDirection 452 ( 453 const btVector3& walkDirection 454 ) 455 { 456 m_useWalkDirection = true; 457 m_walkDirection = walkDirection; 458 m_normalizedDirection = getNormalizedVector(m_walkDirection); 459 } 460 461 462 463 void BulletKinematicCharacterController::setVelocityForTimeInterval 464 ( 465 const btVector3& velocity, 466 btScalar 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 482 void BulletKinematicCharacterController::reset () 483 { 484 } 485 486 void BulletKinematicCharacterController::warp (const btVector3& origin) 487 { 488 btTransform xform; 489 xform.setIdentity(); 490 xform.setOrigin (origin); 491 m_ghostObject->setWorldTransform (xform); 492 } 493 494 495 void 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 520 void 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 578 void BulletKinematicCharacterController::setFallSpeed (btScalar fallSpeed) 579 { 580 m_fallSpeed = fallSpeed; 581 } 582 583 void BulletKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed) 584 { 585 m_jumpSpeed = jumpSpeed; 586 } 587 588 void BulletKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight) 589 { 590 m_maxJumpHeight = maxJumpHeight; 591 } 592 593 bool BulletKinematicCharacterController::canJump () const 594 { 595 return onGround(); 596 } 597 598 void 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 617 void BulletKinematicCharacterController::setGravity(btScalar gravity) 618 { 619 m_gravity = gravity; 620 } 621 622 btScalar BulletKinematicCharacterController::getGravity() const 623 { 624 return m_gravity; 625 } 626 627 void BulletKinematicCharacterController::setMaxSlope(btScalar slopeRadians) 628 { 629 m_maxSlopeRadians = slopeRadians; 630 m_maxSlopeCosine = btCos(slopeRadians); 631 } 632 633 btScalar BulletKinematicCharacterController::getMaxSlope() const 634 { 635 return m_maxSlopeRadians; 636 } 637 638 bool BulletKinematicCharacterController::onGround () const 639 { 640 return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0; 641 } 642 643 644 btVector3* 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 651 void BulletKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer) 652 { 653 } 654 655 29 656 #endif // HAVE_PHYS_USE_BULLET 657 #endif // 0 30 658 31 659 } /* namespace phys */
Note: See TracChangeset
for help on using the changeset viewer.