[Solved]Ghost object is allways in collision

Post Reply
andrew_the_red
Posts: 2
Joined: Tue Oct 06, 2015 7:47 am

[Solved]Ghost object is allways in collision

Post by andrew_the_red »

Hello everybody!
Ok, so i've implemented bullet for rigid body simulation, and it works perfectly. The problem is, that when i add a ghost object to the dynamic world, it shows me that it's always intersecting with something, even when I move it way outside of other objects aabb's.

For start, I do this initialisation:
broadphase = new btDbvtBroadphase();
broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
collision_config = new btDefaultCollisionConfiguration();
collision_dispatcher = new btCollisionDispatcher(collision_config);
dispatcher_info= new btDispatcherInfo();
constraint_solver = new btSequentialImpulseConstraintSolver;
dynamics_world = new btDiscreteDynamicsWorld(collision_dispatcher,broadphase,constraint_solver,collision_config);


the ghost object is created as follows:

ghost_object[0] = new btPairCachingGhostObject();
collision_shape= new btBoxShape(half_extents);
ghost_object[0]->setCollisionShape(collision_shape);

btTransform bullet_matrix;
bullet_matrix.setOrigin(btVector3(5,5,0));
ghost_object[0]->setWorldTransform(bullet_matrix);
ghost_object[0]->setCollisionFlags(ghost_object[0]->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE );
ghost_object[0]->setUserIndex(33); dynamics_world->addCollisionObject(ghost_object[0],btBroadphaseProxy::SensorTrigger,btBroadphaseProxy::StaticFilter);


It doesn't matter if the collision shape is bigger or smaller, it always detects that it is in collision with all the objects of the given filter (static objects in this case).
I tried implementing the static objects, as boxes, static planes, and triangle meshes, i get the same result.
What I found strange, is that if I look at the proxy of the ghost object, it's aabbMin and aabbMax are very, very large negative and positive values respectively.
Also, I tried:
dynamics_world->updateAabbs();
dynamics_world->getBroadphase()->calculateOverlappingPairs(dynamics_world->getDispatcher());

but sadly, with the same result.

What I need is a ghost object that I can move with the character so that it will detect when a wall is in front of him, but for starters, I need to know how to set up the ghost object so that it only detects what is colliding with it's aabb.
Also, if I use only a collision object (no ghost) i get the exact same results.

if I move the collision object with the character, it detects collision propperly the first time, only that after that is says that it's colliding continously, until I exit the aabb of the static object.
The character is a dynamic rigid body which I control with forces and impulses. After each physics tic, I update the collision object's transform acordingly

The tick callback:

btManifoldArray manifoldArray;
btBroadphasePairArray& pairArray =
ghost_object->getOverlappingPairCache()->getOverlappingPairArray();
int numPairs = pairArray.size();

for (int i = 0; i < numPairs; ++i)
{
manifoldArray.clear();

const btBroadphasePair& pair = pairArray;

btBroadphasePair* collisionPair =
dynamics_world->getPairCache()->findPair(
pair.m_pProxy0,pair.m_pProxy1);

if (!collisionPair) continue;

if (collisionPair->m_algorithm)
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);

for (int j=0;j<manifoldArray.size();j++)
{
btPersistentManifold* manifold = manifoldArray[j];

bool isFirstBody = manifold->getBody0() == ghost_object;
bool isSecondBody = manifold->getBody1() == ghost_object;

if (isFirstBody || isSecondBody)
manifold_nr = manifold->getNumContacts();
}
}

nr = ghost_object->getNumOverlappingObjects(); // this allways returns something different from 0


I thank you for your time!
Last edited by andrew_the_red on Wed Oct 07, 2015 2:51 pm, edited 1 time in total.
LHLaurini
Posts: 9
Joined: Tue Sep 08, 2015 6:40 pm

Re: Ghost object is allways in collision

Post by LHLaurini »

Hi!

Before I start I want to give you a tip: always use code tags for code.

Code: Select all

Like this: [code]Code here
[/code]

My guess: Delete this line:

Code: Select all

nr = ghost_object->getNumOverlappingObjects(); // this allways returns something different from 0
Instead, check this:

Code: Select all

manifold_nr = manifold->getNumContacts();
If it still doesn't work: I don't know what it could be, but enabling debug drawing would be a good idea. It may take a day or two to implement, but it will be much easier to debug your physics. You can read a little more about it on the page 11 of the Bullet User Manual. I recommend you to take a look at the Bullet examples - they're pretty good. If you misplace a object it will be a piece of cake to find it.

Also, take a look at my function (I took some unnecessary things out):

Code: Select all

bool Physics::CheckGhost(btPairCachingGhostObject* Ghost)
{
	btManifoldArray ManifoldArray;
	btBroadphasePairArray& PairArray = Ghost->getOverlappingPairCache()->getOverlappingPairArray();

	for (int i = 0; i < PairArray.size(); i++)
	{
		ManifoldArray.clear();

		btBroadphasePair* CollisionPair =
			PhysicsManager.DynamicsWorld.getPairCache()->findPair(PairArray[i].m_pProxy0, PairArray[i].m_pProxy1);

		if (!CollisionPair)
		{
			continue;
		}

		if (CollisionPair->m_algorithm)
		{
			CollisionPair->m_algorithm->getAllContactManifolds(ManifoldArray);
		}

		for (int j = 0; j < ManifoldArray.size(); j++)
		{
			for (int p = 0; p < ManifoldArray[j]->getNumContacts(); p++)
			{
				const btManifoldPoint& Point = ManifoldArray[j]->getContactPoint(p);

				if (Point.getDistance() < 0.0f)
				{
					return true;
				}
			}
		}
	}

	return Collided;
}
It returns true if colliding or false otherwise. Notice the "if (Point.getDistance() < 0.0f)" line. It is very important because this line will differentiate a AABB collision (distance would be greater than zero) from a actual ColisionObject collision (distance would be less than zero).
andrew_the_red
Posts: 2
Joined: Tue Oct 06, 2015 7:47 am

Re: Ghost object is allways in collision

Post by andrew_the_red »

Thank you for the information!
I have managed to solve my problem. When using the function you posted, I stil got the same results. Using the manifold, I could find if the object's true shape was in collision, but that didn't save me from iterating through all the pairs that the ghost object had. For example, if I had 30 static objects, even very far, my puny ghost object would be very enthusiastic and create pairs for each of them.

In the end, my problem was in the initialisation of the ghost object's transform:

Code: Select all

btTransform bullet_matrix;
bullet_matrix.setOrigin(btVector3(5,5,0));
In this way, the "m_basis" parameter of the transform remains uninitialised and this leads to a huge aabb (from -6000000 to +6000000 on each axis) which intersects, oviously, with everything.

The solution was to initialise the transform as this:

Code: Select all

btTransform bullet_matrix(btQuaternion(0,0,0,1),btVector3(5,5,0));
Also, it works perfectly if I attach the ghost to a moving rigid body, by updating it's transform accordingly.

Ah, the classy pitfalls of spare time self learning...

Anyway, the "if (Point.getDistance() < 0.0f)" is surely something that I think would come in handy very soon. Once again, my thanks!
LHLaurini
Posts: 9
Joined: Tue Sep 08, 2015 6:40 pm

Re: Ghost object is allways in collision

Post by LHLaurini »

Glad to hear you've got it to work. As I've already said, if you had implemented debug drawing you would've spent much less time trying to fix your problem. But anyways, good luck!
Post Reply