How to check for collisions before spawning objects.

Enlight
Posts: 8
Joined: Tue May 05, 2009 8:35 pm

How to check for collisions before spawning objects.

Post by Enlight »

We're working on a game using bullet for a while now, and we managed to perform all collision detection with only one function: convexSweepTest. We only have a btCollisionWorld, and we don't even need to call performDiscreteCollisionDetection at all. The scene is a bunch of static objects (convex / trimesh) and a few kinematic (boxes, spheres and capsules) that we move manually using the convexSweepTest.

So far, so good, but now we need to implement a function to detect if a kinematic object is currently touching any other static object (contact points) in order to spawn the object correctly. I've seen btKinematicCharacterController and the recoverFromPenetration code, so I've tried to implement the ghost object, but it didn't work as expected unless I call performDiscreteCollisionDetection before for every frame, which is expensive and I think unnecessary in this case since we only have to check contact points for an *specific* kinematic object, not the whole world.

What is the best way of doing this for an specific object?

Code: Select all

 getContactPointsFrom ( btCollisionObject ) 
without calling performDiscreteCollisionDetection ? (all objects).
The specified object could be ANY of the kinematic objects previously added to the world (different shapes).

We need to check if we can spawn an object in a specific location in the world.

Thanks in advance.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: How to check for collisions before spawning objects.

Post by Erwin Coumans »

In order to perform collision queries the aabb's and broadphase need to be updated at least. Instead of calling 'performDiscreteCollisionDetection' you can manually call:

Code: Select all

world->updateAabbs();
world->getBroadphase()->calculateOverlappingPairs(world->getDispatcher());
Instead of updating all aabb's you can update only the aabb of some objects, using

Code: Select all

world->updateSingleAabb(colObj);
Then try to use the ghost object (recoverFromPenetration).

Hope this helps,
Erwin
Enlight
Posts: 8
Joined: Tue May 05, 2009 8:35 pm

Re: How to check for collisions before spawning objects.

Post by Enlight »

Thank you Erwin, it works. But now I have a strange issue: I have a player (kinematic object) moving through the heightmap, if the object (ghost) moves in the X,Z axis, all contact points are updated accordingly, but *sometimes* when I only move in the Y axis (jump), there will remain the *same* contact point touching the ground, even when the object is not touching anything!, no matter how far I jump.

This means: there is a contact point, that has stuck in the ground, and do not get updated if I only move in the Y axis, as soon as I move in the XZ axis, the invalid contact point is removed (contact points correctly updated!).

Now, I solved this problem with an ugly hack: move the ghost object to 0,0,0 location in the world, dispatch collision pairs, move the ghost object again to the desired location and dispatch collision pairs again: *this is working* and I never receive and invalid contact point again, but its far from efficient.

I also tried to call always cleanProxyFromPairs() before doing anything but it didn't make a difference.

Why I'm having a report from a contact point that is no longer touching any objects? And why, moving the ghost object back and forth in the world solves this problems? Is there an elegant way to solve this 'cache' issue?

Thanks!
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: How to check for collisions before spawning objects.

Post by Erwin Coumans »

contactManifold->refreshContactPoints(transformA,transformB) needs to be called. This is usually part of performDiscreteCollisionDetection.

cleanProxyFromPairs after you moved the objects should discard all existing contact points.

If you don't want to call performDiscreteCollisionDetection, you will need to spend more time to learn the internals of Bullet.
Thanks,
Erwin
Enlight
Posts: 8
Joined: Tue May 05, 2009 8:35 pm

Re: How to check for collisions before spawning objects.

Post by Enlight »

I already was calling cleanProxyFromPairs after the objects where moved and the result was the same, but I didn't try with contactManifold->refreshContactPoints.

I'll try that, thanks Erwin!

Code: Select all

bool has_contacts(btCollisionObject* obj)
{
	// Setup ghost object
	m_ghostObject->setCollisionShape(obj->getCollisionShape());
	m_ghostObject->setWorldTransform(obj->getWorldTransform());
	world->updateSingleAabb(m_ghostObject);
	world->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_ghostObject->getBroadphaseHandle(),world->getDispatcher());

	// Check contact points
	world->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), world->getDispatchInfo(), world->getDispatcher());
	for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
	(...)
Enlight
Posts: 8
Joined: Tue May 05, 2009 8:35 pm

Re: How to check for collisions before spawning objects.

Post by Enlight »

OK, I've found the problem, I was cleaning the proxy from pairs in the world cache instead of the ghost cache:

Code: Select all

world->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_ghostObject->getBroadphaseHandle(),world->getDispatcher());
Should be this:

Code: Select all

m_ghostObject->getOverlappingPairCache()->cleanProxyFromPairs(m_ghostObject->getBroadphaseHandle(),world->getDispatcher());
Problem solved, thanks!