Changeset 8351 for code/trunk/src/external/bullet/BulletDynamics/Character
- Timestamp:
- Apr 28, 2011, 7:15:14 AM (14 years ago)
- Location:
- code/trunk/src/external/bullet/BulletDynamics/Character
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk/src/external/bullet/BulletDynamics/Character/btCharacterControllerInterface.h
r5781 r8351 31 31 32 32 virtual void setWalkDirection(const btVector3& walkDirection) = 0; 33 virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0; 33 34 virtual void reset () = 0; 34 35 virtual void warp (const btVector3& origin) = 0; -
code/trunk/src/external/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp
r5781 r8351 13 13 3. This notice may not be removed or altered from any source distribution. 14 14 */ 15 15 16 16 17 #include "LinearMath/btIDebugDraw.h" … … 23 24 #include "btKinematicCharacterController.h" 24 25 25 static btVector3 upAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) }; 26 27 // static helper method 28 static btVector3 29 getNormalizedVector(const btVector3& v) 30 { 31 btVector3 n = v.normalized(); 32 if (n.length() < SIMD_EPSILON) { 33 n.setValue(0, 0, 0); 34 } 35 return n; 36 } 37 26 38 27 39 ///@todo Interact with dynamic objects, … … 53 65 { 54 66 public: 55 btKinematicClosestNotMeConvexResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) 56 { 57 m_me = me; 67 btKinematicClosestNotMeConvexResultCallback (btCollisionObject* me, const btVector3& up, btScalar minSlopeDot) 68 : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) 69 , m_me(me) 70 , m_up(up) 71 , m_minSlopeDot(minSlopeDot) 72 { 58 73 } 59 74 … … 61 76 { 62 77 if (convexResult.m_hitCollisionObject == m_me) 63 return 1.0; 78 return btScalar(1.0); 79 80 btVector3 hitNormalWorld; 81 if (normalInWorldSpace) 82 { 83 hitNormalWorld = convexResult.m_hitNormalLocal; 84 } else 85 { 86 ///need to transform normal into worldspace 87 hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; 88 } 89 90 btScalar dotUp = m_up.dot(hitNormalWorld); 91 if (dotUp < m_minSlopeDot) { 92 return btScalar(1.0); 93 } 64 94 65 95 return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); … … 67 97 protected: 68 98 btCollisionObject* m_me; 99 const btVector3 m_up; 100 btScalar m_minSlopeDot; 69 101 }; 70 102 … … 99 131 { 100 132 m_upAxis = upAxis; 101 m_addedMargin = 0.02 f;133 m_addedMargin = 0.02; 102 134 m_walkDirection.setValue(0,0,0); 103 135 m_useGhostObjectSweepTest = true; … … 106 138 m_turnAngle = btScalar(0.0); 107 139 m_convexShape=convexShape; 140 m_useWalkDirection = true; // use walk direction by default, legacy behavior 141 m_velocityTimeInterval = 0.0; 142 m_verticalVelocity = 0.0; 143 m_verticalOffset = 0.0; 144 m_gravity = 9.8 * 3 ; // 3G acceleration. 145 m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s. 146 m_jumpSpeed = 10.0; // ? 147 m_wasOnGround = false; 148 m_wasJumping = false; 149 setMaxSlope(btRadians(45.0)); 108 150 } 109 151 … … 145 187 const btManifoldPoint&pt = manifold->getContactPoint(p); 146 188 147 if (pt.getDistance() < 0.0) 189 btScalar dist = pt.getDistance(); 190 191 if (dist < 0.0) 148 192 { 149 if ( pt.getDistance()< maxPen)193 if (dist < maxPen) 150 194 { 151 maxPen = pt.getDistance();195 maxPen = dist; 152 196 m_touchingNormal = pt.m_normalWorldOnB * directionSign;//?? 153 197 154 198 } 155 m_currentPosition += pt.m_normalWorldOnB * directionSign * pt.getDistance()* btScalar(0.2);199 m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2); 156 200 penetration = true; 157 201 } else { 158 //printf("touching %f\n", pt.getDistance());202 //printf("touching %f\n", dist); 159 203 } 160 204 } … … 174 218 // phase 1: up 175 219 btTransform start, end; 176 m_targetPosition = m_currentPosition + upAxisDirection[m_upAxis] * m_stepHeight;220 m_targetPosition = m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_stepHeight + (m_verticalOffset > 0.f?m_verticalOffset:0.f)); 177 221 178 222 start.setIdentity (); … … 180 224 181 225 /* FIXME: Handle penetration properly */ 182 start.setOrigin (m_currentPosition + upAxisDirection[m_upAxis] * btScalar(0.1f));226 start.setOrigin (m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_convexShape->getMargin() + m_addedMargin)); 183 227 end.setOrigin (m_targetPosition); 184 228 185 btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject );229 btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, -getUpAxisDirections()[m_upAxis], btScalar(0.7071)); 186 230 callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; 187 231 callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; … … 198 242 if (callback.hasHit()) 199 243 { 200 // we moved up only a fraction of the step height 201 m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction; 202 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); 244 // Only modify the position if the hit was a slope and not a wall or ceiling. 245 if(callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > 0.0) 246 { 247 // we moved up only a fraction of the step height 248 m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction; 249 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); 250 } 251 m_verticalVelocity = 0.0; 252 m_verticalOffset = 0.0; 203 253 } else { 204 254 m_currentStepOffset = m_stepHeight; … … 245 295 void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove) 246 296 { 247 248 btVector3 originalDir = walkMove.normalized(); 249 if (walkMove.length() < SIMD_EPSILON) 250 { 251 originalDir.setValue(0.f,0.f,0.f); 252 } 253 // printf("originalDir=%f,%f,%f\n",originalDir[0],originalDir[1],originalDir[2]); 297 // printf("m_normalizedDirection=%f,%f,%f\n", 298 // m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]); 254 299 // phase 2: forward and strafe 255 300 btTransform start, end; 256 301 m_targetPosition = m_currentPosition + walkMove; 302 257 303 start.setIdentity (); 258 304 end.setIdentity (); … … 264 310 if (m_touchingContact) 265 311 { 266 if (originalDir.dot(m_touchingNormal) > btScalar(0.0)) 312 if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0)) 313 { 267 314 updateTargetPositionBasedOnCollision (m_touchingNormal); 315 } 268 316 } 269 317 … … 274 322 start.setOrigin (m_currentPosition); 275 323 end.setOrigin (m_targetPosition); 276 277 btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject); 324 btVector3 sweepDirNegative(m_currentPosition - m_targetPosition); 325 326 btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, sweepDirNegative, btScalar(0.0)); 278 327 callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; 279 328 callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; … … 300 349 { 301 350 // we moved only a fraction 302 btScalar hitDistance = (callback.m_hitPointWorld - m_currentPosition).length(); 303 if (hitDistance<0.f) 304 { 305 // printf("neg dist?\n"); 306 } 307 308 /* If the distance is farther than the collision margin, move */ 309 if (hitDistance > m_addedMargin) 310 { 311 // printf("callback.m_closestHitFraction=%f\n",callback.m_closestHitFraction); 312 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); 313 } 351 btScalar hitDistance; 352 hitDistance = (callback.m_hitPointWorld - m_currentPosition).length(); 353 354 // m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); 314 355 315 356 updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld); … … 320 361 currentDir.normalize(); 321 362 /* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */ 322 if (currentDir.dot( originalDir) <= btScalar(0.0))363 if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0)) 323 364 { 324 365 break; … … 329 370 break; 330 371 } 372 331 373 } else { 332 374 // we moved whole way … … 345 387 346 388 // phase 3: down 347 btVector3 step_drop = upAxisDirection[m_upAxis] * m_currentStepOffset; 348 btVector3 gravity_drop = upAxisDirection[m_upAxis] * m_stepHeight; 349 m_targetPosition -= (step_drop + gravity_drop); 389 /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0; 390 btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + additionalDownStep); 391 btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt; 392 btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity; 393 m_targetPosition -= (step_drop + gravity_drop);*/ 394 395 btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt; 396 if(downVelocity > 0.0 && downVelocity < m_stepHeight 397 && (m_wasOnGround || !m_wasJumping)) 398 { 399 downVelocity = m_stepHeight; 400 } 401 402 btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity); 403 m_targetPosition -= step_drop; 350 404 351 405 start.setIdentity (); … … 355 409 end.setOrigin (m_targetPosition); 356 410 357 btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject );411 btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine); 358 412 callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; 359 413 callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; … … 371 425 // we dropped a fraction of the height -> hit floor 372 426 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); 427 m_verticalVelocity = 0.0; 428 m_verticalOffset = 0.0; 429 m_wasJumping = false; 373 430 } else { 374 431 // we dropped the full height … … 378 435 } 379 436 437 438 439 void btKinematicCharacterController::setWalkDirection 440 ( 441 const btVector3& walkDirection 442 ) 443 { 444 m_useWalkDirection = true; 445 m_walkDirection = walkDirection; 446 m_normalizedDirection = getNormalizedVector(m_walkDirection); 447 } 448 449 450 451 void btKinematicCharacterController::setVelocityForTimeInterval 452 ( 453 const btVector3& velocity, 454 btScalar timeInterval 455 ) 456 { 457 // printf("setVelocity!\n"); 458 // printf(" interval: %f\n", timeInterval); 459 // printf(" velocity: (%f, %f, %f)\n", 460 // velocity.x(), velocity.y(), velocity.z()); 461 462 m_useWalkDirection = false; 463 m_walkDirection = velocity; 464 m_normalizedDirection = getNormalizedVector(m_walkDirection); 465 m_velocityTimeInterval = timeInterval; 466 } 467 468 469 380 470 void btKinematicCharacterController::reset () 381 471 { … … 402 492 if (numPenetrationLoops > 4) 403 493 { 404 //printf("character could not recover from penetration = %d\n", numPenetrationLoops);494 //printf("character could not recover from penetration = %d\n", numPenetrationLoops); 405 495 break; 406 496 } … … 414 504 } 415 505 506 #include <stdio.h> 507 416 508 void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt) 417 509 { 510 // printf("playerStep(): "); 511 // printf(" dt = %f", dt); 512 513 // quick check... 514 if (!m_useWalkDirection && m_velocityTimeInterval <= 0.0) { 515 // printf("\n"); 516 return; // no motion 517 } 518 519 m_wasOnGround = onGround(); 520 521 // Update fall velocity. 522 m_verticalVelocity -= m_gravity * dt; 523 if(m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed) 524 { 525 m_verticalVelocity = m_jumpSpeed; 526 } 527 if(m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed)) 528 { 529 m_verticalVelocity = -btFabs(m_fallSpeed); 530 } 531 m_verticalOffset = m_verticalVelocity * dt; 532 533 418 534 btTransform xform; 419 535 xform = m_ghostObject->getWorldTransform (); … … 423 539 424 540 stepUp (collisionWorld); 425 stepForwardAndStrafe (collisionWorld, m_walkDirection); 541 if (m_useWalkDirection) { 542 stepForwardAndStrafe (collisionWorld, m_walkDirection); 543 } else { 544 //printf(" time: %f", m_velocityTimeInterval); 545 // still have some time left for moving! 546 btScalar dtMoving = 547 (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval; 548 m_velocityTimeInterval -= dt; 549 550 // how far will we move while we are moving? 551 btVector3 move = m_walkDirection * dtMoving; 552 553 //printf(" dtMoving: %f", dtMoving); 554 555 // okay, step 556 stepForwardAndStrafe(collisionWorld, move); 557 } 426 558 stepDown (collisionWorld, dt); 559 560 // printf("\n"); 427 561 428 562 xform.setOrigin (m_currentPosition); … … 454 588 if (!canJump()) 455 589 return; 590 591 m_verticalVelocity = m_jumpSpeed; 592 m_wasJumping = true; 456 593 457 594 #if 0 … … 466 603 } 467 604 605 void btKinematicCharacterController::setGravity(btScalar gravity) 606 { 607 m_gravity = gravity; 608 } 609 610 btScalar btKinematicCharacterController::getGravity() const 611 { 612 return m_gravity; 613 } 614 615 void btKinematicCharacterController::setMaxSlope(btScalar slopeRadians) 616 { 617 m_maxSlopeRadians = slopeRadians; 618 m_maxSlopeCosine = btCos(slopeRadians); 619 } 620 621 btScalar btKinematicCharacterController::getMaxSlope() const 622 { 623 return m_maxSlopeRadians; 624 } 625 468 626 bool btKinematicCharacterController::onGround () const 469 627 { 470 return true; 471 } 472 473 474 void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer) 475 { 476 } 628 return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0; 629 } 630 631 632 btVector3* btKinematicCharacterController::getUpAxisDirections() 633 { 634 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) }; 635 636 return sUpAxisDirection; 637 } 638 639 void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer) 640 { 641 } -
code/trunk/src/external/bullet/BulletDynamics/Character/btKinematicCharacterController.h
r5781 r8351 14 14 */ 15 15 16 16 17 #ifndef KINEMATIC_CHARACTER_CONTROLLER_H 17 18 #define KINEMATIC_CHARACTER_CONTROLLER_H … … 20 21 21 22 #include "btCharacterControllerInterface.h" 23 24 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" 25 22 26 23 27 class btCollisionShape; … … 33 37 { 34 38 protected: 39 35 40 btScalar m_halfHeight; 36 41 … … 38 43 btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast 39 44 45 btScalar m_verticalVelocity; 46 btScalar m_verticalOffset; 40 47 btScalar m_fallSpeed; 41 48 btScalar m_jumpSpeed; 42 49 btScalar m_maxJumpHeight; 50 btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value) 51 btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization) 52 btScalar m_gravity; 43 53 44 54 btScalar m_turnAngle; … … 50 60 ///this is the desired walk direction, set by the user 51 61 btVector3 m_walkDirection; 62 btVector3 m_normalizedDirection; 52 63 53 64 //some internal variables … … 62 73 btVector3 m_touchingNormal; 63 74 75 bool m_wasOnGround; 76 bool m_wasJumping; 64 77 bool m_useGhostObjectSweepTest; 78 bool m_useWalkDirection; 79 btScalar m_velocityTimeInterval; 80 int m_upAxis; 65 81 66 int m_upAxis;67 82 static btVector3* getUpAxisDirections(); 83 68 84 btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal); 69 85 btVector3 parallelComponent (const btVector3& direction, const btVector3& normal); … … 99 115 } 100 116 101 virtual void setWalkDirection(const btVector3& walkDirection) 102 { 103 m_walkDirection = walkDirection; 104 } 117 /// This should probably be called setPositionIncrementPerSimulatorStep. 118 /// This is neither a direction nor a velocity, but the amount to 119 /// increment the position each simulation iteration, regardless 120 /// of dt. 121 /// This call will reset any velocity set by setVelocityForTimeInterval(). 122 virtual void setWalkDirection(const btVector3& walkDirection); 123 124 /// Caller provides a velocity with which the character should move for 125 /// the given time period. After the time period, velocity is reset 126 /// to zero. 127 /// This call will reset any walk direction set by setWalkDirection(). 128 /// Negative time intervals will result in no motion. 129 virtual void setVelocityForTimeInterval(const btVector3& velocity, 130 btScalar timeInterval); 105 131 106 132 void reset (); … … 114 140 void setMaxJumpHeight (btScalar maxJumpHeight); 115 141 bool canJump () const; 142 116 143 void jump (); 144 145 void setGravity(btScalar gravity); 146 btScalar getGravity() const; 147 148 /// The max slope determines the maximum angle that the controller can walk up. 149 /// The slope angle is measured in radians. 150 void setMaxSlope(btScalar slopeRadians); 151 btScalar getMaxSlope() const; 117 152 118 153 btPairCachingGhostObject* getGhostObject();
Note: See TracChangeset
for help on using the changeset viewer.