Loading...
You are not logged-in Login/Register





  • Posts   Search Threads
  • S_WAugust 30, 2008 1:22 PM PDT   
    Stepping the simulation correctly

    Hi,

    I'm updating the physics using a "time-slicer" to ensure constant stepping at different frame times:


    // time accumulator
    static float elapsed = 0.0f;
    elapsed += timeSinceLastFrame;   

    // update using time slicer
    while( elapsed > m_timestep )
    {
    m_world->stepDeltaTime( m_timestep );
    vdb->step( m_timestep );
    updateDisplay( m_world );
    elapsed -= m_timestep;
    m_physicsStepsLastFrame++;
    }

    This generally works quite well as illustrated in the following part of a screenshot:



    As you can see one physics step is performed per frame (framerate is locked at 60 fps, m_timestep = 1.0f / 60.0f ).

    But on some machines, in certain situations (probably due to process scheduling) the frametimes get very "wacky".



    The first screenshot shows the beginning performance slowdown due to another process using more CPU time.
    This is no big deal because the timesteps of the physics catch up and keep the "physics framerate" at its desired 60 fps.

    But sometimes (e.g. on another machine) something strange happens as shown in the right image.
    A periodic "peak" in the frametime appears, without the overall system load being stressed too much. These regular peaks result in "update bursts" of the physics in the above code sample, which result in really wacky physics. This means there are partially smooth movements but there are regular "jumps" in the movement of the bodies.

    Is there a way to ensure the physics runs smoothly but still at a locked update rate (which is as far as I know very important for running a game over a network)?

    Thanks for any help or advice!
    S_W



    sean.thurstonSeptember 2, 2008 6:42 PM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hi S_W,

    You are doing this the right way. The timestep should be constant. Some things to think about doing when you are stepping like this is what happens when your frame takes longer than 60hz to do and you need to step the physics steps multiple times. It can cause problems, so you might have to cap the number of physics steps you take.

    As for the popping and update bursts, it might be that you need to interpolate the positions of your rigid bodies with a call to approxTransformAt() for the times that you are rendering.

    There is some documentation on this if you look at the Havok Physics->Havok Dynamics->Stepping the Simulation. Let me know if this helps.

    Thanks,
    Sean


    Developer Support Engineer
    Havok
    www.havok.com

    S_WSeptember 2, 2008 7:05 PM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hi Sean,

    Actually I'm uncertain about the possiblities to perform "large" timesteps instead of doing update bursts (which worsen the performance as well). Is there a maximum timestep which could be used to at least reduce the number of update calls neccessary to keep up? But then again I'm not sure whether "switching" the timestep wouldn't result in slightly different simulation results.

    In terms of interpolation: approxTransformAt() seems to be for for asynchronous simulation only. Would the best solution for providing a more stable experience be to use asynchronous stepping? I'm not sure whether this is a good idea, since the manual recommends to use the parallel approach.

    And in terms of networking: is it better to use parallel or asynchronous stepping?

    Thank you very much,
    S_W


    rossodwyerSeptember 4, 2008 12:42 PM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hey S_W,
    approxTransformAt is the interface you need to use if there's ever a disparity between your game frame time and your physics time (which the stepping approach outlined above could produce). Can you look at using this and see if it works?

    Our previous asynchronous interface had the unfortunate artifact of tying up all of the threads involved in simulation when handling TOI collisions. We therefore suggested that the asynchronous handling be the responsibility of the client.

    Your question on what the ideal approach is when there's a very long frame time is a pretty common one and there are several approaches:
    • You can step all frames using the code you already have but this can lead to a vicious cycle where the need to simulate that much physics causes a knock on effect that slows your next step even further.
    • You can cap the number of times you step the physics, the end result of this will be that for those long frames your physics will seem to run slightly slower than normal , some users find that this is acceptable.
    • Another approach is obviously to take slightly longer steps, the trade off here is that you can't change your step size too much from frame to frame without introducing some solver instability: the solver uses the last frame size to help anticipate forces it needs to apply to avoid error in the next frame and if you change the step size this approximation will have been incorrect and so you get unstable contacts and constraints. In addition to instabilities, if you're using continuous collision detection then longer frame times increase the likelihood of TOIs which in and of themselves can cause more simulation to occur. If you're not changing the frame time too dramatically though, this approach can work fine.
    Try the approximate transform function and let us know if this works out for you.
    Thanks,
    Ross


    S_WSeptember 4, 2008 1:25 PM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hi Ross,

    I'm currently using approxCurrentTransform(), which should have the same effect as using approxTransformAt().

    The stuttering issue is a problem I've already noticed earlier when using another physics engine. So when I saw this problem again in the visual debugger, I didn't take a closer look at the game itself. I guess the visual debugger isn't showing any interpolation, so this is why I thought I've run into the same problem again. The game seems to run smoothly

    Clamping the number of times the physics is stepped at e.g. 20 x 0.0166 should be a good solution, because once the game drops below about 3 fps it's already unplayable:

    unsigned char count = 0;


    // update using time slicer

    while( elapsed > m_timestep && count < 20 )

    {

    m_world->stepDeltaTime( m_timestep );

        vdb->step( m_timestep );

        updateDisplay( m_world );

        elapsed -= m_timestep;

        count++;

    }


    I just wanted to make sure I'm using the right approach for stepping the simulation.

    So thanks again everyone for this great and fast support! :)
    S_W



    rossodwyerSeptember 4, 2008 4:23 PM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hey S_W,
    You're stepping correctly, that's fine. However approxCurrentTransform is not the same as approxTransformAt. Look at hkpRigidBody.inl

    approxCurrentTransform does the following:
    getRigidMotion()->approxTransformAt( m_world->getCurrentTime(), transformOut );

    It's not the current time of the physics world that you want the transform for, it's the current time of your game world and your game frame time is different from your physics step time if you step the world as you outline above.

    If you set the frame time on the world then step delta time will only advance the current time up to the end of the frame and the function you're calling would work. You're handling the stepping yourself though (which is the ideal in the long run) so when you access the rigid body positions for your game you'll need to do so with respect to where your game time is.

    Hope this makes sense,
    Ross

    S_WSeptember 4, 2008 5:06 PM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hi Ross,
    thanks for clearing up the situation.

    Just to make sure I've got it right...what's exactly the time for approxTransformAt()?

    Image Hosted by ImageShack.us
    So should I simply add the time which has remained in the time accumulator to m_world->getCurrentTime(), since this is the time the visual meshes of my game are ahead of the physics current time? Is this correct?

    Thanks again!
    S_W


    rossodwyerSeptember 5, 2008 11:16 AM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hey S_W,
    Looks like your code actually steps past the end of the frame time (which is what our async stuff does too) so if your frame ended half way through your last 60 Hz step you'd be looking for positions at 8.333333 ms, let me know if that makes sense,
    Thanks,
    Ross

    S_WSeptember 5, 2008 11:58 AM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hi Ross,

    actually I'm a little bit confused now ;) 

    I'm running my game from my main loop. At the moment there is a procedure call "updatePhysics( timeSinceLastFrame in seconds )" inside the loop. "updatePhysics(...)" adds the timeSinceLastFrame to its time accumulator "elapsed". Now the loop inside updatePhysics() steps the world as often as required to get to the elapsed time, The remaining time is added to the physics time, because this should be the difference between the physics current time and the current frame time.

    E.g. elapsed = 0.02s, timestep = 0.016s, so the loops is called once and 0.004s remain in elapsed, so after stepping the world I'm updating the graphics with: hkpWorld::getCurrentTime() + 0.004s  because actually this is the time where the physics should be, but the timestep would have been too small for a step.

    Is this the right track? Or is there something I've got wrong?

    Thanks!
    S_W


    S_WSeptember 7, 2008 6:09 AM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hi abaraba,

    thanks for the lengthy responce. I think you wanted to show me a way to step the simulation smoothly without having to clamp the number of substeps. As far as I've seen the only difference in terms of code is the way you're decreasing the accumulated time every step. I guess clamping the number of substeps would only make a difference once the fps drops below a limit and the substeps can't keep up, e.g. 3 fps which seems acceptable, because the game would already be unplayable with these game settings. So actually moon walking would only occur below 3 fps which isn't really a problem to me by using the time slicer in my code.

    My last question was related to the time I should use as parameter for the approxTransformAt() function in order to get a correct visual result without any "wacky jumps" when rendering.

    Thanks anyway for the response! :)
    S_W


    S_WSeptember 7, 2008 11:04 AM PDT
    Rate
     
    Re: Stepping the simulation correctly

    Hi abaraba,

    thanks again for the reply and I was really a little confused by your answer :)

    In terms of putting updateDisplay() outside the loop I already did that once I noticed I have to update the view only once ;)  But sadly this doesn't solve the problem.

    These "jumps" in the world objects seem to exist because sometimes the frametime does one or more peaks (in the third picture, the red peaks), so the loop trys to catch up which results in a time lapse due to the fixed time stepping (this movement, which is too fast, looks like a "jump"). I'm not really sure how to solve this problem, but with using approxTransformAt() this problem seems to disappear...I guess it's smoothing the positions then used for rendering (?) a bit. I could also use to implement a frame time smoothing for the view, but maybe approxTransformAt() does that already...I also guess I need it when programming some network stuff for being able to reverse time if required (I guess Havok stores some sort of history for about 30 seconds or so and approxTransformAt() can access this history or do a simple extrapolation of a transform in the "future", please correct me if I'm wrong).

    I just wasn't sure what Ross was trying to tell me; this was the reason I asked again...but Havok engineers do also need some weekend right? ;)

    Thanks,
    S_W

    P.S. you asked about that graph, I'm using Ogre (www.ogre3d.org) for rendering and it's just a simple texture overlay I wrote "quick n dirty", not really clean code, but if you want it, just send me message.




Forum jump:  

Intel Software Network Forums Statistics

17,025 users have contributed to 48,321 threads and 172,762 posts to date.

In the past 24 hours, we have 11 new thread(s) 45 new posts(s), and 38 new user(s).

In the past 3 days, the most popular thread for everyone has been Optimalization of sine function\'s taylor expansion The most posts were made to Most likely, the issue is that The post with the most views is Optimalization of sine function\'s taylor expansion

Please welcome our newest member mehakchehal52


For more complete information about compiler optimizations, see our Optimization Notice.