Stepping the simulation correctly

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

26 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

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

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

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

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

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

Hi Ross,

thanks for clearing up the situation.

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


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

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

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

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

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.

Just a little extension to the previous question: is there a way to get an approximated position for the wheels of a vehicle?

Hey S_W,
This thread seems to have evolved into more general discussions than the specific question you were asking. I read your code incorrectly and thought it was stepping the physics further than your game had stepped (which is how our async utility handles stepping the simulation) and then the approx function is simply interpolating.

I now see you're not and your physics sim time ends before your game time in which case you need to use the function to extrapolate.

Either way, both of these approaches give you a transform for your bodies that is aligned time-wise with your display frame. They can result in inaccuracies in the final rendered result but when dealing with a standard game running somewhere between 30 and 60 Hz they tend to be negligible.

I hope that answers your original question. Sounds like you have it working.
Thanks,
Ross

Hey abaraba,
I have to say it's a little difficult to break down your different posts and understand where you're talking about the question at hand, where you're discussing stepping strategies in general and where you're making posts from other forums without reading what's happened in the thread already.

You also mentioned that you hadn't downloaded Havok so it's a little difficult to understand where you've noticed a bug.

That said, I'm certainly not saying there aren't any bugs in the system at all but I can only spend the effort to give feedback here when the topic is presented clearly.

Havok provides a simple interface for stepping the physics world one step at a time. How to handle asynchronous stepping isn't part of this so there isn't a bug there based on previous posts.

In terms of the general topic concerning suggested approaches to async stepping, we do provide a simple utility interface where we step beyond the end of the game frame, this can hit issues if the next game frame becomes so small as to not require another physics step because essentially you get no physics step for that time. However, if that becomes an issue (very unlikely in a game scenario) there are other strategies for handling this, some of those are outlined above and we discuss this topic in pretty good detail in the documentation.

If there's something else you'd like to chat about please feel free but do try to be concise and clear in discussions and in questions you want to raise. As noted in another post, the forum is user supported and we have to limit the time we can give support directly for and working through a number of posts which are copies and pastes from other forums or are flaming about how we shouldn't be providing a clean api interface for "newbies", does not help us track down specific questions.

Thanks again,
Ross

Hi Ross,

Everything seems to be working all right in terms of extrapolating the graphics using approxTransformAt().

I've just rendered the meshes twice to see the difference and it showed me that the approximated position is slightly different, but very well acceptable. The visual "jumps" also don't occur on the extrapolated transforms so everything seems to run fine (also when running at low fps).

Thanks again for the support! :)
S_W

Hey Abaraba,
I think S_W has the answer needed to the question asked.

I'd really rather not continue to discuss this further unless you're having an issue using Havok. If that's not the case can we stop posting to the thread as I think it's adding confusion for people who want to read this thread in the future.

maxSubSteps may be a parameter that Bullet uses when stepping but does not exist for Havok where you just ask the world to take a given step size and you need to understand how to handle the different scenarios caused by potential over and under shoot for game frame time. The solver is iterative and you can tweak the number of iterations it takes but that's different to substepping a simulation.

