No performance difference between static and kinematic bodies?

Post Reply
GeanGean
Posts: 7
Joined: Sat Feb 04, 2023 11:04 pm

No performance difference between static and kinematic bodies?

Post by GeanGean »

So I'm trying to get a simulation going where even though I have minimal moving objects, I may have a very large amount of totally static things to collide with. Really the greater the number the better, 10000s at least, ideally hundreds of thousands. But none of them need to do anything except maybe collide with an object.


Anyway, I've noticed this doesn't really seem feasible at a decent framerate.
But what's more curious to me is there no difference in performance between:

Code: Select all

btMotionState* ms = new btDefaultMotionState(startTrans);
btRigidBody::btRigidBodyConstructionInfo info(0.0,ms,shape,btVector3(0,0,0));
body = new btRigidBody(info);
body->setCollisionFlags( btCollisionObject::CF_STATIC_OBJECT);
body->setFriction(0.5);
body->setRestitution(0.5);
body->forceActivationState(ISLAND_SLEEPING);
world->addRigidBody(body);
And:

Code: Select all

btMotionState* ms = new btDefaultMotionState(startTrans);
btRigidBody::btRigidBodyConstructionInfo info(0.0,ms,shape,btVector3(0,0,0));
body = new btRigidBody(info);
body->setCollisionFlags( btCollisionObject::CF_KINEMATIC_OBJECT);
body->setFriction(0.5);
body->setRestitution(0.5);
world->addRigidBody(body);
You'd think the kinematic objects would use up a bit more CPU time because they *might* move, where as the static objects would use up essentially zero CPU time, because they literally do nothing. Forcing deactivation also does nothing.

Any tips in general on how to reasonably get a greater amount of static bodies?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: No performance difference between static and kinematic bodies?

Post by drleviathan »

If the kinematic objects are not active then they are not much more expensive than static. If you were to bounce a dynamic object around the kinematic objects then they would activate, but since they are being "animated" by btDefaultMotionState which does nothing, then they will be deactivated again after two seconds.

If you want to increase performance you should try consolidating multiple static objects together to get a smaller number of them. Either combine them into large mesh objects using btBvhTriangleMeshShape, or maybe use btCompoundShape.

Somewhere in the high 10k objects you might notice the world->addCollisionObject() call starts to become expensive enough to notice, because the time to load the Nth object scales at O(N). This cost is being spent adding each new AABB to the broadphase overlap tree. Keeping the number of objects low will help you here.
GeanGean
Posts: 7
Joined: Sat Feb 04, 2023 11:04 pm

Re: No performance difference between static and kinematic bodies?

Post by GeanGean »

First off, I did find a magic line that did increase performance by a ton:

Code: Select all

 world->setForceUpdateAllAabbs(false); 
That said, I'm still on the quest to handle ever more objects.
drleviathan wrote: Sun Feb 05, 2023 7:07 am If you want to increase performance you should try consolidating multiple static objects together to get a smaller number of them. Either combine them into large mesh objects using btBvhTriangleMeshShape, or maybe use btCompoundShape.
Most ( 90%? ) of my static objects are various rectangular prisms made with btBoxShape. Would combining a bunch of these into a compound shape really improve performance? I guess I just assumed a more complex shape isn't necessarily better than 2 simpler ones.
drleviathan wrote: Sun Feb 05, 2023 7:07 am Somewhere in the high 10k objects you might notice the world->addCollisionObject() call starts to become expensive enough to notice, because the time to load the Nth object scales at O(N). This cost is being spent adding each new AABB to the broadphase overlap tree. Keeping the number of objects low will help you here.
I've actually noticed that adding objects with addCollisionObject results in lower FPS than addRigidBody for static objects.
Just to be clear, I don't care about *loading* time. I care about performance in FPS after everything has been added.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: No performance difference between static and kinematic bodies?

Post by drleviathan »

The broadphase keeps track of the AABBs and also overlapping AABB pairs between distinct objects that might need narrowphase collision check to compute the contact points (if any). Ignoring narrowphase costs... there is overhead in: (1) knowing all the AABBs and overlaps and (2) adding new AABBs to the data structure. By using a compound shapes to store static objects you reduce the complexity of the broadphase while slightly increasing the cost of the narrowphase check when there IS an overlap. So, if you have a big world and you clump nearby static objects into single shapes you may find it improves the runtime efficiency. If that is all you care about then perhaps it is worth trying.

One disadvantage to combining static objects is: if you want to move or remove just one of a group then the complexity of your own logic, and perhaps the CPU cost of removal, will go up. But again, if all you care about is runtime efficiency then you would be willing to pay this price.

For the benefit of fellow readers I supply this snippet from the code from btCollisionWorld.h:

Code: Select all

   ·///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs
   ·///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB)
   ·bool m_forceUpdateAllAabbs;
When setting it false you need to manually update the AABB of non-active objects... when you move them. Static objects would always need their AABBs updated when moved whereas dynamic and kinematic objects would only need them updated if you move them without also activating them.

You are probably already doing this, but I mention it for the record: if all of your static objects are using btBoxShape, and you have a lot of them, be sure to take advantage of "shape sharing" where two identically shaped objects reference same shape instance. This saves memory and improves cache coherence. There is no default ref-counting or shape-manager built into Bullet so you would have to write your own.
Post Reply