From 8d97babd888749a6490c3aabdbcdd57f5f80919e Mon Sep 17 00:00:00 2001 From: panzergame Date: Fri, 5 Oct 2018 23:01:23 +0200 Subject: [PATCH] UPBGE: Fix character collision detection. (#866) Chracter controller is using a ghost object and in particular a ghost object caching collision pairs named btPairCachingGhostObject. But with the recent update of bullet, we realized after some bug reported around character that the caching of collision is not anymore supported in a safe way. Instead of fixing the caching mechanism, it was choose to replace btPairCachingGhostObject by btGhostObject. The btGhostObject is already maintaining a cache of object overlapping the only step added is asking the pair cache in the world dispatcher for the character ghost and one of its overlapping objects. By this way the character is just reading and not managing duplication or deletion of manifold in its own cache which is the safest solution. In the same time the function btSequentialImpulseConstraintSolver::getOrInitSolverBody is not handling ghost object but only soft, rigid, kinematic and multibody. An assert is disabled with the adjonction of ghost type check. Fix issue #838. --- .../btKinematicCharacterController.cpp | 32 +++++++++++-------- .../btKinematicCharacterController.h | 8 ++--- .../btSequentialImpulseConstraintSolver.cpp | 3 +- .../Physics/Bullet/CcdPhysicsController.cpp | 6 ++-- .../Physics/Bullet/CcdPhysicsController.h | 4 +-- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/extern/bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/extern/bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp index cb1aa71a14e4..4a6ce16a4e2b 100644 --- a/extern/bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp +++ b/extern/bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp @@ -132,7 +132,7 @@ btVector3 btKinematicCharacterController::perpindicularComponent (const btVector return direction - parallelComponent(direction, normal); } -btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up) +btKinematicCharacterController::btKinematicCharacterController (btGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up) { m_ghostObject = ghostObject; m_up.setValue(0.0f, 0.0f, 1.0f); @@ -170,7 +170,7 @@ btKinematicCharacterController::~btKinematicCharacterController () { } -btPairCachingGhostObject* btKinematicCharacterController::getGhostObject() +btGhostObject* btKinematicCharacterController::getGhostObject() { return m_ghostObject; } @@ -194,26 +194,32 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* bool penetration = false; - collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher()); - m_currentPosition = m_ghostObject->getWorldTransform().getOrigin(); - + + btOverlappingPairCache *pairCache = collisionWorld->getPairCache(); + const unsigned int numPairs = m_ghostObject->getNumOverlappingObjects(); + // btScalar maxPen = btScalar(0.0); - for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++) + for (int i = 0; i < numPairs; i++) { - m_manifoldArray.resize(0); + btCollisionObject *obj0 = m_ghostObject; + btCollisionObject *obj1 = m_ghostObject->getOverlappingObject(i); - btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i]; + btBroadphaseProxy *proxy0 = obj0->getBroadphaseHandle(); + btBroadphaseProxy *proxy1 = obj1->getBroadphaseHandle(); - btCollisionObject* obj0 = static_cast(collisionPair->m_pProxy0->m_clientObject); - btCollisionObject* obj1 = static_cast(collisionPair->m_pProxy1->m_clientObject); + btBroadphasePair* collisionPair = pairCache->findPair(proxy0, proxy1); + + btAssert(collisionPair); if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse())) continue; if (!needsCollision(obj0, obj1)) continue; - + + m_manifoldArray.resize(0); + if (collisionPair->m_algorithm) collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray); @@ -688,11 +694,11 @@ void btKinematicCharacterController::reset ( btCollisionWorld* collisionWorld ) m_velocityTimeInterval = 0.0; //clear pair cache - btHashedOverlappingPairCache *cache = m_ghostObject->getOverlappingPairCache(); + /*btHashedOverlappingPairCache *cache = m_ghostObject->getOverlappingPairCache(); while (cache->getOverlappingPairArray().size() > 0) { cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher()); - } + }*/ } void btKinematicCharacterController::warp (const btVector3& origin) diff --git a/extern/bullet/src/BulletDynamics/Character/btKinematicCharacterController.h b/extern/bullet/src/BulletDynamics/Character/btKinematicCharacterController.h index 00c59c02480d..fe3cf2768b02 100644 --- a/extern/bullet/src/BulletDynamics/Character/btKinematicCharacterController.h +++ b/extern/bullet/src/BulletDynamics/Character/btKinematicCharacterController.h @@ -29,7 +29,7 @@ class btConvexShape; class btRigidBody; class btCollisionWorld; class btCollisionDispatcher; -class btPairCachingGhostObject; +class btGhostObject; ///btKinematicCharacterController is an object that supports a sliding motion in a world. ///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. @@ -40,7 +40,7 @@ ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterCo btScalar m_halfHeight; - btPairCachingGhostObject* m_ghostObject; + btGhostObject* m_ghostObject; btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast btScalar m_maxPenetrationDepth; @@ -117,7 +117,7 @@ ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterCo BT_DECLARE_ALIGNED_ALLOCATOR(); - btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up = btVector3(1.0,0.0,0.0)); + btKinematicCharacterController (btGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up = btVector3(1.0,0.0,0.0)); ~btKinematicCharacterController (); @@ -191,7 +191,7 @@ ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterCo void setMaxPenetrationDepth(btScalar d); btScalar getMaxPenetrationDepth() const; - btPairCachingGhostObject* getGhostObject(); + btGhostObject* getGhostObject(); void setUseGhostSweepTest(bool useGhostObjectSweepTest) { m_useGhostObjectSweepTest = useGhostObjectSweepTest; diff --git a/extern/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 63174a6ec0ec..4df7b33adb84 100644 --- a/extern/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/extern/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -785,8 +785,9 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& else { bool isMultiBodyType = (body.getInternalType()&btCollisionObject::CO_FEATHERSTONE_LINK); + const bool isGhostType = (body.getInternalType() & btCollisionObject::CO_GHOST_OBJECT); // Incorrectly set collision object flags can degrade performance in various ways. - if (!isMultiBodyType) + if (!isMultiBodyType && !isGhostType) { btAssert( body.isStaticOrKinematicObject() ); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index f8ec5e9896e5..20602b56a138 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -58,7 +58,7 @@ float gLinearSleepingTreshold; float gAngularSleepingTreshold; CcdCharacter::CcdCharacter(CcdPhysicsController *ctrl, btMotionState *motionState, - btPairCachingGhostObject *ghost, btConvexShape *shape, float stepHeight) + btGhostObject *ghost, btConvexShape *shape, float stepHeight) :btKinematicCharacterController(ghost, shape, stepHeight, btVector3(0.0f, 0.0f, 1.0f)), m_ctrl(ctrl), m_motionState(motionState), @@ -510,7 +510,7 @@ bool CcdPhysicsController::CreateCharacterController() return false; } - m_object = new btPairCachingGhostObject(); + m_object = new btGhostObject(); m_object->setCollisionShape(m_collisionShape); m_object->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT); @@ -518,7 +518,7 @@ bool CcdPhysicsController::CreateCharacterController() m_bulletMotionState->getWorldTransform(trans); m_object->setWorldTransform(trans); - m_characterController = new CcdCharacter(this, m_bulletMotionState, (btPairCachingGhostObject *)m_object, + m_characterController = new CcdCharacter(this, m_bulletMotionState, (btGhostObject *)m_object, (btConvexShape *)m_collisionShape, m_cci.m_stepHeight); m_characterController->setJumpSpeed(m_cci.m_jumpSpeed); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index a1a8935799b9..a2a7541e4669 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -438,7 +438,7 @@ struct CcdConstructionInfo { class btRigidBody; class btCollisionObject; class btSoftBody; -class btPairCachingGhostObject; +class btGhostObject; class CcdCharacter : public btKinematicCharacterController, public PHY_ICharacter { @@ -449,7 +449,7 @@ class CcdCharacter : public btKinematicCharacterController, public PHY_ICharacte unsigned char m_maxJumps; public: - CcdCharacter(CcdPhysicsController *ctrl, btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape *shape, float stepHeight); + CcdCharacter(CcdPhysicsController *ctrl, btMotionState *motionState, btGhostObject *ghost, btConvexShape *shape, float stepHeight); virtual void updateAction(btCollisionWorld *collisionWorld, btScalar dt);