PhysicsCharacter.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /**
  2. * PhysicsCharacter.cpp
  3. *
  4. * Much of the collision detection code for this implementation is based off the
  5. * btbtKinematicCharacterController class from Bullet Physics 2.7.6.
  6. */
  7. #include "Base.h"
  8. #include "PhysicsCharacter.h"
  9. #include "Scene.h"
  10. #include "Game.h"
  11. #include "PhysicsController.h"
  12. namespace gameplay
  13. {
  14. class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
  15. {
  16. public:
  17. ClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
  18. : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), _me(me), _up(up), _minSlopeDot(minSlopeDot)
  19. {
  20. }
  21. btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
  22. {
  23. if (convexResult.m_hitCollisionObject == _me)
  24. return btScalar(1.0);
  25. /*
  26. btVector3 hitNormalWorld;
  27. if (normalInWorldSpace)
  28. {
  29. hitNormalWorld = convexResult.m_hitNormalLocal;
  30. } else
  31. {
  32. // transform normal into worldspace
  33. hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
  34. }
  35. btScalar dotUp = _up.dot(hitNormalWorld);
  36. if (dotUp < _minSlopeDot)
  37. {
  38. return btScalar(1.0);
  39. }
  40. */
  41. return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
  42. }
  43. protected:
  44. btCollisionObject* _me;
  45. const btVector3 _up;
  46. btScalar _minSlopeDot;
  47. };
  48. PhysicsCharacter::PhysicsCharacter(Node* node, const PhysicsCollisionShape::Definition& shape, float mass)
  49. : PhysicsGhostObject(node, shape), _moveVelocity(0,0,0), _forwardVelocity(0.0f), _rightVelocity(0.0f),
  50. _fallVelocity(0, 0, 0), _currentVelocity(0,0,0), _normalizedVelocity(0,0,0),
  51. _colliding(false), _collisionNormal(0,0,0), _currentPosition(0,0,0),
  52. _stepHeight(0.1f), _slopeAngle(0.0f), _cosSlopeAngle(0.0f), _physicsEnabled(true), _mass(mass)
  53. {
  54. setMaxSlopeAngle(45.0f);
  55. // Set the collision flags on the ghost object to indicate it's a character
  56. _ghostObject->setCollisionFlags(_ghostObject->getCollisionFlags() | btCollisionObject::CF_CHARACTER_OBJECT);
  57. // Register ourselves as an action on the physics world so we are called back during physics ticks
  58. Game::getInstance()->getPhysicsController()->_world->addAction(this);
  59. }
  60. PhysicsCharacter::~PhysicsCharacter()
  61. {
  62. // Unregister ourselves as action from world
  63. Game::getInstance()->getPhysicsController()->_world->removeAction(this);
  64. }
  65. PhysicsCharacter* PhysicsCharacter::create(Node* node, Properties* properties)
  66. {
  67. // Check if the properties is valid and has a valid namespace.
  68. assert(properties);
  69. if (!properties || !(strcmp(properties->getNamespace(), "character") == 0))
  70. {
  71. WARN("Failed to load physics character from properties object: must be non-null object and have namespace equal to \'character\'.");
  72. return NULL;
  73. }
  74. // Load the physics collision shape definition.
  75. PhysicsCollisionShape::Definition* shape = PhysicsCollisionShape::Definition::create(node, properties);
  76. if (shape == NULL)
  77. {
  78. WARN("Failed to create collision shape during physics character creation.");
  79. return NULL;
  80. }
  81. // Load the character's parameters.
  82. properties->rewind();
  83. float mass = 1.0f;
  84. const char* name = NULL;
  85. while ((name = properties->getNextProperty()) != NULL)
  86. {
  87. if (strcmp(name, "mass") == 0)
  88. {
  89. mass = properties->getFloat();
  90. }
  91. }
  92. // Create the physics character.
  93. PhysicsCharacter* character = new PhysicsCharacter(node, *shape, mass);
  94. SAFE_DELETE(shape);
  95. return character;
  96. }
  97. PhysicsCollisionObject::Type PhysicsCharacter::getType() const
  98. {
  99. return PhysicsCollisionObject::CHARACTER;
  100. }
  101. btCollisionObject* PhysicsCharacter::getCollisionObject() const
  102. {
  103. return _ghostObject;
  104. }
  105. bool PhysicsCharacter::isPhysicsEnabled() const
  106. {
  107. return _physicsEnabled;
  108. }
  109. void PhysicsCharacter::setPhysicsEnabled(bool enabled)
  110. {
  111. _physicsEnabled = enabled;
  112. }
  113. float PhysicsCharacter::getMaxStepHeight() const
  114. {
  115. return _stepHeight;
  116. }
  117. void PhysicsCharacter::setMaxStepHeight(float height)
  118. {
  119. _stepHeight = height;
  120. }
  121. float PhysicsCharacter::getMaxSlopeAngle() const
  122. {
  123. return _slopeAngle;
  124. }
  125. void PhysicsCharacter::setMaxSlopeAngle(float angle)
  126. {
  127. _slopeAngle = angle;
  128. _cosSlopeAngle = std::cos(MATH_DEG_TO_RAD(angle));
  129. }
  130. void PhysicsCharacter::addAnimation(const char* name, AnimationClip* clip, float moveSpeed)
  131. {
  132. CharacterAnimation a;
  133. a.name = name;
  134. a.clip = clip;
  135. a.moveSpeed = moveSpeed;
  136. a.layer = 0;
  137. a.playing = false;
  138. a.animationFlags = ANIMATION_STOP;
  139. a.prev = NULL;
  140. _animations[name] = a;
  141. }
  142. AnimationClip* PhysicsCharacter::getAnimation(const char* name)
  143. {
  144. if (name)
  145. {
  146. // Lookup the specified animation
  147. std::map<const char*, CharacterAnimation>::iterator aitr = _animations.find(name);
  148. if (aitr != _animations.end())
  149. {
  150. return aitr->second.clip;
  151. }
  152. }
  153. return NULL;
  154. }
  155. void PhysicsCharacter::play(const char* name, AnimationFlags flags, float speed, unsigned int blendDuration, unsigned int layer)
  156. {
  157. CharacterAnimation* animation = NULL;
  158. if (name)
  159. {
  160. // Lookup the specified animation
  161. std::map<const char*, CharacterAnimation>::iterator aitr = _animations.find(name);
  162. if (aitr == _animations.end())
  163. return; // invalid animation name
  164. animation = &(aitr->second);
  165. // Set animation flags
  166. animation->clip->setRepeatCount(flags & ANIMATION_REPEAT ? AnimationClip::REPEAT_INDEFINITE : 1);
  167. animation->clip->setSpeed(speed);
  168. animation->animationFlags = flags;
  169. animation->layer = layer;
  170. animation->blendDuration = blendDuration;
  171. animation->prev = NULL;
  172. // If the animation is already marked playing, do nothing more
  173. if (animation->playing)
  174. return;
  175. }
  176. play(animation, layer);
  177. }
  178. void PhysicsCharacter::play(CharacterAnimation* animation, unsigned int layer)
  179. {
  180. // Is there already an animation playing on this layer?
  181. std::map<unsigned int, CharacterAnimation*>::iterator litr = _layers.find(layer);
  182. CharacterAnimation* prevAnimation = (litr == _layers.end() ? NULL : litr->second);
  183. if (prevAnimation && prevAnimation->playing)
  184. {
  185. // An animation is already playing on this layer
  186. if (animation)
  187. {
  188. if (animation->animationFlags == ANIMATION_RESUME)
  189. animation->prev = prevAnimation;
  190. if (animation->blendDuration > 0L)
  191. {
  192. // Crossfade from current animation into the new one
  193. prevAnimation->clip->crossFade(animation->clip, animation->blendDuration);
  194. }
  195. else
  196. {
  197. // Stop the previous animation (no blending)
  198. prevAnimation->clip->stop();
  199. // Play the new animation
  200. animation->clip->play();
  201. }
  202. }
  203. else
  204. {
  205. // No new animaton specified - stop current animation on this layer
  206. prevAnimation->clip->stop();
  207. }
  208. prevAnimation->playing = false;
  209. }
  210. else if (animation)
  211. {
  212. // No animations currently playing - just play the new one
  213. animation->clip->play();
  214. }
  215. // Update animaton and layers
  216. if (animation)
  217. {
  218. animation->playing = true;
  219. // Update layer to point to the new animation
  220. if (litr != _layers.end())
  221. litr->second = animation;
  222. else
  223. _layers[layer] = animation;
  224. }
  225. else if (litr != _layers.end())
  226. {
  227. // Remove layer sine we stopped the animation previously on it
  228. _layers.erase(litr);
  229. }
  230. }
  231. void PhysicsCharacter::setVelocity(const Vector3& velocity)
  232. {
  233. _moveVelocity.setValue(velocity.x, velocity.y, velocity.z);
  234. }
  235. void PhysicsCharacter::rotate(const Vector3& axis, float angle)
  236. {
  237. _node->rotate(axis, angle);
  238. }
  239. void PhysicsCharacter::rotate(const Quaternion& rotation)
  240. {
  241. _node->rotate(rotation);
  242. }
  243. void PhysicsCharacter::setRotation(const Vector3& axis, float angle)
  244. {
  245. _node->setRotation(axis, angle);
  246. }
  247. void PhysicsCharacter::setRotation(const Quaternion& rotation)
  248. {
  249. _node->setRotation(rotation);
  250. }
  251. void PhysicsCharacter::setForwardVelocity(float velocity)
  252. {
  253. _forwardVelocity = velocity;
  254. }
  255. void PhysicsCharacter::setRightVelocity(float velocity)
  256. {
  257. _rightVelocity = velocity;
  258. }
  259. void PhysicsCharacter::jump(float height)
  260. {
  261. // TODO
  262. }
  263. void PhysicsCharacter::updateCurrentVelocity()
  264. {
  265. Vector3 temp;
  266. btScalar velocity2 = 0;
  267. // Reset velocity vector
  268. _normalizedVelocity.setValue(0, 0, 0);
  269. // Add movement velocity contribution
  270. if (!_moveVelocity.isZero())
  271. {
  272. _normalizedVelocity = _moveVelocity;
  273. velocity2 = _moveVelocity.length2();
  274. }
  275. // Add forward velocity contribution
  276. if (_forwardVelocity != 0)
  277. {
  278. _node->getWorldMatrix().getForwardVector(&temp);
  279. temp.normalize();
  280. temp *= -_forwardVelocity;
  281. _normalizedVelocity += btVector3(temp.x, temp.y, temp.z);
  282. velocity2 = std::max(std::abs(velocity2), std::abs(_forwardVelocity*_forwardVelocity));
  283. }
  284. // Add right velocity contribution
  285. if (_rightVelocity != 0)
  286. {
  287. _node->getWorldMatrix().getRightVector(&temp);
  288. temp.normalize();
  289. temp *= _rightVelocity;
  290. _normalizedVelocity += btVector3(temp.x, temp.y, temp.z);
  291. velocity2 = std::max(std::abs(velocity2), std::abs(_rightVelocity*_rightVelocity));
  292. }
  293. // Compute final combined movement vectors
  294. if (_normalizedVelocity.isZero())
  295. {
  296. _currentVelocity.setZero();
  297. }
  298. else
  299. {
  300. _normalizedVelocity.normalize();
  301. _currentVelocity = _normalizedVelocity * std::sqrt(velocity2);
  302. }
  303. }
  304. void PhysicsCharacter::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep)
  305. {
  306. // First check for existing collisions and attempt to respond/fix them.
  307. // Basically we are trying to move the character so that it does not penetrate
  308. // any other collision objects in the scene. We need to do this to ensure that
  309. // the following steps (movement) start from a clean slate, where the character
  310. // is not colliding with anything. Also, this step handles collision between
  311. // dynamic objects (i.e. objects that moved and now intersect the character).
  312. if (_physicsEnabled)
  313. {
  314. //_colliding = fixCollision(collisionWorld);
  315. _colliding = false;
  316. int stepCount = 0;
  317. while (fixCollision(collisionWorld))
  318. {
  319. _colliding = true;
  320. if (++stepCount > 4)
  321. {
  322. // Most likely we are wedged between a number of different collision objects
  323. break;
  324. }
  325. }
  326. }
  327. // Update current and target world positions
  328. btVector3 startPosition = _ghostObject->getWorldTransform().getOrigin();
  329. _currentPosition = startPosition;
  330. // Process movement in the up direction
  331. if (_physicsEnabled)
  332. stepUp(collisionWorld, deltaTimeStep);
  333. // Process horizontal movement
  334. stepForwardAndStrafe(collisionWorld, deltaTimeStep);
  335. // Process movement in the down direction
  336. if (_physicsEnabled)
  337. stepDown(collisionWorld, deltaTimeStep);
  338. // Set new position
  339. btVector3 translation = _currentPosition - startPosition;
  340. _node->translate(translation.x(), translation.y(), translation.z());
  341. }
  342. void PhysicsCharacter::stepUp(btCollisionWorld* collisionWorld, btScalar time)
  343. {
  344. // Note: btKinematicCharacterController implements this by always just setting
  345. // target position to currentPosition.y + stepHeight, and then checking for collisions.
  346. // Don't let the character move up if it hits the ceiling (or something above).
  347. // Do this WITHOUT using time in the calculation - this way you are always guarnateed
  348. // to step over a step that is stepHeight high.
  349. //
  350. // Note that stepDown() will be called right after this, so the character will move back
  351. // down to collide with the ground so that he smoothly steps up stairs.
  352. _currentPosition += btVector3(0, _stepHeight, 0);
  353. }
  354. void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, float time)
  355. {
  356. // Process currently playing movements+animations and determine final move location
  357. float animationMoveSpeed = 0.0f;
  358. unsigned int animationCount = 0;
  359. for (std::map<unsigned int, CharacterAnimation*>::iterator itr = _layers.begin(); itr != _layers.end(); ++itr)
  360. {
  361. CharacterAnimation* animation = itr->second;
  362. // If the animation is not playing, ignore it
  363. if (!animation->playing)
  364. continue;
  365. AnimationClip* clip = animation->clip;
  366. // Did the clip finish playing (but we still have it marked playing)?
  367. if (!clip->isPlaying())
  368. {
  369. // If the animaton was flaged the ANIMATION_RESUME bit, start the previously playing animation
  370. if ((animation->animationFlags == ANIMATION_RESUME) && animation->prev)
  371. {
  372. play(animation->prev, animation->prev->layer);
  373. }
  374. animation->playing = false;
  375. continue;
  376. }
  377. animationMoveSpeed += animation->moveSpeed;
  378. ++animationCount;
  379. }
  380. updateCurrentVelocity();
  381. // Calculate final velocity
  382. btVector3 velocity(_currentVelocity);
  383. if (animationCount > 0)
  384. {
  385. velocity *= animationMoveSpeed;
  386. }
  387. velocity *= time; // since velocity is in meters per second
  388. if (velocity.isZero())
  389. {
  390. // No velocity, so we aren't moving
  391. return;
  392. }
  393. // Translate the target position by the velocity vector (already scaled by t)
  394. btVector3 targetPosition = _currentPosition + velocity;
  395. // If physics is disabled, simply update current position without checking collisions
  396. if (!_physicsEnabled)
  397. {
  398. _currentPosition = targetPosition;
  399. return;
  400. }
  401. // Check for collisions by performing a bullet convex sweep test
  402. btTransform start;
  403. btTransform end;
  404. start.setIdentity();
  405. end.setIdentity();
  406. btScalar fraction = 1.0;
  407. btScalar distance2;
  408. if (_colliding && (_normalizedVelocity.dot(_collisionNormal) > btScalar(0.0)))
  409. {
  410. updateTargetPositionFromCollision(targetPosition, _collisionNormal);
  411. }
  412. int maxIter = 10;
  413. while (fraction > btScalar(0.01) && maxIter-- > 0)
  414. {
  415. start.setOrigin(_currentPosition);
  416. end.setOrigin(targetPosition);
  417. btVector3 sweepDirNegative(_currentPosition - targetPosition);
  418. ClosestNotMeConvexResultCallback callback(_ghostObject, sweepDirNegative, btScalar(0.0));
  419. callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
  420. callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
  421. _ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
  422. fraction -= callback.m_closestHitFraction;
  423. if (callback.hasHit())
  424. {
  425. Vector3 normal(callback.m_hitNormalWorld.x(), callback.m_hitNormalWorld.y(), callback.m_hitNormalWorld.z());
  426. PhysicsCollisionObject* o = Game::getInstance()->getPhysicsController()->getCollisionObject(callback.m_hitCollisionObject);
  427. if (o->getType() == PhysicsCollisionObject::RIGID_BODY && o->isDynamic())
  428. {
  429. PhysicsRigidBody* rb = static_cast<PhysicsRigidBody*>(o);
  430. normal.normalize();
  431. rb->applyImpulse(_mass * -normal * velocity.length());
  432. }
  433. updateTargetPositionFromCollision(targetPosition, callback.m_hitNormalWorld);
  434. btVector3 currentDir = targetPosition - _currentPosition;
  435. distance2 = currentDir.length2();
  436. if (distance2 > FLT_EPSILON)
  437. {
  438. currentDir.normalize();
  439. // If velocity is against original velocity, stop to avoid tiny oscilations in sloping corners.
  440. if (currentDir.dot(_normalizedVelocity) <= btScalar(0.0))
  441. {
  442. break;
  443. }
  444. }
  445. }
  446. else
  447. {
  448. // Nothing in our way
  449. break;
  450. }
  451. }
  452. _currentPosition = targetPosition;
  453. }
  454. void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
  455. {
  456. // Contribute basic gravity to fall velocity.
  457. btVector3 gravity = Game::getInstance()->getPhysicsController()->_world->getGravity();
  458. _fallVelocity += (gravity * time);
  459. btVector3 targetPosition = _currentPosition + (_fallVelocity * time);
  460. targetPosition -= btVector3(0, _stepHeight, 0);
  461. // Perform a convex sweep test between current and target position
  462. btTransform start;
  463. btTransform end;
  464. start.setIdentity();
  465. end.setIdentity();
  466. start.setOrigin(_currentPosition);
  467. end.setOrigin(targetPosition);
  468. ClosestNotMeConvexResultCallback callback(_ghostObject, btVector3(0, 1, 0), _cosSlopeAngle);
  469. callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
  470. callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
  471. _ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
  472. if (callback.hasHit())
  473. {
  474. // Collision detected, fix it
  475. _currentPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction);
  476. // Zero out fall velocity when we hit an object
  477. _fallVelocity.setZero();
  478. }
  479. else
  480. {
  481. // We can move here
  482. _currentPosition = targetPosition;
  483. }
  484. }
  485. /*
  486. * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
  487. */
  488. btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal)
  489. {
  490. return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
  491. }
  492. /*
  493. * Returns the portion of 'direction' that is parallel to 'normal'
  494. */
  495. btVector3 parallelComponent(const btVector3& direction, const btVector3& normal)
  496. {
  497. btScalar magnitude = direction.dot(normal);
  498. return normal * magnitude;
  499. }
  500. /*
  501. * Returns the portion of 'direction' that is perpindicular to 'normal'
  502. */
  503. btVector3 perpindicularComponent(const btVector3& direction, const btVector3& normal)
  504. {
  505. return direction - parallelComponent(direction, normal);
  506. }
  507. void PhysicsCharacter::updateTargetPositionFromCollision(btVector3& targetPosition, const btVector3& collisionNormal)
  508. {
  509. btVector3 movementDirection = targetPosition - _currentPosition;
  510. btScalar movementLength = movementDirection.length();
  511. if (movementLength > FLT_EPSILON)
  512. {
  513. movementDirection.normalize();
  514. btVector3 reflectDir = computeReflectionDirection(movementDirection, collisionNormal);
  515. reflectDir.normalize();
  516. btVector3 perpindicularDir = perpindicularComponent(reflectDir, collisionNormal);
  517. targetPosition = _currentPosition;
  518. // Disallow the character from moving up during collision recovery (using an arbitrary reasonable epsilon).
  519. // Note that this will need to be generalized to allow for an arbitrary up axis.
  520. if (perpindicularDir.y() < _stepHeight + 0.001)
  521. {
  522. btVector3 perpComponent = perpindicularDir * movementLength;
  523. targetPosition += perpComponent;
  524. }
  525. }
  526. }
  527. bool PhysicsCharacter::fixCollision(btCollisionWorld* world)
  528. {
  529. bool collision = false;
  530. btOverlappingPairCache* pairCache = _ghostObject->getOverlappingPairCache();
  531. // Tell the world to dispatch collision events for our ghost object
  532. world->getDispatcher()->dispatchAllCollisionPairs(pairCache, world->getDispatchInfo(), world->getDispatcher());
  533. // Store our current world position
  534. Vector3 startPosition;
  535. _node->getWorldMatrix().getTranslation(&startPosition);
  536. btVector3 currentPosition = BV(startPosition);
  537. // Handle all collisions/overlappign pairs
  538. btScalar maxPenetration = btScalar(0.0);
  539. for (int i = 0, count = pairCache->getNumOverlappingPairs(); i < count; ++i)
  540. {
  541. _manifoldArray.resize(0);
  542. // Query contacts between this overlapping pair (store in _manifoldArray)
  543. btBroadphasePair* collisionPair = &pairCache->getOverlappingPairArray()[i];
  544. if (collisionPair->m_algorithm)
  545. {
  546. collisionPair->m_algorithm->getAllContactManifolds(_manifoldArray);
  547. }
  548. for (int j = 0, manifoldCount = _manifoldArray.size(); j < manifoldCount; ++j)
  549. {
  550. btPersistentManifold* manifold = _manifoldArray[j];
  551. // Get the direction of the contact points (used to scale normal vector in the correct direction).
  552. btScalar directionSign = manifold->getBody0() == _ghostObject ? -1.0f : 1.0f;
  553. for (int p = 0, contactCount = manifold->getNumContacts(); p < contactCount; ++p)
  554. {
  555. const btManifoldPoint& pt = manifold->getContactPoint(p);
  556. // Get penetration distance for this contact point
  557. btScalar dist = pt.getDistance();
  558. if (dist < 0.0)
  559. {
  560. // A negative distance means the objects are overlapping
  561. if (dist < maxPenetration)
  562. {
  563. // Store collision normal for this point
  564. maxPenetration = dist;
  565. _collisionNormal = pt.m_normalWorldOnB * directionSign;
  566. }
  567. //Node* node = Game::getInstance()->getPhysicsController()->getCollisionObject((btCollisionObject*)(manifold->getBody0() == _ghostObject ? manifold->getBody1() : manifold->getBody0()))->getNode();
  568. // Calculate new position for object, which is translated back along the collision normal
  569. currentPosition += pt.m_normalWorldOnB * directionSign * dist * 0.2f;
  570. collision = true;
  571. }
  572. }
  573. //manifold->clearManifold();
  574. }
  575. }
  576. // Set the new world transformation to apply to fix the collision
  577. _node->translate(Vector3(currentPosition.x(), currentPosition.y(), currentPosition.z()) - startPosition);
  578. return collision;
  579. }
  580. void PhysicsCharacter::debugDraw(btIDebugDraw* debugDrawer)
  581. {
  582. // debug drawing handled by PhysicsController
  583. }
  584. }