Introduction to btGhostObject:
When you go through the API documentation, please pay attention to the Inheritance diagram for each class you are searching, Actually it is the most important part of the class.
When you check BtGhostObject, please be aware that it is inherited from btCollisionObject. And Pay attention to btPairCachingGhostObject.
-----btCollisionObject
------------btGhostObject
-------------------btPairCachingGhostObject
------------btRigidObject
------------btSoftObject
So you see, it is at the equal level with the rigidbody and softbody.
And don't mess this btCollisionObject with btCollisionShape.
-----btCollisionShape
----------btConvexShape (This is what most people use, box, capsule, sphere etc)
----------btConcaveShape
----------btCompoundShape
One more little thing: Contact manifold is a small group that contains contact points. When two collision objects collide with each other, there may be one more manifolds between them, and each manifold contains no more than 4 contact points.
Why you want to use btGhostObject:
The reason why you use btGhostObject is that you only want to focus on some objects , to see what it collides with. By this way, you don't need to iterate over all contact manifolds in the dynamics world. You iterate only over the pairs of objects that you are interested in. (Check the tutorial: http://bulletphysics.org/mediawiki-1.5. ... d_Triggers)
However, even if you constrain your iteration to part of the whole world, the contact points information are still stored in the dynamics world cache, which means we still have to look up the allContacManifold to get the contact points we need.
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
Let's work it out:
First, you should add the header file into your cpp:
Code: Select all
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
Code: Select all
#include "btGhostObject.h"
Code: Select all
ghostObject = new btGhostObject();
ghostObject->setCollisionShape(new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))));
ghostObject->setWorldTransform(groundTransform);
m_dynamicsWorld->addCollisionObject(ghostObject);
m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
2. Use this ghostobject:
What I did is to use it in motorPreTickCallback (you can also find it in the same tutorial)
Setup the motorPreTickCallback:
Code: Select all
m_dynamicsWorld->setInternalTickCallback(motorPreTickCallback,this,true);
Code: Select all
void motorPreTickCallback (btDynamicsWorld *world, btScalar timeStep)
{
for(int i = 0; i < ghostObject->getNumOverlappingObjects(); i++)
{
btRigidBody *pRigidBody = dynamic_cast<btRigidBody *>(ghostObject->getOverlappingObject(i));
// do whatever you want to do with these pairs of colliding objects
}
Code: Select all
m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
About the Tutorial In the Wiki
If you try to implement the example about btGhostObject given at the tutorial from the Wiki, define your GhostObject as the btPairCachingGhostObject, not just as btGhostObject. Then it should work out.
Code: Select all
m_ghostObject = new btPairCachingGhostObject();
Code: Select all
// Prepare for getting all the contact manifolds for one Overlapping Pair
btManifoldArray manifoldArray;
// Get all the Overlapping Pair
btBroadphasePairArray& pairArray = ghostObject->getOverlappingPairCache()->getOverlappingPairArray();
int numPairs = pairArray.size();
for (int i=0;i<numPairs;i++)
{
manifoldArray.clear();
const btBroadphasePair& pair = pairArray[i];
//unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache:
//The next line fetches the collision information for this Pair
btBroadphasePair* collisionPair = dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
if (!collisionPair)
continue;
// Read out the all contact manifolds for this Overlapping Pair
if (collisionPair->m_algorithm)
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
for (int j=0;j<manifoldArray.size();j++)
{
btPersistentManifold* manifold = manifoldArray[j];
// Check if the first object in the Pair is GhostObject or not.
btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
for (int p=0;p<manifold->getNumContacts();p++)
{
const btManifoldPoint&pt = manifold->getContactPoint(p);
if (pt.getDistance()<0.f)
{
// Actually you can get the local information from this Overlapping pair, not just world Position
const btVector3& ptA = pt.getPositionWorldOnA();
const btVector3& ptB = pt.getPositionWorldOnB();
const btVector3& normalOnB = pt.m_normalWorldOnB;
/// work here
}
}
}
}
This is just the simplest implementation for btGhostObject, and I try to tell what I have done in my case. Though this is simple, it is enough for my case. Hope anyone can give more suggestions on how to use btGhostObject.
I think Bullet should need such little examples to show how each class works, we can provide our each small example and prepare for future's documentation.
I read through the posts below when I try to find information on this topic:
http://bulletphysics.org/Bullet/phpBB3/ ... f=9&t=3976
http://www.bulletphysics.org/Bullet/php ... 26&start=0