Recently I was wondering why stepSimulation() took about 10% of our CPU time even though we only have a single _deactived_ dynamic object and a lot (~10000) static objects in a scene.
I debugged into Bullet 2.73-sp1 and saw this inside stepSimulation(...)
Code: Select all
if (numSimulationSubSteps)
{
saveKinematicState(fixedTimeStep);
applyGravity();
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
for (int i=0;i<clampedSimulationSteps;i++)
{
internalSingleStepSimulation(fixedTimeStep);
synchronizeMotionStates();
}
}
synchronizeMotionStates();
clearForces();
does something like this:
Code: Select all
for (int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
...
}
}
I'm aware that a single upcast from btCollisionObject to btRigidBody isn't exactly that much costly on it's own.
But I figure it gets somewhat relevant if you have 10000 collision objects and fixed timestep of 1/60.
This is only a estimation, but let's say there are 10 upcast loops per stepSimulation call:
10* 10000 * 60 = 6.000.000 upcasts per frame. That's a little much ...
I made a small test with a base class and 2 different derived classes:
6.000.000 casts take about 180 milliseconds on my PC.
My suggestion is to optimize this by doing the upcast only one itme for each object and storing the pointers in sperated lis which is then used by all functions that follow. Another (better?) option would be to insert rigidbodies into that list when addRigidBody() is called (and remove them from the list at the time removeRigidBody() is called ).
This would cost some memory of course.
Another ( more simple improvement ) I suggest:
Code: Select all
for (int i=0;i<clampedSimulationSteps;i++)
{
internalSingleStepSimulation(fixedTimeStep);
synchronizeMotionStates();
}
}
if( clampedSimulationSteps < 1) // HERE ///////////////////////
synchronizeMotionStates();
I'm posting this because I plan to make these changes and to see how it works out.
Unfortunatly I'm short of spare time currently. Maybe I can save my time if someone here can tell me if there is something fundamentally wrong with my ideas.
Or maybe someone had have similar problems and can tell me about his experiences.
Thanks for your time.