[ODE] world update - best practices?
Greg Mayer
gmayer at hotheadgames.com
Wed May 23 15:00:07 MST 2007
Hello
I apologize if this issue has alreday been answered in the mailing lists
- I did not have any success searching the mailing list for this topic.
I am evaluating various physics APIs and I'm trying to understand the
best way to setup the main update loop in ODE.
It seems for any game application with more than a small amount of
physics, dWorldQuickStep is the way to go.
The documentation heavily stresses that this function should be called
with a constant-size time step.
Also, there is a function to set dWorldSetQuickStepNumIterations.
However, there are a few things I'm not clear on.
Presumably, if you have an app running in real-time, you will have some
sort of update loop like:
UpdateWorld(float dtSeconds)
{
}
In which you do your collision detection and solving and stepping of the
dynamic simulation.
One would hope that this update is being called very frequently and with
a value that doesn't vary much. Ideally dtSeconds would be something
like 0.016 for a game running at 60fps.
However, as anyone who's written a game knows, in practice the incoming
value will vary slightly, and in bad scenarios (especially during
development) it could be several times higher than the desired 0.016.
Therefore, it seems like good practice to wrap the dWorldQuickStep (and
collision detection/solving, and external game force applications) call
in a loop which breaks down the incoming dtSeconds into the
constant-size time steps that ODE desires.
Where things get unclear though are the values that are close to, but
not exactly, the desired constant-sized step.
Say for example you have an incoming value of 0.017.
What is the best practice in this case??
Does it _really_ matter to ODE if you pass in 0.016 one update, and
0.017 the next? Does it explicitly cache the 0.016
and have some sort of optimization for the _exact_ same value being used
repeatedly.
This would seem odd to me, but I ask because in the wiki-manual, in
large red letters it says "Variable Step Size: Don't!"
So an alternative in this case would be to have a loop which starts
taking 0.016 sized bites out of the incoming step and calls
dWorldQuickStep. However, in this case that would mean you make on call
with 0.016, and are left with a remainder of 0.001. Now what to do?
Making a second call to the update with this value seems to deviate far
more from the constant-step-size requirement than to have simply called
dWorldQuickStep with 0.017.
Or one could have some sort of static "remaninder" variable in the
update loop and wait until the value accumulates to at least 0.016, but
then you are not strictly running in sync with the rendering and the
rest of the game (though the difference may not be noticeable)
A further complication on this is the dWorldSetQuickStepNumIterations -
this seems to set an internal counter for substeps so that you do not
need to maintain such a loop manually in your WorldUpdate, but shouldn't
this number of substeps be dependent on the size of the incoming dtSeconds?
So are you supposed to call dWorldSetQuickStepNumIterations every frame?
If someone could please explain these issues in ODE and suggest the best
practice I would really appreciate it.
Thanks in advance
Greg
More information about the ODE
mailing list