How can I use ghost objects?

lulzfish
Posts: 43
Joined: Mon Jan 03, 2011 4:26 pm

How can I use ghost objects?

Post by lulzfish »

Summary:
It would be great if I could get a short example of how to set up a ghost object and then how to check it for all colliding bodies.

Long version:
I need to create a box collision shape and then determine, at every frame, (Or callback-based, doesn't matter) whether anything is intersecting that shape.

I think btGhostObject or btPairCachingGhostObject can do this.
But how do I set that up?

I found this page: http://bulletphysics.org/mediawiki-1.5. ... hostObject

But it doesn't explain how to set up the ghost, and it doesn't explain why I would need the manifolds.
Ideally I would just get a list of btCollisionObject pointers that are all currently colliding with the ghost.
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How can I use ghost objects?

Post by Flix »

You may find this link useful:
http://bulletphysics.org/Bullet/phpBB3/ ... ost+object

Edit: The code in the link is a bit old. I think that the line:

Code: Select all

   //======================================================================================================
// This is the expensive operation to trigger the narrowphase detection:   m_dynamicsWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), m_dynamicsWorld->getDispatchInfo(), m_dynamicsWorld->getDispatcher());
//======================================================================================================
can be commented out...

It should be nice if someone could put all the stuff about ghost objects together in an ordered way (or in a demo for example...).
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How can I use ghost objects?

Post by Flix »

Flix wrote:It should be nice if someone could put all the stuff about ghost objects together in an ordered way (or in a demo for example...).
I've finally made a very simple and small appGhostObjectsDemo. Here's a screenshot of it:
appGhostObjectDemo.PNG
The large light yellow box is a btGhostObject and the big purple cylinder is a btPairCachingGhostObject. They move around in circle and the objects they hit are pushed up by an impulse.
Here is the demo source code:
GhostObjectsDemo.zip
Hope it's good enough for all the people that have problems using ghost objects.
You do not have the required permissions to view the files attached to this post.
Last edited by Flix on Thu Jul 21, 2011 10:02 am, edited 1 time in total.
lulzfish
Posts: 43
Joined: Mon Jan 03, 2011 4:26 pm

Re: How can I use ghost objects?

Post by lulzfish »

I'm reading through that now.
What is the difference between a regular GhostObject and a PairCachingGhostObject? IS there some situation where one is clearly better?

Edit: I made my builder into a btPairCachingGhostObject (again), following your example.
The code was like :twisted: and I was like :cry:
And then the result was... the same as when I used a regular btCollisionObject and iterated over all the collision pairs.

It still has this really annoying "hysteresis" effect, it seems to be caching the AABB and giving false positives until I move it away and then back.

http://blip.tv/file/4610543?filename=Lu ... hes966.m4v

It is very clear around 10 seconds into this video. The builder turns red if it has a collision, to prevent the user from spawning objects inside other objects. But in my case, it doesn't update quite right when moving.

Edit: Around line 364 of your GhostObjectsDemo.cpp, the program includes objects that have at least one contact point with the ghost object. I commented it out in my program. It still seems to report collisions fine, but the "hysteresis" and its false positives appear to be gone.

I wonder why that line is used in your program, but breaks mine?

Edit: Spoke too soon. There is still a weird corner case that gives a false positive, I'll keep messing with it until it works, or until I understand it.
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How can I use ghost objects?

Post by Flix »

lulzfish wrote:What is the difference between a regular GhostObject and a PairCachingGhostObject? IS there some situation where one is clearly better?
Well,as far as I know the pair caching ones give additional access to their collision manifold (I think the demo explains that).
lulzfish wrote:And then the result was... the same as when I used a regular btCollisionObject and iterated over all the collision pairs.
Yes, actually it's what they're supposed to do...
lulzfish wrote:it seems to be caching the AABB and giving false positives until I move it away and then back.
Honestly I made the demo for the community and not to solve your particular problem... anyway maybe you can try to clean the collision proxy manually. For common objects this can be done like this:

Code: Select all

btWorld->getPairCache()->cleanProxyFromPairs(myBody->getBroadphaseProxy(),btWorld->getDispatcher());
, but I'm almost sure that there's a similiar (but different) line that can be used with ghost object... (or maybe this line is enough). You may try and see.[Edit:] Probably you can just remove/readd the ghost object to the world when you want to clean the manifold as a quick method to test if it works.Alternatively you may use aabb/contact queries instead of ghost objects.
lulzfish wrote:Edit: Around line 364 of your GhostObjectsDemo.cpp, the program includes objects that have at least one contact point with the ghost object.
Well, that's because it seems that the manifold can be created before contact points are added (at least it is what I experienced when I made that code): in short first a manifold is created and then (the manifold is cached and updated) contact points are added.
lulzfish
Posts: 43
Joined: Mon Jan 03, 2011 4:26 pm

Re: How can I use ghost objects?

Post by lulzfish »

Flix wrote:

Code: Select all

btWorld->getPairCache()->cleanProxyFromPairs(myBody->getBroadphaseProxy(),btWorld->getDispatcher());
, but I'm almost sure that there's a similiar (but different) line that can be used with ghost object...
Thanks, it seems to work perfectly if I run that, then step the simulation, then iterate over all pairs. But in that case, I can switch back to a regular object that just has no collision response, I think.
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How can I use ghost objects?

Post by Flix »

lulzfish wrote:Thanks, it seems to work perfectly if I run that, then step the simulation, then iterate over all pairs. But in that case, I can switch back to a regular object that just has no collision response, I think.
Well I think that you can use a ghost object with no collision response + ghost object manifold processing (in case of btPairCachingGhostObject), or a regular object with no collision response + global manifold processing.
(I'm not sure that the fact that an object has collision response or not is in some relations with the manifold creation and update...; for sure you can use it as a sensor.)
The line I posted should work for the latter case (i.e.: regular object + global manifold processing: ghost objects might need a similiar one, but I'm not sure about it).
Anyway probably you can remove/readd the object to the world to be sure that the proxy get cleaned from pairs in both cases.

Thus I think the point is: why and when should I clean the proxy from pairs?
The answer to the first question depends on the application you're developing: do you get any improvement if you do it?
The second answer is relative to the frequecy of the call.
Every frame? Probably no, since in that case a plain aabb/contact pair query could be more efficient (not 100% sure about it).
Maybe just in critical situations that depend on the application (for example when you move the ghost object to a very distant point or maybe when you spawn new objects inside it..., I don't know...).

In short: I don't know if this can be a solution to your application... :oops:
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How can I use ghost objects?

Post by Flix »

Just to say that I updated GhostObjectsDemo.zip.

The line:
m_dynamicsWorld->getDispatcher()->dispatchAllCollisionPairs(m_pairCachingGhostObject->getOverlappingPairCache(), m_dynamicsWorld->getDispatchInfo(), m_dynamicsWorld->getDispatcher());
has been commented out and findPair(...) is used.

It should be a bit faster.
DanielS
Posts: 4
Joined: Sun Jan 29, 2012 7:54 pm

Re: How can I use ghost objects?

Post by DanielS »

Thanks for the demo, but do you have any idea how to make it so that it detects static bodies?

It only reports collisions with dynamic bodies (mass > 0). I'm sure it's possible, I've seen a few posts saying they managed it. It also worked for me when I used the wrong method of deriving from btGhostPairCallback, but not since I used this example.

Cheers.
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: How can I use ghost objects?

Post by Flix »

DanielS wrote:It only reports collisions with dynamic bodies (mass > 0).
Not true.
If you modify the code this way:

Code: Select all

static void ProcessObectsInsideGhostObjects(btAlignedObjectArray < btCollisionObject* >& objs, const bool isPairCachingGhostObject)	{
	for (int j=0,jsz=objs.size();j<jsz;j++) {
		if (objs[j]->isStaticOrKinematicObject()) printf("StaticOrKinematicObject detected\n"); // New
			
		btRigidBody* b = btRigidBody::upcast(objs[j]);
		if (b) {
			b->activate();
			b->applyCentralImpulse(isPairCachingGhostObject ? btVector3(0,0.5,0) : btVector3(0,0.25,0));
		}	
	}	
}
you can see from the console whether the ghost objects collide or not with the static ground (you can play around with its position at line 102 (or so):

Code: Select all

groundTransform.setOrigin(btVector3(0,-50,0)); // try -52 or -48 and see the difference.