The code outlined above is also confusing as you pass maxSubSteps in by value but then ignore whatever value is passed in. It also looks like the code limits to a max of two steps per frame so as discussed earlier this would lead to visual artifacts (which can be fine if that's a trade off you're making but it's something users should be aware of).

I'm just being careful here for people reading this thread and seeing you stating that the code above works in all cases as that's misleading.

If you'd like to discuss general stepping strategies in a separate thread then please post there but I would urge you try out Havok and familiarise yourself with that first if possible.

Thanks again for your contributions,
Ross

Hi abaraba,

I guess you want to show me that if there is a need to clamp the stepping, the time accumulator should also be reset to zero to avoid extrapolation errors, e.g the visual meshes going crazy.

But actually it would have been enough to provide the link, so that the thread wouldn't have grown so big...maybe someone could clean up this thread a bit, so that only the last post / link of abaraba is left instead of the large number of posts?

Thanks again for the help, I hope that's the error you wanted to make me aware of.
S_W

Hey Abaraba,
I withheld from posting to your previous post to me where you asked to speak to
my manager as I was hoping this thread would finish quietly of its own accord
and the last thing we want to do is limit speech where users may find it
useful.

We definitely don't want to ban people from forums for trying to help, I know
you've been banned from other physics forums and we want that to be the last
step we take with any user, especially where their intent is to support the
community.

However, we really won't permit rudeness and a lack of respect to other users
of the board. It may be that you're not aware that your responses have not been
polite, but several of your posts to this thread have been abrupt and
disrespectful, posting emotional responses on your thoughts about "Newbies",
suggesting that posters are trying to inhibit information, strongly implying that
people aren't reading your posts when other users have tried to explain that
they're not necessarily clearly laid out so it's difficult to understand what
you're trying to say.

Please be careful how you address people in the future, if your behavior
continues we may have to limit your access to the forum.

Ross

Hi abaraba,

I'm sorry if you've been offended by my response abouth the length of your post, this wasn't intended.

So here is a video (I guess that's more useful than just a few screenshots) of the second algorithm above in action:
http://rapidshare.com/files/146725336/stepping.rar.html

So thanks again,
S_W

Forgot to mention:

The red vehicle uses the current exact transform of the rigidbody, the white vehicle shows the extrapolated movement using approxTransformAt().

So there is a little offset, but once the framerate goes down and the red vehicle starts stuttering, the white vehicle keeps moving smoothly.

Hi
I have a problem not so different from topics's author, so i think it would not be bad if i post my question here.
The problem is in wheels of physic car. The situation is so that i have low FPS and when it fall below 15, the wheels begin to rotate every frame dramatically from left to right and backward. So i even can't controll the car. I want to turn left, but car continue to go forward. The difference between left and right angles of wheel during rotating is really big. I use such code to step world:
void onFrame(double frameTime)
{

//get input from user and pass it to hkpVehicleDriverInputAnalogStatus

#define STEP_DELTA_TIME 0.02f

float devide = (float)frameTime / STEP_DELTA_TIME;
int LeftPart = (int)devide;
float RightPart = devide - (float)LeftPart;

nNumStepsInLastTrigger = LeftPart;

if(nNumStepsInLastTrigger == 0)
{
nNumStepsInLastTrigger = 1;
}
else if(RightPart >= 0.5f*STEP_DELTA_TIME)
{
nNumStepsInLastTrigger++;
}

float fNewFrameTime = float(frameTime / (double)nNumStepsInLastTrigger);

for(int i=0; i
m_world->stepDeltaTime(fNewFrameTime);

#undef STEP_DELTA_TIME

//update graphics

}

I tried to use hkpVariableTimestepper (i know that it design for timesteps between 15 fps and 750 fps) and the result was much better for wheels, but worse for the rest of world. So i refused it.
Also, i tried to do always only one step:
m_world->stepDeltaTime(frameTime);
As before the rest of physic world behaved bad, but the car was normal. But only if fps > 15.
Two different approaches and the same result. I mean this red limit in 15 fps. I wonder, if there is any limitation or peculiarity in havok i don't know about? Or its my fault?
When fps is greater than 15, everything is ok.
Could you tell me where i must search the answer? Or what can i try to fix this strange wheel behavior?
Thanks

Quoting - ittenHi
I have a problem not so different from topics's author, so i think it would not be bad if i post my question here.
The problem is in wheels of physic car. The situation is so that i have low FPS and when it fall below 15, the wheels begin to rotate every frame dramatically from left to right and backward. So i even can't controll the car. I want to turn left, but car continue to go forward. The difference between left and right angles of wheel during rotating is really big. I use such code to step world:
void onFrame(double frameTime)
{

//get input from user and pass it to hkpVehicleDriverInputAnalogStatus

#define STEP_DELTA_TIME 0.02f

float devide = (float)frameTime / STEP_DELTA_TIME;
int LeftPart = (int)devide;
float RightPart = devide - (float)LeftPart;

nNumStepsInLastTrigger = LeftPart;

if(nNumStepsInLastTrigger == 0)
{
nNumStepsInLastTrigger = 1;
}
else if(RightPart >= 0.5f*STEP_DELTA_TIME)
{
nNumStepsInLastTrigger++;
}

float fNewFrameTime = float(frameTime / (double)nNumStepsInLastTrigger);

for(int i=0; i m_world->stepDeltaTime(fNewFrameTime);

#undef STEP_DELTA_TIME

//update graphics

}

I tried to use hkpVariableTimestepper (i know that it design for timesteps between 15 fps and 750 fps) and the result was much better for wheels, but worse for the rest of world. So i refused it.
Also, i tried to do always only one step:
m_world->stepDeltaTime(frameTime);
As before the rest of physic world behaved bad, but the car was normal. But only if fps > 15.
Two different approaches and the same result. I mean this red limit in 15 fps. I wonder, if there is any limitation or peculiarity in havok i don't know about? Or its my fault?
When fps is greater than 15, everything is ok.
Could you tell me where i must search the answer? Or what can i try to fix this strange wheel behavior?
Thanks

Hi itten,

I think the main point of this somewhat bloated thread is that a) you want to step the physics world with a constant timestep, b) you want to use approxTransformAt() to interpolate or extrapolate where the rigid bodies should be for the actual frame time, and c) that you may need to cap the number of steps that you are able to take in one frame. The last point is to avoid the problem of (let me see if I can explain this well) entering a cycle where taking a certain number of physics steps in one frame leads to taking more in the next frame and then more in the next frame and so on. Hopefully that makes sense.

Thanks,
Sean

Developer Support Engineer Havok www.havok.com

Quoting - abaraba

Hi, sean

I sorry for my last post. There was bug in my code in another place. And the problem didn't concern to physics simulation. And havok doesn't have any limit on 15 fps - now i have convinced that this is true by myself

Quoting - ittenops, sorry for such formating. :-) there were not any tags for quoting

Quoting - abaraba

this is not about Physics at all..

Please keep to the topic of this post. You've derailed this thread a number of times, and I think we'd all appreciate if you kept on topic.

Kind regards,
-Guy

The original question here was answered a while back, and the current discussion isn't specific to Havok, so I'm locking this thread.

-Chris

Login to leave a comment.