PhysicsCharacter.cpp 22 KB

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