///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<btCollisionObject*>(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()));
}