///The setup code for using btGhostObjects //create the ghost object. Ogre::Vector3 pos = node->getPosition(); body->setShape(node, _sphereShapeInstance, bodyRes, bodyFriction, bodyMass, pos); btPairCachingGhostObject* ghostObject = new btPairCachingGhostObject(); ghostObject->setCollisionShape(_sphereShapeInstance->getBulletShape()); //create the debug node Ogre::SceneNode* debugNode = _geoMgr->createCube(Ogre::Vector3(10.0f, 10.0f, 10.0f), "DebugNode" + sphereIdStr); PhysicsDestructionComponent* phyDestructionComp = new PhysicsDestructionComponent(ghostObject, body, debugNode); _world->getBulletDynamicsWorld()->addCollisionObject(ghostObject, btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::StaticFilter); _world->getBulletDynamicsWorld()->addAction(phyDestructionComp); _actionComps.push_back(phyDestructionComp); ///below is the updateAction method where you will find the ghost object code. /** * This method implements the updateAction interface from bullet. * * This method will find the max penetration and assume that to be the impact point. The current assumption is that we *don't care about penetration because this impact point is used in the inelastic collision model. * * \precondition We assume this object is valid: ghostobject and target object exists and is valid. * \postcondition the impact point is computed. **/ void PhysicsDestructionComponent::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) { //do collision detection specific to static objects. btManifoldArray manifoldArray; btBroadphasePairArray& pairArray = _ghostObject->getOverlappingPairCache()->getOverlappingPairArray(); bool collision = false; for(size_t i = 0; i < pairArray.size(); ++i) { manifoldArray.clear(); const btBroadphasePair& pair = pairArray[i]; btBroadphasePair* collisionPair = collisionWorld->getPairCache()->findPair(pair.m_pProxy0, pair.m_pProxy1); if(!collisionPair) continue; btCollisionObject* collisionObject = _targetObject->getBulletObject(); btCollisionObject* proxyObject = static_cast(collisionPair->m_pProxy1->m_clientObject); if(proxyObject == collisionObject) { continue; } if(collisionPair->m_algorithm) collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); for(size_t j = 0; j < manifoldArray.size(); ++j) { btPersistentManifold* manifold = manifoldArray[j]; btScalar directionSign = manifold->getBody0() == _ghostObject ? btScalar(-1.0) : btScalar(1.0); for(int p = 0; p < manifold->getNumContacts(); ++p) { const btManifoldPoint &pt = manifold->getContactPoint(p); btScalar dist = pt.getDistance(); if(dist < 0.0) //pentration and thus collision { collision = true; } } } } auto worldTransform = _targetObject->getBulletObject()->getWorldTransform(); _ghostObject->setWorldTransform(worldTransform); if(collision) _debugNode->setPosition(OgreBulletCollisions::BtOgreConverter::to(worldTransform.getOrigin())); }