How do i get my RigidBodies to penetrate my PairCachingGhostObjects in a way that the PairCachingGhostObject still registers them?
I tried setting the collision flag to "CF_NO_CONTACT_RESPONSE" but my Objects still collide with it.
When I set CollisionGroup and CollisionMask to not collide with the Ghost, then the Penetrating Objects are not registered (e.g. my RigidBodies penetrate it, but the OverlappingPairCache stays empty)
I tried several days now, to create a detector/sensor class that tells me when a RigidBody is at a certain location (volume).
Please help me, as I think I might be going crazy.

Edit:
I pasted alot of the code out of an example that I found in this forum.
The updateAction is NOT from btActionInterface, but from one of our own classes. It gets called immediately before the physics tick.
Code Attached:
Code: Select all
AEGhostDetector::AEGhostDetector(AEPhysicsWorld* physWorld)
{
mBulletWorld= physWorld->getBulletWorld();
mGhostObject = new btPairCachingGhostObject();
mGhostObject->setWorldTransform(btTransform(btQuaternion::getIdentity(),btVector3(0,2,0)));
mBulletWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
btCylinderShape* shape = new btCylinderShape(btVector3(btScalar(0.5),btScalar(1.),btScalar(0.7))); // Here the "full" shape will be used
mGhostObject->setCollisionShape(shape);
mGhostObject->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
mBulletWorld->addCollisionObject(mGhostObject,btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
physWorld->addAction(this);
//mBulletWorld->addCollisionObject(mGhostObject);
}
void AEGhostDetector::updateAction(btDiscreteDynamicsWorld *bulletWorld, int deltaTimeStep)
{
btAlignedObjectArray < btCollisionObject* > objsInsidePairCachingGhostObject; // We might want this to be a member variable...
btAlignedObjectArray < btCollisionObject* >* pObjsInsideGhostObject = NULL; // We will store a reference of the current array in this pointer
const btAlignedObjectArray < btCollisionObject* >& objs = mBulletWorld->getCollisionObjectArray();
for (int i=0,sz=objs.size();i<sz;i++)
{
btCollisionObject* o = objs[i];
btGhostObject* go = btGhostObject::upcast(o);
if (go) {
objsInsidePairCachingGhostObject.resize(0);
btPairCachingGhostObject* pgo = dynamic_cast < btPairCachingGhostObject* > (go); // No upcast functionality...
if (pgo) {
GetCollidingObjectsInsidePairCachingGhostObject(static_cast < btDiscreteDynamicsWorld* > (mBulletWorld),pgo,objsInsidePairCachingGhostObject);
pObjsInsideGhostObject = &objsInsidePairCachingGhostObject;
}
else {
pObjsInsideGhostObject = &go->getOverlappingPairs(); // It's better not to try and copy the whole array, but to keep a reference to it!
// Side Note: btAlignedObjectArray < btCollisionObject* > objs = go->getOverlappingPairs(); (at the moment) makes my program crash on my system...
// Nevermind, that was the wrong way of doing it: btAlignedObjectArray < btCollisionObject* >& objs = go->getOverlappingPairs(); is much better.
}
// Here pObjsInsideGhostObject should be valid.
ProcessObectsInsideGhostObjects(*pObjsInsideGhostObject,pgo);
}
}
}
void AEGhostDetector::ProcessObectsInsideGhostObjects(btAlignedObjectArray < btCollisionObject* >& objs, const bool isPairCachingGhostObject)
{
for (int j=0,jsz=objs.size();j<jsz;j++) {
btRigidBody* b = btRigidBody::upcast(objs[j]);
if (b) {
b->activate();
b->applyCentralImpulse(isPairCachingGhostObject ? btVector3(0,0.5,0) : btVector3(0,0.25,0));
}
}
}
void AEGhostDetector::GetCollidingObjectsInsidePairCachingGhostObject(btDiscreteDynamicsWorld* m_dynamicsWorld,btPairCachingGhostObject* m_pairCachingGhostObject,btAlignedObjectArray < btCollisionObject* >& collisionArrayOut)
{
collisionArrayOut.resize(0);
if (!m_pairCachingGhostObject || !m_dynamicsWorld) return;
const bool addOnlyObjectsWithNegativeDistance(true); // With "false" things don't change much, and the code is a bit faster and cleaner...
//======================================================================================================
// I thought this line was no longer needed, but it seems to be necessary (and I believe it's an expensive call):
m_dynamicsWorld->getDispatcher()->dispatchAllCollisionPairs(m_pairCachingGhostObject->getOverlappingPairCache(), m_dynamicsWorld->getDispatchInfo(), m_dynamicsWorld->getDispatcher());
// PS: This line is present in "bool btKinematicCharacterController::recoverFromPenetration (btCollisionWorld* collisionWorld)" too, so I guess it can't be skipped...
//======================================================================================================
btBroadphasePairArray& collisionPairs = m_pairCachingGhostObject->getOverlappingPairCache()->getOverlappingPairArray();
const int numObjects=collisionPairs.size();
qDebug() << " colliding Objs: " << numObjects;
static btManifoldArray m_manifoldArray;
bool added;
for(int i=0;i<numObjects;i++) {
const btBroadphasePair& collisionPair = collisionPairs[i];
m_manifoldArray.resize(0);
if (collisionPair.m_algorithm) collisionPair.m_algorithm->getAllContactManifolds(m_manifoldArray);
else { // THIS SHOULD NEVER HAPPEN, AND IF IT DOES, PLEASE RE-ENABLE the "call" a few lines above...
printf("No collisionPair.m_algorithm - probably m_dynamicsWorld->getDispatcher()->dispatchAllCollisionPairs(...) must be missing.\n");
}
added = false;
for (int j=0;j<m_manifoldArray.size();j++) {
btPersistentManifold* manifold = m_manifoldArray[j];
// Here we are in the narrowphase, but can happen that manifold->getNumContacts()==0:
if (addOnlyObjectsWithNegativeDistance) {
for (int p=0,numContacts=manifold->getNumContacts();p<numContacts;p++) {
const btManifoldPoint&pt = manifold->getContactPoint(p);
if (pt.getDistance() < 0.0) {
// How can I be sure that the colObjs are all distinct ? I use the "added" flag.
collisionArrayOut.push_back((btCollisionObject*) (manifold->getBody0() == m_pairCachingGhostObject ? manifold->getBody1() : manifold->getBody0()));
added = true;
break;
}
}
if (added) break;
}
else if (manifold->getNumContacts()>0) {
collisionArrayOut.push_back((btCollisionObject*) (manifold->getBody0() == m_pairCachingGhostObject ? manifold->getBody1() : manifold->getBody0()));
break;
}
}
}
}