Dynamics on an Opt-In Basis?

Aardwolf
Posts: 13
Joined: Thu Jul 07, 2011 2:57 am

Dynamics on an Opt-In Basis?

Post by Aardwolf »

From what I can tell Bullet allows you to specify, for some pair of collision objects, whether to do a collision check / collision response... is it possible to do this on an opt-in basis instead?

What I'd like to be able to do is something like the broad phase, but instead of calling some function for each of the O(n²) pairs and returning bools, using a function like "enable collisions for this pair". If there's no other way to do this, I guess I will have to keep a

Code: Select all

hash_map<btCollisionObject*, hash_set<btCollisionObject*> >
and use that in the broadphase.

(Maybe I'm missing something obvious?)
Aardwolf
Posts: 13
Joined: Thu Jul 07, 2011 2:57 am

Re: Dynamics on an Opt-In Basis?

Post by Aardwolf »

On closer examination, I notice that in struct btDbvtBroadphase there is a member btOverlappingPairCache* m_paircache, and that there is a method btBroadphasePair* btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1), which is called in the function void btDbvtTreeCollider::Process(const btDbvtNode* na, const btDbvtNode* nb)...

That btOverlappingPairCache::addOverlappingPair method looks relevant, but it looks like there are a lot of hoops I would have to jump through to make it do what I want.



But to rephrase my original question: how could I wrap existing Bullet functionality to get something like this:

Code: Select all

void MyWrapper::clearCollisionPairs();
void MyWrapper::addCollisionPair(btCollisionObject* a, btCollisionObject* b);
Aardwolf
Posts: 13
Joined: Thu Jul 07, 2011 2:57 am

Re: Dynamics on an Opt-In Basis?

Post by Aardwolf »

Alternatively, is there some "correct" way to have multiple active ragdolls at once, without a huge performance hit?

The ragdoll I am using has 21 bones; I get the same performance hit when I create the rigid bodies without adding any constraints between them. Thus I have concluded that it must be an issue with the collision detection/dynamics, not the constraints.

I read an article online about custom collision filtering, but AFAICT using the techniques in that article the best I can do is opt out of collisions... but I still have to call a function O(n²) times and return whether I do or don't want collisions... but when I have a handful of ragdolls, that gets really big, really fast, and the btDbvtBroadphase isn't keeping up.
Mako_energy02
Posts: 171
Joined: Sun Jan 17, 2010 4:47 am

Re: Dynamics on an Opt-In Basis?

Post by Mako_energy02 »

First, I want to say I saw your tiny text in the other post and it made me laugh pretty hard, so here I am.

If you look at the documentation for the base class of btOverlappingPairCache, here, you'll see there is a remove function on there as well. You could get a reference to the overlapping pair array by calling "getOverlappingPairArray()", and iterate over it's members calling the remove function and passing in the two bodies in the pair you are iterating over. That would effectively let you clear the entire cache. From there you can use add to add whichever pairs you want. Or more directly you could only remove the ones you don't want to have collisions for.

Alternatively you could use Collision Groups and Collision Masks. This is a bit more generic of a solution and may not suit your needs. But essentially the Group is what the object belongs to and the Mask is what it will collide with. I think there are 5 or 6 predefined groups, and from there you can make your own groups as you see fit, provided the number is both a short int, and a power of two. So I think that means you can have around ~10 more groups defined yourself, not gonna do the math right now. Also note that the mask(what the object will collide with) can have any combination of groups in it as you want/need. In fact non-static rigid bodies by default have the "AllFilter" passed in as it's mask. Really this is only useful if you know an objects collision behavior won't need to change while it's in the world.

I don't have any experience with ragdolls personally, but how are you constructing them? And what are you using for their shapes? I've tinkered a bit with shapes and numerous collisions myself and found that anything beyond a basic primitive or convex hull can degrade your performance really fast. But this is assuming you are having the objects overlap and collide each frame. Which may not be the case.
Aardwolf
Posts: 13
Joined: Thu Jul 07, 2011 2:57 am

