stepSimulation() and ticks

Post Reply
bill23
Posts: 2
Joined: Sat Jul 06, 2013 9:40 pm

stepSimulation() and ticks

Post by bill23 »

(disclaimer: sorry for my bad english)

I have some question regarding stepSimulation() in btDiscreteDynamicsWorld (bullet-2.81-rev2613).

I keep track of physics ticks incrementing a variable inside the callback of dynamicsWorld->setInternalTickCallback().
I checked and discovered that the ticks returned by stepSimulation() and the ticks of the callback are not the same.

I see that stepSimulation() returns 'numSimulationSubSteps', but the code do the follow:

Code: Select all

	int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
	saveKinematicState(fixedTimeStep*clampedSimulationSteps);
	applyGravity();

	for (int i=0;i<clampedSimulationSteps;i++)
	{
		internalSingleStepSimulation(fixedTimeStep);
		synchronizeMotionStates();
	}

1) I think that re return value must be clampedSimulationSteps...

2) What's the point updating the motion states every internalSingleStepSimulation() ?
We can safely remove it out of the for loop. Or not?


My real problem was the method used by bullet to calculate the substeps. So, in the end I inherited the btDiscreteDynamicsWorld and implemented this version without noticing any problem (note: this version don't use variable timeStep).

Any feedback is much apreciated.


Code: Select all

    int    BraveNewWorld::stepSimulation2(double elapsed, const int& maxSubSteps, const double& fixedTimeStep) {
        startProfiling(elapsed);
        BT_PROFILE("stepSimulation");


        double max_time =  fixedTimeStep * double( maxSubSteps ) ;
        m_localTime        +=   (elapsed > max_time) ?  max_time : elapsed;

        double num_ticks;
        /* double tick_interpolator  = */ modf( m_localTime / fixedTimeStep , &num_ticks);
        m_localTime        -=   fixedTimeStep * num_ticks;



        int numSimulationSubSteps = int(num_ticks);


        //process some debugging flags
        if (getDebugDrawer())
        {
             btIDebugDraw* debugDrawer = getDebugDrawer ();
             gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
        }
        
        if (numSimulationSubSteps) {
            saveKinematicState(fixedTimeStep*double(numSimulationSubSteps));
            applyGravity();

            for (int i=0;i<numSimulationSubSteps;i++) {
                internalSingleStepSimulation(fixedTimeStep);
            }
        }
       

        synchronizeMotionStates();
        clearForces();

#ifndef BT_NO_PROFILE
     CProfileManager::Increment_Frame_Counter();
#endif //BT_NO_PROFILE


        return numSimulationSubSteps;
    }

STTrife
Posts: 109
Joined: Tue May 01, 2012 10:42 am

Re: stepSimulation() and ticks

Post by STTrife »

I think it's more up to Erwin or someone with more expertise as I to comment on this, but I think moving the update-motionshapes outside the loop like that is fine when the update of your graphics renderer happens in the same process, i.e. after or before calling StepSimulation.
But in a case where your graphics renderer runs in another process, I could imagine that it looks smoother if the motion states are updated for each internal tick. cause it might be rendered between internal ticks. But besides that, I don't think you would actually break anything by moving it outside the loop.
However, I also doubt if it will give a noticable performance improvement, because compared to collosion checking and solving.. updating motion states is probably peanuts (but yeah...if you use the same process for rendering, any optimization is welcome I guess?)


As for point 1: yeah I think it would be more sensible to return the clamped number of substeps, I think people would expect the number of REAL substepts taken to be returned, and not the number of substeps that would be taken in case there was no maximum.
bill23
Posts: 2
Joined: Sat Jul 06, 2013 9:40 pm

Re: stepSimulation() and ticks

Post by bill23 »

Thanks STTrife for the feedback.
You're right: I'm using a single thread for everything right now (shame on me).

But AFAIK, the synchronizeMotionStates() in Bullet interpolates between the last 2 transforms computed by the library.
So I imagine that bullet save these 2 transforms internally, and they change every tick (the 'current' becomes the 'previous' and what computed during last tick becomes the new 'current', and I do the same in my program for other things).

The motion states are useful for rendering purpose, so I think the interpolation IMO should be made (if needed) one for every rendering frame.
I don't actually understand how using two thread can be a problem for this, but I must admit I have not much experience in multi-threading.

Thanks anyway!
STTrife
Posts: 109
Joined: Tue May 01, 2012 10:42 am

Re: stepSimulation() and ticks

Post by STTrife »

In the case that the physics engine is updating in a separate thread, the rendering code in another thread might be running at a much higher FPS. So any update in using the motion states will show immediately in the rendering.
Now if some reason the thread with the physics updates is delayed (it might be doing other logic that is taking longer), it might take 2 or 3 internal steps at once. If you only update the motions states after those 3 internal steps, you'll get less smooth visual movement compared to when it would update them each internal time step.

When you say
The motion states are useful for rendering purpose, so I think the interpolation IMO should be made (if needed) one for every rendering frame.
it seems like you assume that a frame render only takes place after bullet has done it's work, but that's why I started about the separate thread idea: it's doesn't have to be that way. Perhaps it's more accurate to say that you want to update the motions states at a smooth rate like 60 fps.
przecze
Posts: 3
Joined: Mon Jun 17, 2019 12:15 pm

Re: stepSimulation() and ticks

Post by przecze »

Hello there,
I encountered the same problem and create an issue for, but unfortunately no response in over a year:
viewtopic.php?t=5066
My idea to deal with this problem is either to disable clamping (by setting maxSubSets to some high number or 0) or use some other method to calculate the actual steps (setInternalTickCallback?)
Post Reply