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
|
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
|
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
|
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
|
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
|
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()?
 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
|
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
|
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
|
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
|
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.
| |