Page 1 of 1

stepSimulation() and ticks

Posted: Sat Jul 06, 2013 10:57 pm
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;
    }


Re: stepSimulation() and ticks

Posted: Tue Jul 09, 2013 3:40 pm
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.

Re: stepSimulation() and ticks

Posted: Sat Jul 13, 2013 11:01 pm
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!

Re: stepSimulation() and ticks

Posted: Sun Jul 14, 2013 11:00 pm
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.

Re: stepSimulation() and ticks

Posted: Thu Dec 31, 2020 1:28 pm
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?)