Bullet Collision Detection & Physics Library
btKinematicCharacterController.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 
17 #include <stdio.h>
26 
27 
28 // static helper method
29 static btVector3
31 {
32  btVector3 n = v.normalized();
33  if (n.length() < SIMD_EPSILON) {
34  n.setValue(0, 0, 0);
35  }
36  return n;
37 }
38 
39 
47 {
48 public:
50  {
51  m_me = me;
52  }
53 
54  virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
55  {
56  if (rayResult.m_collisionObject == m_me)
57  return 1.0;
58 
59  return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
60  }
61 protected:
63 };
64 
66 {
67 public:
69  : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
70  , m_me(me)
71  , m_up(up)
72  , m_minSlopeDot(minSlopeDot)
73  {
74  }
75 
76  virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
77  {
78  if (convexResult.m_hitCollisionObject == m_me)
79  return btScalar(1.0);
80 
81  if (!convexResult.m_hitCollisionObject->hasContactResponse())
82  return btScalar(1.0);
83 
84  btVector3 hitNormalWorld;
85  if (normalInWorldSpace)
86  {
87  hitNormalWorld = convexResult.m_hitNormalLocal;
88  } else
89  {
91  hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
92  }
93 
94  btScalar dotUp = m_up.dot(hitNormalWorld);
95  if (dotUp < m_minSlopeDot) {
96  return btScalar(1.0);
97  }
98 
99  return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
100  }
101 protected:
105 };
106 
107 /*
108  * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
109  *
110  * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
111  */
113 {
114  return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
115 }
116 
117 /*
118  * Returns the portion of 'direction' that is parallel to 'normal'
119  */
121 {
122  btScalar magnitude = direction.dot(normal);
123  return normal * magnitude;
124 }
125 
126 /*
127  * Returns the portion of 'direction' that is perpindicular to 'normal'
128  */
130 {
131  return direction - parallelComponent(direction, normal);
132 }
133 
135 {
136  m_upAxis = upAxis;
137  m_addedMargin = 0.02;
138  m_walkDirection.setValue(0,0,0);
140  m_ghostObject = ghostObject;
141  m_stepHeight = stepHeight;
142  m_turnAngle = btScalar(0.0);
143  m_convexShape=convexShape;
144  m_useWalkDirection = true; // use walk direction by default, legacy behavior
146  m_verticalVelocity = 0.0;
147  m_verticalOffset = 0.0;
148  m_gravity = 9.8 * 3 ; // 3G acceleration.
149  m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
150  m_jumpSpeed = 10.0; // ?
151  m_wasOnGround = false;
152  m_wasJumping = false;
153  m_interpolateUp = true;
154  setMaxSlope(btRadians(45.0));
156  full_drop = false;
157  bounce_fix = false;
158 }
159 
161 {
162 }
163 
165 {
166  return m_ghostObject;
167 }
168 
170 {
171  // Here we must refresh the overlapping paircache as the penetrating movement itself or the
172  // previous recovery iteration might have used setWorldTransform and pushed us into an object
173  // that is not in the previous cache contents from the last timestep, as will happen if we
174  // are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck.
175  //
176  // Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase
177  // paircache and the ghostobject's internal paircache at the same time. /BW
178 
179  btVector3 minAabb, maxAabb;
182  minAabb,
183  maxAabb,
184  collisionWorld->getDispatcher());
185 
186  bool penetration = false;
187 
188  collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
189 
191 
192  btScalar maxPen = btScalar(0.0);
193  for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
194  {
196 
198 
199  btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
200  btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
201 
202  if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
203  continue;
204 
205  if (collisionPair->m_algorithm)
207 
208 
209  for (int j=0;j<m_manifoldArray.size();j++)
210  {
211  btPersistentManifold* manifold = m_manifoldArray[j];
212  btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
213  for (int p=0;p<manifold->getNumContacts();p++)
214  {
215  const btManifoldPoint&pt = manifold->getContactPoint(p);
216 
217  btScalar dist = pt.getDistance();
218 
219  if (dist < 0.0)
220  {
221  if (dist < maxPen)
222  {
223  maxPen = dist;
224  m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
225 
226  }
227  m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
228  penetration = true;
229  } else {
230  //printf("touching %f\n", dist);
231  }
232  }
233 
234  //manifold->clearManifold();
235  }
236  }
238  newTrans.setOrigin(m_currentPosition);
239  m_ghostObject->setWorldTransform(newTrans);
240 // printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
241  return penetration;
242 }
243 
245 {
246  // phase 1: up
247  btTransform start, end;
249 
250  start.setIdentity ();
251  end.setIdentity ();
252 
253  /* FIXME: Handle penetration properly */
256 
260 
262  {
264  }
265  else
266  {
267  world->convexSweepTest (m_convexShape, start, end, callback);
268  }
269 
270  if (callback.hasHit())
271  {
272  // Only modify the position if the hit was a slope and not a wall or ceiling.
273  if(callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > 0.0)
274  {
275  // we moved up only a fraction of the step height
277  if (m_interpolateUp == true)
279  else
281  }
282  m_verticalVelocity = 0.0;
283  m_verticalOffset = 0.0;
284  } else {
287  }
288 }
289 
291 {
292  btVector3 movementDirection = m_targetPosition - m_currentPosition;
293  btScalar movementLength = movementDirection.length();
294  if (movementLength>SIMD_EPSILON)
295  {
296  movementDirection.normalize();
297 
298  btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
299  reflectDir.normalize();
300 
301  btVector3 parallelDir, perpindicularDir;
302 
303  parallelDir = parallelComponent (reflectDir, hitNormal);
304  perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
305 
307  if (0)//tangentMag != 0.0)
308  {
309  btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength);
310 // printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
311  m_targetPosition += parComponent;
312  }
313 
314  if (normalMag != 0.0)
315  {
316  btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength);
317 // printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
318  m_targetPosition += perpComponent;
319  }
320  } else
321  {
322 // printf("movementLength don't normalize a zero vector\n");
323  }
324 }
325 
327 {
328  // printf("m_normalizedDirection=%f,%f,%f\n",
329  // m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
330  // phase 2: forward and strafe
331  btTransform start, end;
332  m_targetPosition = m_currentPosition + walkMove;
333 
334  start.setIdentity ();
335  end.setIdentity ();
336 
337  btScalar fraction = 1.0;
338  btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
339 // printf("distance2=%f\n",distance2);
340 
341  if (m_touchingContact)
342  {
344  {
345  //interferes with step movement
346  //updateTargetPositionBasedOnCollision (m_touchingNormal);
347  }
348  }
349 
350  int maxIter = 10;
351 
352  while (fraction > btScalar(0.01) && maxIter-- > 0)
353  {
356  btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
357 
358  btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, sweepDirNegative, btScalar(0.0));
361 
362 
363  btScalar margin = m_convexShape->getMargin();
365 
366 
368  {
369  m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
370  } else
371  {
372  collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
373  }
374 
375  m_convexShape->setMargin(margin);
376 
377 
378  fraction -= callback.m_closestHitFraction;
379 
380  if (callback.hasHit())
381  {
382  // we moved only a fraction
383  btScalar hitDistance;
384  hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
385 
386 // m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
387 
390  distance2 = currentDir.length2();
391  if (distance2 > SIMD_EPSILON)
392  {
393  currentDir.normalize();
394  /* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
395  if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0))
396  {
397  break;
398  }
399  } else
400  {
401 // printf("currentDir: don't normalize a zero vector\n");
402  break;
403  }
404 
405  } else {
406  // we moved whole way
408  }
409 
410  // if (callback.m_closestHitFraction == 0.f)
411  // break;
412 
413  }
414 }
415 
417 {
418  btTransform start, end, end_double;
419  bool runonce = false;
420 
421  // phase 3: down
422  /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
423  btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + additionalDownStep);
424  btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt;
425  btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity;
426  m_targetPosition -= (step_drop + gravity_drop);*/
427 
428  btVector3 orig_position = m_targetPosition;
429 
430  btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
431 
432  if(downVelocity > 0.0 && downVelocity > m_fallSpeed
433  && (m_wasOnGround || !m_wasJumping))
434  downVelocity = m_fallSpeed;
435 
436  btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
437  m_targetPosition -= step_drop;
438 
442 
446 
447  while (1)
448  {
449  start.setIdentity ();
450  end.setIdentity ();
451 
452  end_double.setIdentity ();
453 
456 
457  //set double test for 2x the step drop, to check for a large drop vs small drop
458  end_double.setOrigin (m_targetPosition - step_drop);
459 
461  {
462  m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
463 
464  if (!callback.hasHit())
465  {
466  //test a double fall height, to see if the character should interpolate it's fall (full) or not (partial)
467  m_ghostObject->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
468  }
469  } else
470  {
471  collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
472 
473  if (!callback.hasHit())
474  {
475  //test a double fall height, to see if the character should interpolate it's fall (large) or not (small)
476  collisionWorld->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
477  }
478  }
479 
480  btScalar downVelocity2 = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
481  bool has_hit = false;
482  if (bounce_fix == true)
483  has_hit = callback.hasHit() || callback2.hasHit();
484  else
485  has_hit = callback2.hasHit();
486 
487  if(downVelocity2 > 0.0 && downVelocity2 < m_stepHeight && has_hit == true && runonce == false
488  && (m_wasOnGround || !m_wasJumping))
489  {
490  //redo the velocity calculation when falling a small amount, for fast stairs motion
491  //for larger falls, use the smoother/slower interpolated movement by not touching the target position
492 
493  m_targetPosition = orig_position;
494  downVelocity = m_stepHeight;
495 
496  btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
497  m_targetPosition -= step_drop;
498  runonce = true;
499  continue; //re-run previous tests
500  }
501  break;
502  }
503 
504  if (callback.hasHit() || runonce == true)
505  {
506  // we dropped a fraction of the height -> hit floor
507 
508  btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2;
509 
510  //printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY());
511 
512  if (bounce_fix == true)
513  {
514  if (full_drop == true)
516  else
517  //due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually
519  }
520  else
522 
523  full_drop = false;
524 
525  m_verticalVelocity = 0.0;
526  m_verticalOffset = 0.0;
527  m_wasJumping = false;
528  } else {
529  // we dropped the full height
530 
531  full_drop = true;
532 
533  if (bounce_fix == true)
534  {
535  downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
536  if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
537  {
538  m_targetPosition += step_drop; //undo previous target change
539  downVelocity = m_fallSpeed;
540  step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
541  m_targetPosition -= step_drop;
542  }
543  }
544  //printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY());
545 
547  }
548 }
549 
550 
551 
553 (
554 const btVector3& walkDirection
555 )
556 {
557  m_useWalkDirection = true;
558  m_walkDirection = walkDirection;
559  m_normalizedDirection = getNormalizedVector(m_walkDirection);
560 }
561 
562 
563 
565 (
566 const btVector3& velocity,
567 btScalar timeInterval
568 )
569 {
570 // printf("setVelocity!\n");
571 // printf(" interval: %f\n", timeInterval);
572 // printf(" velocity: (%f, %f, %f)\n",
573 // velocity.x(), velocity.y(), velocity.z());
574 
575  m_useWalkDirection = false;
576  m_walkDirection = velocity;
577  m_normalizedDirection = getNormalizedVector(m_walkDirection);
578  m_velocityTimeInterval += timeInterval;
579 }
580 
582 {
583  m_verticalVelocity = 0.0;
584  m_verticalOffset = 0.0;
585  m_wasOnGround = false;
586  m_wasJumping = false;
587  m_walkDirection.setValue(0,0,0);
589 
590  //clear pair cache
592  while (cache->getOverlappingPairArray().size() > 0)
593  {
594  cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
595  }
596 }
597 
599 {
600  btTransform xform;
601  xform.setIdentity();
602  xform.setOrigin (origin);
604 }
605 
606 
608 {
609 
610  int numPenetrationLoops = 0;
611  m_touchingContact = false;
612  while (recoverFromPenetration (collisionWorld))
613  {
614  numPenetrationLoops++;
615  m_touchingContact = true;
616  if (numPenetrationLoops > 4)
617  {
618  //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
619  break;
620  }
621  }
622 
625 // printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
626 
627 
628 }
629 
630 #include <stdio.h>
631 
633 {
634 // printf("playerStep(): ");
635 // printf(" dt = %f", dt);
636 
637  // quick check...
639 // printf("\n");
640  return; // no motion
641  }
642 
644 
645  // Update fall velocity.
648  {
650  }
652  {
654  }
656 
657 
658  btTransform xform;
659  xform = m_ghostObject->getWorldTransform ();
660 
661 // printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
662 // printf("walkSpeed=%f\n",walkSpeed);
663 
664  stepUp (collisionWorld);
665  if (m_useWalkDirection) {
666  stepForwardAndStrafe (collisionWorld, m_walkDirection);
667  } else {
668  //printf(" time: %f", m_velocityTimeInterval);
669  // still have some time left for moving!
670  btScalar dtMoving =
673 
674  // how far will we move while we are moving?
675  btVector3 move = m_walkDirection * dtMoving;
676 
677  //printf(" dtMoving: %f", dtMoving);
678 
679  // okay, step
680  stepForwardAndStrafe(collisionWorld, move);
681  }
682  stepDown (collisionWorld, dt);
683 
684  // printf("\n");
685 
688 }
689 
691 {
692  m_fallSpeed = fallSpeed;
693 }
694 
696 {
697  m_jumpSpeed = jumpSpeed;
698 }
699 
701 {
702  m_maxJumpHeight = maxJumpHeight;
703 }
704 
706 {
707  return onGround();
708 }
709 
711 {
712  if (!canJump())
713  return;
714 
716  m_wasJumping = true;
717 
718 #if 0
719  currently no jumping.
720  btTransform xform;
721  m_rigidBody->getMotionState()->getWorldTransform (xform);
722  btVector3 up = xform.getBasis()[1];
723  up.normalize ();
724  btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
725  m_rigidBody->applyCentralImpulse (up * magnitude);
726 #endif
727 }
728 
730 {
731  m_gravity = gravity;
732 }
733 
735 {
736  return m_gravity;
737 }
738 
740 {
741  m_maxSlopeRadians = slopeRadians;
742  m_maxSlopeCosine = btCos(slopeRadians);
743 }
744 
746 {
747  return m_maxSlopeRadians;
748 }
749 
751 {
752  return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0;
753 }
754 
755 
757 {
758  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) };
759 
760  return sUpAxisDirection;
761 }
762 
764 {
765 }
766 
768 {
769  m_interpolateUp = value;
770 }
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:150
#define SIMD_EPSILON
Definition: btScalar.h:448
btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:835
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
void playerStep(btCollisionWorld *collisionWorld, btScalar dt)
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace)
void stepDown(btCollisionWorld *collisionWorld, btScalar dt)
btScalar btRadians(btScalar x)
Definition: btScalar.h:482
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:640
float dist(const Point3 &pnt0, const Point3 &pnt1)
short int m_collisionFilterGroup
virtual void dispatchAllCollisionPairs(btOverlappingPairCache *pairCache, const btDispatcherInfo &dispatchInfo, btDispatcher *dispatcher)=0
btVector3 computeReflectionDirection(const btVector3 &direction, const btVector3 &normal)
btKinematicCharacterController(btPairCachingGhostObject *ghostObject, btConvexShape *convexShape, btScalar stepHeight, int upAxis=1)
void setIdentity()
Set this transformation to the identity.
Definition: btTransform.h:172
btBroadphasePairArray & getOverlappingPairArray()
ManifoldContactPoint collects and maintains persistent contactpoints.
const btCollisionObject * getBody0() const
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval)
Caller provides a velocity with which the character should move for the given time period...
void debugDraw(btIDebugDraw *debugDrawer)
btActionInterface interface
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:235
bool hasContactResponse() const
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:297
The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape...
Definition: btConvexShape.h:31
btHashedOverlappingPairCache * getOverlappingPairCache()
const btCollisionObject * m_hitCollisionObject
btTransform & getWorldTransform()
btVector3 m_normalWorldOnB
int size() const
return the number of elements in the array
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const =0
getAabb's default implementation is brute force, expected derived classes to implement a fast dedicat...
btBroadphaseProxy * getBroadphaseHandle()
static btVector3 getNormalizedVector(const btVector3 &v)
ClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld)
void setMaxSlope(btScalar slopeRadians)
The max slope determines the maximum angle that the controller can walk up.
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
btCollisionObject can be used to manage collision detection objects.
bool recoverFromPenetration(btCollisionWorld *collisionWorld)
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations...
Definition: btIDebugDraw.h:28
btScalar length() const
Return the length of the vector.
Definition: btVector3.h:263
const btCollisionObject * m_collisionObject
const btManifoldPoint & getContactPoint(int index) const
void setWorldTransform(const btTransform &worldTrans)
btDispatcher * getDispatcher()
virtual btScalar getMargin() const =0
btVector3 parallelComponent(const btVector3 &direction, const btVector3 &normal)
btBroadphaseProxy * m_pProxy1
btCollisionAlgorithm * m_algorithm
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace)
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
btManifoldArray m_manifoldArray
keep track of the contact manifolds
virtual void * removeOverlappingPair(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1, btDispatcher *dispatcher)
virtual void getAllContactManifolds(btManifoldArray &manifoldArray)=0
btScalar length2() const
Return the length of the vector squared.
Definition: btVector3.h:257
btVector3 m_walkDirection
this is the desired walk direction, set by the user
btBroadphaseProxy * m_pProxy0
const btBroadphaseInterface * getBroadphase() const
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
void updateTargetPositionBasedOnCollision(const btVector3 &hit_normal, btScalar tangentMag=btScalar(0.0), btScalar normalMag=btScalar(1.0))
CollisionWorld is interface and container for the collision detection.
btDispatcherInfo & getDispatchInfo()
void stepUp(btCollisionWorld *collisionWorld)
btVector3 normalized() const
Return a normalized version of this vector.
Definition: btVector3.h:951
btScalar m_allowedCcdPenetration
Definition: btDispatcher.h:62
void resize(int newsize, const T &fillData=T())
btVector3 perpindicularComponent(const btVector3 &direction, const btVector3 &normal)
void reset(btCollisionWorld *collisionWorld)
void convexSweepTest(const class btConvexShape *castShape, const btTransform &convexFromWorld, const btTransform &convexToWorld, btCollisionWorld::ConvexResultCallback &resultCallback, btScalar allowedCcdPenetration=0.f) const
btKinematicClosestNotMeConvexResultCallback(btCollisionObject *me, const btVector3 &up, btScalar minSlopeDot)
virtual void setAabb(btBroadphaseProxy *proxy, const btVector3 &aabbMin, const btVector3 &aabbMax, btDispatcher *dispatcher)=0
short int m_collisionFilterMask
void stepForwardAndStrafe(btCollisionWorld *collisionWorld, const btVector3 &walkMove)
void preStep(btCollisionWorld *collisionWorld)
virtual void setWalkDirection(const btVector3 &walkDirection)
This should probably be called setPositionIncrementPerSimulatorStep.
virtual void setMargin(btScalar margin)=0
void convexSweepTest(const btConvexShape *castShape, const btTransform &from, const btTransform &to, ConvexResultCallback &resultCallback, btScalar allowedCcdPenetration=btScalar(0.)) const
convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultC...
btScalar getDistance() const
void setInterpolate3(const btVector3 &v0, const btVector3 &v1, btScalar rt)
Definition: btVector3.h:491
Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman...
ClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:266
btScalar btCos(btScalar x)
Definition: btScalar.h:408
btScalar btFabs(btScalar x)
Definition: btScalar.h:407
The btBroadphasePair class contains a pair of aabb-overlapping objects.