# Bullet - btGhostObject

## Recommended Posts

Hello,

I have googled and for quite some time now and i seem to only find the same type of answer.
And the result im getting is so strange.

The goal is to create a trigger volume (for now a box) that should trigger events whenever something enters it.
According to the Bullet, btGhostObject is the way to go for simple triggers.

This is my code for setting up bullet.

m_BulletBroadphase = new btDbvtBroadphase();
m_BulletConfiguration = new btDefaultCollisionConfiguration();
m_BulletDispatcher = new btCollisionDispatcher( m_BulletConfiguration );
m_BulletSolver = new btSequentialImpulseConstraintSolver;
m_BulletDynamicsWorld = new btDiscreteDynamicsWorld( m_BulletDispatcher, m_BulletBroadphase, m_BulletSolver, m_BulletConfiguration );
m_BulletDynamicsWorld->setGravity( btVector3(0.0f, -50.0f, 0.0f) );
m_BulletDynamicsWorld->getPairCache()->setInternalGhostPairCallback( new btGhostPairCallback() );

btGhostObject

// create trigger volume
btTransform world( btQuaternion(rotation.yaw, rotation.pitch, rotation.roll), btVector3(location.x, location.y, location.z) );
m_GhostObject = new btGhostObject();
m_GhostObject->setCollisionShape( new btBoxShape(btVector3(10.0f, 5.0f, 10.0f)) );
m_GhostObject->setWorldTransform( world );

....

// check for intersections
btAlignedObjectArray< btCollisionObject * > & pairs = m_GhostObject->getOverlappingPairs();
for( pmInt32 i=0; i<pairs.size(); ++i )
{
....
}

And finally, the object that i use to test the trigger with

btDefaultMotionState * motionState = new btDefaultMotionState();
btVector3 inertia;
m_Shape = new btBoxShape(btVector3(5.0f, 5.0f, 5.0f));
m_Shape->calculateLocalInertia( m_Mass, inertia );
btRigidBody::btRigidBodyConstructionInfo rigidBodyCI( m_Mass, motionState, m_Shape, inertia );
m_Body = new btRigidBody( rigidBodyCI );

The simulation looks correct, the rigid body spawns highup in the air and falls down correctly.
The btRigidBody is transformed to location(0.0f, 40.0f, 0.0f)
And the trigger is transformed to location(0.0f, 5.0f, 0.0)

The problem im getting is that in the triggers intersection check i instantly get a overlapping pair.
Even though they are really far apart and their AABBs cant intersect.
I also checked their worldTransforms, they indicate that they are positioned correctly. I went as far to even set the interpolatedWorldTransform but
it dident help.

Have anyone else had this problem or am i just missing something basic here?

##### Share on other sites

I cannot spot directly the mistake you've got, it should work I guess...

However a few weeks ago I had a problem with ghost objects with Collision Shapes that had scaling. It really did not work. After fighting a few battles, I've switched to  btCollisionWorld::ContactResultCallback (see contactTest in btCollisionWorld or btDynamicsWorld for details). It works better for me and the rigid body used for triggering doesn't need to be in the dynamicsWorld for this to work.

##### Share on other sites

Yeah, all the informaiton i can find seem to say that im doing it right.
But yet it yeilds strange results

I read abit about the contact callback thing.
But i felt hesitant towards it, since even Bullet says the preferred way is to use ghost objects.

Guess i have to do some experiments with it and see what happens

##### Share on other sites

What code do you have inside your getOverlappingPairs loop? From memory the internals of that loop are kind of complicated.

 Checked my code...
I'm using btPairCachingGhostObject and checking for collisions with something like:

for( int i=0, end=m_ghost->getNumOverlappingObjects(); i != end; ++i )
{
btCollisionObject* c = m_ghost->getOverlappingObject( i );
TriggerContactResultCallback results;
m_world->contactPairTest( m_ghost, c, results );
if( results.m_hit )
...
}

##### Share on other sites

Right now, im not doing anything.

Is my understanding wrong here.
Shouldnt i only get overlapping pairs when the AABBs intersect?

##### Share on other sites

You get overlapping pairs when the broadphase algorithm has identified a potential overlap. If the broadphase is working off AABB's, then yes. If the broadphase is using some other algorithm, then possibly no.

##### Share on other sites

Thanks for explaning.
Tinkering with the code, i think im starting to understand what the actuall problem is...

If i put a log inside the loop i get a hit the first frame, then i stop getting hits.
So im thinking im doing something wrong when im trying to transform the btRigidBody.

This is my naive approach

btTransform world( btQuaternion(p_Rotation.yaw, p_Rotation.pitch, p_Rotation.roll), btVector3(p_Location.x, p_Location.y, p_Location.z) );
m_Body->setWorldTransform( world );
m_Body->getMotionState()->setWorldTransform( world );

##### Share on other sites

That should be fine for teleporting an object. If you're teleporting an object every frame though, you may want to look into implementing it as a kinematic object instead though -- teleporting an object won't result in good interactions when it collides with other objects, but when moving a kinematic object it will collide as normal.

I found that when I teleport ghosts, I had to notify the broadphase for some reason that I don't understand...

m_ghost->setWorldTransform( tx );
m_world->updateSingleAabb(m_ghost);

I also can't remember why I changed from btGhostObject to btPairCachingGhostObject at some point...

##### Share on other sites

I think for now, im going to simply solve my problem by not allowing triggers to take action for the first frame they are alive.
Sure... Not the best option, but atleast i can move forward for now.

So to sum it up, i thought i had a problem with btGhostObject.
It turned out to be a problem with teleporting objects instead.

Thanks for all the help

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account

• 18
• 11
• 17
• 9
• 51
• ### Forum Statistics

• Total Topics
631397
• Total Posts
2999795
×