Bullet Collision Detection & Physics Library
btKinematicCharacterController.cpp
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. 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
29static btVector3
31{
32 btVector3 n(0, 0, 0);
33
34 if (v.length() > SIMD_EPSILON) {
35 n = v.normalized();
36 }
37 return n;
38}
39
40
48{
49public:
51 {
52 m_me = me;
53 }
54
56 {
57 if (rayResult.m_collisionObject == m_me)
58 return 1.0;
59
60 return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
61 }
62protected:
64};
65
67{
68public:
70 : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
71 , m_me(me)
72 , m_up(up)
74 {
75 }
76
78 {
79 if (convexResult.m_hitCollisionObject == m_me)
80 return btScalar(1.0);
81
82 if (!convexResult.m_hitCollisionObject->hasContactResponse())
83 return btScalar(1.0);
84
87 {
88 hitNormalWorld = convexResult.m_hitNormalLocal;
89 } else
90 {
92 hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
93 }
94
96 if (dotUp < m_minSlopeDot) {
97 return btScalar(1.0);
98 }
99
100 return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
101 }
102protected:
106};
107
108/*
109 * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
110 *
111 * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
112 */
114{
115 return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
116}
117
118/*
119 * Returns the portion of 'direction' that is parallel to 'normal'
120 */
122{
124 return normal * magnitude;
125}
126
127/*
128 * Returns the portion of 'direction' that is perpindicular to 'normal'
129 */
131{
132 return direction - parallelComponent(direction, normal);
133}
134
136{
138 m_up.setValue(0.0f, 0.0f, 1.0f);
139 m_jumpAxis.setValue(0.0f, 0.0f, 1.0f);
140 m_addedMargin = 0.02;
141 m_walkDirection.setValue(0.0,0.0,0.0);
142 m_AngVel.setValue(0.0, 0.0, 0.0);
144 m_turnAngle = btScalar(0.0);
146 m_useWalkDirection = true; // use walk direction by default, legacy behavior
148 m_verticalVelocity = 0.0;
149 m_verticalOffset = 0.0;
150 m_gravity = 9.8 * 3.0 ; // 3G acceleration.
151 m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
152 m_jumpSpeed = 10.0; // ?
154 m_wasOnGround = false;
155 m_wasJumping = false;
156 m_interpolateUp = true;
159 full_drop = false;
160 bounce_fix = false;
163
164 setUp(up);
166 setMaxSlope(btRadians(45.0));
167}
168
170{
171}
172
174{
175 return m_ghostObject;
176}
177
179{
180 // Here we must refresh the overlapping paircache as the penetrating movement itself or the
181 // previous recovery iteration might have used setWorldTransform and pushed us into an object
182 // that is not in the previous cache contents from the last timestep, as will happen if we
183 // are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck.
184 //
185 // Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase
186 // paircache and the ghostobject's internal paircache at the same time. /BW
187
190 collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(),
191 minAabb,
192 maxAabb,
193 collisionWorld->getDispatcher());
194
195 bool penetration = false;
196
197 collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
198
200
201// btScalar maxPen = btScalar(0.0);
202 for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
203 {
205
207
208 btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
209 btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
210
211 if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
212 continue;
213
214 if (!needsCollision(obj0, obj1))
215 continue;
216
217 if (collisionPair->m_algorithm)
218 collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
219
220
221 for (int j=0;j<m_manifoldArray.size();j++)
222 {
224 btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
225 for (int p=0;p<manifold->getNumContacts();p++)
226 {
227 const btManifoldPoint&pt = manifold->getContactPoint(p);
228
229 btScalar dist = pt.getDistance();
230
231 if (dist < -m_maxPenetrationDepth)
232 {
233 // TODO: cause problems on slopes, not sure if it is needed
234 //if (dist < maxPen)
235 //{
236 // maxPen = dist;
237 // m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
238
239 //}
240 m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
241 penetration = true;
242 } else {
243 //printf("touching %f\n", dist);
244 }
245 }
246
247 //manifold->clearManifold();
248 }
249 }
253// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
254 return penetration;
255}
256
258{
259 btScalar stepHeight = 0.0f;
260 if (m_verticalVelocity < 0.0)
262
263 // phase 1: up
265
267 end.setIdentity ();
268
269 /* FIXME: Handle penetration properly */
270 start.setOrigin(m_currentPosition);
271
274
275 end.setOrigin (m_targetPosition);
276
277 start.setRotation(m_currentOrientation);
278 end.setRotation(m_targetOrientation);
279
283
285 {
287 }
288 else
289 {
291 }
292
294 {
295 // Only modify the position if the hit was a slope and not a wall or ceiling.
296 if (callback.m_hitNormalWorld.dot(m_up) > 0.0)
297 {
298 // we moved up only a fraction of the step height
300 if (m_interpolateUp == true)
302 else
304 }
305
309
310 // fix penetration if we hit a ceiling for example
311 int numPenetrationLoops = 0;
312 m_touchingContact = false;
313 while (recoverFromPenetration(world))
314 {
316 m_touchingContact = true;
317 if (numPenetrationLoops > 4)
318 {
319 //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
320 break;
321 }
322 }
325
326 if (m_verticalOffset > 0)
327 {
328 m_verticalOffset = 0.0;
329 m_verticalVelocity = 0.0;
331 }
332 } else {
335 }
336}
337
339{
340 bool collides = (body0->getBroadphaseHandle()->m_collisionFilterGroup & body1->getBroadphaseHandle()->m_collisionFilterMask) != 0;
341 collides = collides && (body1->getBroadphaseHandle()->m_collisionFilterGroup & body0->getBroadphaseHandle()->m_collisionFilterMask);
342 return collides;
343}
344
346{
350 {
351 movementDirection.normalize();
352
354 reflectDir.normalize();
355
357
360
362 if (0)//tangentMag != 0.0)
363 {
365// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
367 }
368
369 if (normalMag != 0.0)
370 {
372// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
374 }
375 } else
376 {
377// printf("movementLength don't normalize a zero vector\n");
378 }
379}
380
382{
383 // printf("m_normalizedDirection=%f,%f,%f\n",
384 // m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
385 // phase 2: forward and strafe
387
389
390 start.setIdentity ();
391 end.setIdentity ();
392
393 btScalar fraction = 1.0;
394 btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
395// printf("distance2=%f\n",distance2);
396
397 int maxIter = 10;
398
399 while (fraction > btScalar(0.01) && maxIter-- > 0)
400 {
401 start.setOrigin (m_currentPosition);
402 end.setOrigin (m_targetPosition);
404
405 start.setRotation(m_currentOrientation);
406 end.setRotation(m_targetOrientation);
407
411
412
413 btScalar margin = m_convexShape->getMargin();
415
416 if (!(start == end))
417 {
419 {
420 m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
421 }
422 else
423 {
424 collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
425 }
426 }
427 m_convexShape->setMargin(margin);
428
429
430 fraction -= callback.m_closestHitFraction;
431
433 {
434 // we moved only a fraction
435 //btScalar hitDistance;
436 //hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
437
438// m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
439
442 distance2 = currentDir.length2();
443 if (distance2 > SIMD_EPSILON)
444 {
445 currentDir.normalize();
446 /* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
448 {
449 break;
450 }
451 } else
452 {
453// printf("currentDir: don't normalize a zero vector\n");
454 break;
455 }
456
457 }
458 else
459 {
461 }
462 }
463}
464
466{
468 bool runonce = false;
469
470 // phase 3: down
471 /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
472 btVector3 step_drop = m_up * (m_currentStepOffset + additionalDownStep);
473 btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt;
474 btVector3 gravity_drop = m_up * downVelocity;
475 m_targetPosition -= (step_drop + gravity_drop);*/
476
478
480
481 if (m_verticalVelocity > 0.0)
482 return;
483
487
490
494
498
499 while (1)
500 {
501 start.setIdentity ();
502 end.setIdentity ();
503
504 end_double.setIdentity ();
505
506 start.setOrigin (m_currentPosition);
507 end.setOrigin (m_targetPosition);
508
509 start.setRotation(m_currentOrientation);
510 end.setRotation(m_targetOrientation);
511
512 //set double test for 2x the step drop, to check for a large drop vs small drop
514
516 {
517 m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
518
519 if (!callback.hasHit() && m_ghostObject->hasContactResponse())
520 {
521 //test a double fall height, to see if the character should interpolate it's fall (full) or not (partial)
522 m_ghostObject->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
523 }
524 } else
525 {
526 collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
527
528 if (!callback.hasHit() && m_ghostObject->hasContactResponse())
529 {
530 //test a double fall height, to see if the character should interpolate it's fall (large) or not (small)
531 collisionWorld->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
532 }
533 }
534
536 bool has_hit;
537 if (bounce_fix == true)
539 else
541
542 btScalar stepHeight = 0.0f;
543 if (m_verticalVelocity < 0.0)
545
546 if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit == true && runonce == false
548 {
549 //redo the velocity calculation when falling a small amount, for fast stairs motion
550 //for larger falls, use the smoother/slower interpolated movement by not touching the target position
551
554
557 runonce = true;
558 continue; //re-run previous tests
559 }
560 break;
561 }
562
563 if ((m_ghostObject->hasContactResponse() && (callback.hasHit() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))) || runonce == true)
564 {
565 // we dropped a fraction of the height -> hit floor
566 btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2;
567
568 //printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY());
569
570 if (bounce_fix == true)
571 {
572 if (full_drop == true)
574 else
575 //due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually
577 }
578 else
580
581 full_drop = false;
582
583 m_verticalVelocity = 0.0;
584 m_verticalOffset = 0.0;
585 m_wasJumping = false;
586 } else {
587 // we dropped the full height
588
589 full_drop = true;
590
591 if (bounce_fix == true)
592 {
595 {
596 m_targetPosition += step_drop; //undo previous target change
600 }
601 }
602 //printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY());
603
605 }
606}
607
608
609
611(
613)
614{
615 m_useWalkDirection = true;
618}
619
620
621
623(
624const btVector3& velocity,
626)
627{
628// printf("setVelocity!\n");
629// printf(" interval: %f\n", timeInterval);
630// printf(" velocity: (%f, %f, %f)\n",
631// velocity.x(), velocity.y(), velocity.z());
632
633 m_useWalkDirection = false;
634 m_walkDirection = velocity;
637}
638
640{
641 m_AngVel = velocity;
642}
643
645{
646 return m_AngVel;
647}
648
650{
651 m_walkDirection = velocity;
652
653 // HACK: if we are moving in the direction of the up, treat it as a jump :(
654 if (m_walkDirection.length2() > 0)
655 {
656 btVector3 w = velocity.normalized();
657 btScalar c = w.dot(m_up);
658 if (c != 0)
659 {
660 //there is a component in walkdirection for vertical velocity
663 m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.length();
664
665 if (c > 0.0f)
666 {
667 m_wasJumping = true;
669 }
670 }
671 }
672 else
673 m_verticalVelocity = 0.0f;
674}
675
677{
679}
680
682{
683 m_verticalVelocity = 0.0;
684 m_verticalOffset = 0.0;
685 m_wasOnGround = false;
686 m_wasJumping = false;
689
690 //clear pair cache
692 while (cache->getOverlappingPairArray().size() > 0)
693 {
694 cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
695 }
696}
697
699{
700 btTransform xform;
701 xform.setIdentity();
702 xform.setOrigin (origin);
704}
705
706
708{
711
714// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
715}
716
718{
719// printf("playerStep(): ");
720// printf(" dt = %f", dt);
721
722 if (m_AngVel.length2() > 0.0f)
723 {
725 }
726
727 // integrate for angular velocity
728 if (m_AngVel.length2() > 0.0f)
729 {
730 btTransform xform;
732
734
735 btQuaternion orn = rot * xform.getRotation();
736
737 xform.setRotation(orn);
739
744 }
745
746 // quick check...
748// printf("\n");
749 return; // no motion
750 }
751
753
754 //btVector3 lvel = m_walkDirection;
755 //btScalar c = 0.0f;
756
757 if (m_walkDirection.length2() > 0)
758 {
759 // apply damping
761 }
762
764
765 // Update fall velocity.
768 {
770 }
772 {
774 }
776
777 btTransform xform;
779
780// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
781// printf("walkSpeed=%f\n",walkSpeed);
782
784 //todo: Experimenting with behavior of controller when it hits a ceiling..
785 //bool hitUp = stepUp (collisionWorld);
786 //if (hitUp)
787 //{
788 // m_verticalVelocity -= m_gravity * dt;
789 // if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
790 // {
791 // m_verticalVelocity = m_jumpSpeed;
792 // }
793 // if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
794 // {
795 // m_verticalVelocity = -btFabs(m_fallSpeed);
796 // }
797 // m_verticalOffset = m_verticalVelocity * dt;
798
799 // xform = m_ghostObject->getWorldTransform();
800 //}
801
802 if (m_useWalkDirection) {
804 } else {
805 //printf(" time: %f", m_velocityTimeInterval);
806 // still have some time left for moving!
810
811 // how far will we move while we are moving?
813
814 //printf(" dtMoving: %f", dtMoving);
815
816 // okay, step
818 }
820
821 //todo: Experimenting with max jump height
822 //if (m_wasJumping)
823 //{
824 // btScalar ds = m_currentPosition[m_upAxis] - m_jumpPosition[m_upAxis];
825 // if (ds > m_maxJumpHeight)
826 // {
827 // // substract the overshoot
828 // m_currentPosition[m_upAxis] -= ds - m_maxJumpHeight;
829
830 // // max height was reached, so potential energy is at max
831 // // and kinematic energy is 0, thus velocity is 0.
832 // if (m_verticalVelocity > 0.0)
833 // m_verticalVelocity = 0.0;
834 // }
835 //}
836 // printf("\n");
837
840
841 int numPenetrationLoops = 0;
842 m_touchingContact = false;
844 {
846 m_touchingContact = true;
847 if (numPenetrationLoops > 4)
848 {
849 //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
850 break;
851 }
852 }
853}
854
856{
858}
859
861{
864}
865
867{
869}
870
872{
873 return onGround();
874}
875
877{
878 m_jumpSpeed = v.length2() == 0 ? m_SetjumpSpeed : v.length();
880 m_wasJumping = true;
881
882 m_jumpAxis = v.length2() == 0 ? m_up : v.normalized();
883
885
886#if 0
888 btTransform xform;
889 m_rigidBody->getMotionState()->getWorldTransform (xform);
890 btVector3 up = xform.getBasis()[1];
891 up.normalize ();
892 btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
893 m_rigidBody->applyCentralImpulse (up * magnitude);
894#endif
895}
896
898{
899 if (gravity.length2() > 0) setUpVector(-gravity);
900
901 m_gravity = gravity.length();
902}
903
905{
906 return -m_gravity * m_up;
907}
908
910{
913}
914
916{
917 return m_maxSlopeRadians;
918}
919
921{
923}
924
926{
928}
929
931{
933}
934
936{
937 m_stepHeight = h;
938}
939
941{
942 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) };
943
944 return sUpAxisDirection;
945}
946
948{
949}
950
952{
953 m_interpolateUp = value;
954}
955
957{
958 if (up.length2() > 0 && m_gravity > 0.0f)
959 {
960 setGravity(-m_gravity * up.normalized());
961 return;
962 }
963
965}
966
968{
969 if (m_up == up)
970 return;
971
972 btVector3 u = m_up;
973
974 if (up.length2() > 0)
975 m_up = up.normalized();
976 else
977 m_up = btVector3(0.0, 0.0, 0.0);
978
979 if (!m_ghostObject) return;
981
982 //set orientation with new up
983 btTransform xform;
985 btQuaternion orn = rot.inverse() * xform.getRotation();
986 xform.setRotation(orn);
988}
989
991{
992 if (v0.length2() == 0.0f || v1.length2() == 0.0f)
993 {
995 return q;
996 }
997
998 return shortestArcQuatNormalize2(v0, v1);
999}
1000
static btVector3 getNormalizedVector(const btVector3 &v)
const T & btMax(const T &a, const T &b)
Definition btMinMax.h:29
btQuaternion shortestArcQuatNormalize2(btVector3 &v0, btVector3 &v1)
btScalar btPow(btScalar x, btScalar y)
Definition btScalar.h:499
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition btScalar.h:292
btScalar btSin(btScalar x)
Definition btScalar.h:477
btScalar btFabs(btScalar x)
Definition btScalar.h:475
btScalar btCos(btScalar x)
Definition btScalar.h:476
btScalar btRadians(btScalar x)
Definition btScalar.h:566
#define SIMD_EPSILON
Definition btScalar.h:521
btScalar btAcos(btScalar x)
Definition btScalar.h:479
#define SIMD_HALF_PI
Definition btScalar.h:506
int size() const
return the number of elements in the array
void resize(int newsize, const T &fillData=T())
btCollisionObject can be used to manage collision detection objects.
btTransform & getWorldTransform()
btBroadphaseProxy * getBroadphaseHandle()
bool hasContactResponse() const
void setWorldTransform(const btTransform &worldTrans)
CollisionWorld is interface and container for the collision detection.
btDispatcherInfo & getDispatchInfo()
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...
The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape...
virtual void setMargin(btScalar margin)=0
virtual btScalar getMargin() const =0
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...
void convexSweepTest(const class btConvexShape *castShape, const btTransform &convexFromWorld, const btTransform &convexToWorld, btCollisionWorld::ConvexResultCallback &resultCallback, btScalar allowedCcdPenetration=0.f) const
Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman,...
virtual void * removeOverlappingPair(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1, btDispatcher *dispatcher)
btBroadphasePairArray & getOverlappingPairArray()
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
btVector3 perpindicularComponent(const btVector3 &direction, const btVector3 &normal)
btVector3 m_walkDirection
this is the desired walk direction, set by the user
virtual void setWalkDirection(const btVector3 &walkDirection)
This should probably be called setPositionIncrementPerSimulatorStep.
virtual bool needsCollision(const btCollisionObject *body0, const btCollisionObject *body1)
void reset(btCollisionWorld *collisionWorld)
void jump(const btVector3 &v=btVector3())
void playerStep(btCollisionWorld *collisionWorld, btScalar dt)
void preStep(btCollisionWorld *collisionWorld)
btVector3 computeReflectionDirection(const btVector3 &direction, const btVector3 &normal)
virtual void setLinearVelocity(const btVector3 &velocity)
void stepDown(btCollisionWorld *collisionWorld, btScalar dt)
virtual const btVector3 & getAngularVelocity() const
btManifoldArray m_manifoldArray
keep track of the contact manifolds
btKinematicCharacterController(btPairCachingGhostObject *ghostObject, btConvexShape *convexShape, btScalar stepHeight, const btVector3 &up=btVector3(1.0, 0.0, 0.0))
void stepForwardAndStrafe(btCollisionWorld *collisionWorld, const btVector3 &walkMove)
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval)
Caller provides a velocity with which the character should move for the given time period.
void setMaxSlope(btScalar slopeRadians)
The max slope determines the maximum angle that the controller can walk up.
void debugDraw(btIDebugDraw *debugDrawer)
btActionInterface interface
void updateTargetPositionBasedOnCollision(const btVector3 &hit_normal, btScalar tangentMag=btScalar(0.0), btScalar normalMag=btScalar(1.0))
void stepUp(btCollisionWorld *collisionWorld)
virtual void setAngularVelocity(const btVector3 &velocity)
btQuaternion getRotation(btVector3 &v0, btVector3 &v1) const
btVector3 parallelComponent(const btVector3 &direction, const btVector3 &normal)
bool recoverFromPenetration(btCollisionWorld *collisionWorld)
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace)
btKinematicClosestNotMeConvexResultCallback(btCollisionObject *me, const btVector3 &up, btScalar minSlopeDot)
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace)
ManifoldContactPoint collects and maintains persistent contactpoints.
btScalar getDistance() const
btHashedOverlappingPairCache * getOverlappingPairCache()
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
btQuaternion inverse() const
Return the inverse of this quaternion.
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition btTransform.h:34
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
void setRotation(const btQuaternion &q)
Set the rotational element by btQuaternion.
void setIdentity()
Set this transformation to the identity.
btQuaternion getRotation() const
Return a quaternion representing the rotation.
btVector3 & getOrigin()
Return the origin vector translation.
void setOrigin(const btVector3 &origin)
Set the translational element.
btVector3 can be used to represent 3D points and vectors.
Definition btVector3.h:84
void setInterpolate3(const btVector3 &v0, const btVector3 &v1, btScalar rt)
Definition btVector3.h:503
btScalar length() const
Return the length of the vector.
Definition btVector3.h:263
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition btVector3.h:235
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition btVector3.h:652
btVector3 normalized() const
Return a normalized version of this vector.
Definition btVector3.h:964
btScalar length2() const
Return the length of the vector squared.
Definition btVector3.h:257
const btScalar & getY() const
Return the y value.
Definition btVector3.h:575
The btBroadphasePair class contains a pair of aabb-overlapping objects.
ClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld)
ClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld)
btScalar m_allowedCcdPenetration