Re: Dynamics on an Opt-In Basis?

Post by Aardwolf »

Hm... getOverlappingPairArray... could be useful, if I decide to go that route.

I had read about the collision groups/masks, but I couldn't see any way to use that for my particular situation. That seems to be aimed at specifying categories of objects that can interact. In my case, however, there are no rules that determine whether one rigid body can interact with another based on what type of rigid body they are---every type of rigid body can interact with every other type. Rather, I want to only do collision tests between bones in different ragdolls if the two ragdolls are close together.

My ragdolls are made of btMultiSphereShapes. One bone has 7 spheres, while the other 20 bones have 2 spheres each. Part of why I chose to use btMultiSphereShape was because the coordinates for creating one are absolute, whereas many other collision shapes are centered around the origin. However, I suppose that if the collision shape turns out to be the problem, I could manage with some other primitive.


Edit: I did a test, simultaneously creating 10 ragdolls (well, spawning 10 enemies 50 meters off the ground and having them fall to their deaths), first using the original btMultiSphereShapes, and then again using btSphereShapes instead. Before they hit the ground, I had 111 FPS. When they hit the ground, they switch from being 1 rigid body each to being ragdolls with 21 rigid bodies each, and the framerate drops to 5 FPS for btMultiSphereShape, and 9 FPS for btSphereShape. Plain spheres are faster, but not enough to make a difference.
Last edited by Aardwolf on Mon Aug 01, 2011 3:39 am, edited 1 time in total.
Mako_energy02
Posts: 171
Joined: Sun Jan 17, 2010 4:47 am

Re: Dynamics on an Opt-In Basis?

Post by Mako_energy02 »

I'm not positive about this, but if it's just the origin/pivot of the shape that you are worried about, you could construct a compound shape and put just one shape in it with the specified transform. Note: I've never actually tried this before, but it was just an idea that came to me.
Aardwolf
Posts: 13
Joined: Thu Jul 07, 2011 2:57 am

Re: Dynamics on an Opt-In Basis?

Post by Aardwolf »

Hm... I'm going to feel silly if it's as simple as this, but... would it work to have the bones of the ragdoll as parts of a btCompoundShape?
Mako_energy02
Posts: 171
Joined: Sun Jan 17, 2010 4:47 am

Re: Dynamics on an Opt-In Basis?

Post by Mako_energy02 »

Each part of the ragdoll under the same btCompound shape? I don't think it would, no. Physics forces would be applied to the body as a whole that way(cause this would mean you have only one Rigid body as well), and wouldn't get per-limb effects.

The only exception I could see is if you have an animation driven ragdoll that only needed really basic colision detection. Then you could advance your animation, get the new bone transforms, update the btCompoundShape, and then let physics run. But this is an odd edge case, so I'm assuming it doesn't apply to you.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Dynamics on an Opt-In Basis?

Post by Erwin Coumans »

It is best if you do some profiling, to make sure where time is spend.

Right after world->stepSimulation(...);
//add the following line
CProfileManager::dumpAll();

You can customize if collision detection is necessary for each pair, by deriving your own class from btOverlapFilterCallback,
and override the virtual 'needBroadphaseCollision' method. See Bullet\src\BulletCollision\BroadphaseCollision\btOverlappingPairCache.h

Then call pairCache->setOverlapFilterCallback(btOverlapFilterCallback* callback)

Thanks,
Erwin
Aardwolf
Posts: 13
Joined: Thu Jul 07, 2011 2:57 am

Re: Dynamics on an Opt-In Basis?

Post by Aardwolf »

Oh wow, I didn't notice this got another reply.

Ah yes, the needsBroadphaseCollision function is the O(n²) function I was referring to in my original post. Is needsBroadphaseCollision called once every step of the simulation, or only once per pair? I had figured it was a once-every-tick thing, but if it's only computed once per pair and the result gets cached, then that might actually work. Is there a way to force recalculation of the cache, either partially or entirely?