Skip to main content
gamedev.net
🔒 Locked

Time compression in physics engine

Started by MGB Jul 2, 2004 at 10:17 AM 21 replies 3.4k views
Original Post
MGB
MGB
Has anyone here successfully implemented 'proper' physics with time compression (i.e. variable timestep)? I'm thinking that I'll never get the same behaviour of my physical objects at higher time steps and should give up and find a physics implementation that doesn't rely so much on integrator accuracy..? I've read bits about verlet integration on here - would that approach be any good for this?
Charles B
Charles B
I'd never work again for a game that does not work with fixed time steps ;) I have always found the idea of updating at the FPS rate stupid.

No reason to work at the same rate as the graphics. Work at a given frequency and interpolate the object positions to match the end of the framer exactly for rendering. More with fixed time steps many optimizations can be done since dt is constant. It's great for quaternions for instance, slerps are costly.

PS: fixed time steps do not mean you can't subdivide your base timesteps for collision detection, or constraint integrations.
"Coding math tricks in asm is more fun than Java"
MGB
MGB
Quote:
Original post by Charles B
I'd never work again for a game that does not work with fixed time steps ;) I have always found the idea of updating at the FPS rate stupid.


lol - not lookin good for me so far ;)

But by 'time compression / variable timestep' I mean the user can choose to increase time to pass at e.g. 2, 4, 8x normal speed, thereby screwing up my carefully fixed update time...
Lode
Lode
I have sort of made a (never finished) space game that had a "stardreamer" like Frontier Elite had. It makes time pass faster or slower. I did it like this:

The gameloop does each on their turn: drawing, physics, drawing, physics, etc...

In the physics part, I remember the time of the previous loop, and get the time now. Based on the time difference between those two (timedifference), I did the physics calculations:

newposition = oldposition + velocity*timedifference*someparameter
newvelocity = oldvelocity + accelaration*timedifference*someparameter

Etc...

someparameter is chosen so that it moves exactly with those physical units I want (second, meter,...), e.g. if timedifference is in milliseconds and velocity is in meter/second, someparameter will have to be 1000 or 1/1000 (too lazy to calculate which of those two it is at the moment)

That way, the faster the computer, the more precision the physical calculations have, and the more FPS the drawing, but the spaceship still always moves as fast no matter how fast or slow the computer is...

I don't know if this is a good way though, since I see posts saying it's bad to do the physics calculations at the same rate as the drawing?
DigitalDelusion
DigitalDelusion
Well if you want to speed up your physics don't change the time step used for updating the physics, change your delta time.

Want the game to run 4 times as fast then when calculating your delta time to know how much time went by since the last frame simply do:

fDelta *= 4;

and let the engine handle the rest, the maximum game speed will then be dependant on how fast the machine can crunch physics.

EDIT:
here's a link to a thread in "game programming" dealing with almost the same thing.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
clum
clum
Quote:
Original post by Lode
newposition = oldposition + velocity*timedifference*someparameter
newvelocity = oldvelocity + accelaration*timedifference*someparameter
These are actually also framerate dependant (albeit to a lesser extent). If there are less frames, then the acceleration would be updated less often and the position would be updated with slower velocities. The correct formula for totally frame-independant position is:
newposition = oldposition + velocity*timedifference + accleration*timedifference*timedifference/2
Zorx (a Puzzle Bobble clone)Discontinuity (an animation system for POV-Ray)
Charles B
Charles B
You all probably know what happens in Quake3 when you change the com_maxFPS which controls the physics rate. You jump higher or longer at 75 or 125 than 85FPS. It's because of the very nature of the integrators that just sum things at various sample times and not continuously. (dt is never zero). Change the values of your dt (I mean in the physics world, not necessarilly the real time), and you get different physical behaviours. That's why I don't like varying physics time steps in games. The same commands should cause the same effects whatever the machine. This is also the base of deterministic physics such as solid mechanics.


Quote:
(Digital)
fDelta *= 4;


So for these previous reasons I would not do that. I would try to maintain the time step whatever your acceleration ratio of game time over real time. This means that the part of the physics will cost more ressources when you accelerate. You simply treat more game time samples per (real time) second. Perfs is a potential drawback I admit.

But if else you scale the delta time proportionnally (increase it), you risk to let new flaws appear in your physics. Some collisions previously detected may vanish, the classical wall traversal problem with huge time steps. Some springs, or aerodynamics may start to cause catastrophic diverging effects.
"Coding math tricks in asm is more fun than Java"
DigitalDelusion
DigitalDelusion
Charles B, Im not sure I understand what the heck you're saying here, did you look at the thread I linked to?

What I ment to say was basicly that the easiest way to do things (and this is to keep things stable and not get the effects you talked about with diffrent jump heights etc) is to always update the physics with a fixed time step. Basicly doing

const float TimeStep = 0.01f;//some nice small value const float MaxDelta = 1.f; //let's cap itfloat fPhysicsAccumulator = 0;while( bRunGame){  float fDelta = GetTimeSinceLastUpdate();  if( fDelta > MaxDelta) fDelta = MaxDelta;  for( fPhysicsAccumulator += fDelta; fPhysicsAccumulator >= TimeStep; fPhysicsAccumulator -= TimeStep)    UpdatePhysics( TimeStep);//do the funky stuff   Render();   HandleInput();}


Changing the gamespeed if you do it like this is simply a matter of scaling what ever GetTimeSinceLastUpdate() returns.

That's what I ment to say.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
markr
markr
I've done this several times - it isn't that difficult, but I'm beginning to think in agreement with Charles - that it's a better idea to use fixed time steps for logic.

In practice it's dead easy, just multiply your velocity * quantum before adding to position, acceleration * quantum before adding to velocity etc. Collisions aren't in practice any different depending on the time step.

The thing that becomes awkward is that you get odd effects if the timestep is very large, and it causes code bloat whenever you want a timer, because consider the pseudo-code:

void Player::doThings() {  if (gunReloadTime > 0) {    gunReloadTime --;  } else {    if player has finger on trigger {      fire bullet;      gunReloadTime = maxReloadTime;    }  }}


if you have a variable timestep, *everywhere* you have gunReloadTime-- must become gunReloadTime -= quantum - and you then have to have gunReloadTime as a float - and cope with the inaccuracies that this causes.

Additionally, variable time steps make your gameplay unrepeatable - i.e. even with the exact same inputs and no randoms anywhere in your code, subtle variations caused by timestep variations cause a different outcome.

Mark
DigitalDelusion
DigitalDelusion
Just for the record I agree with charles too, and I think my code snippets (both threads) should make that quite clear, the UpdatePhysics thing is where you would put any update that's dependant on time.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Lode
Lode
Quote:
Original post by clum
These are actually also framerate dependant (albeit to a lesser extent). If there are less frames, then the acceleration would be updated less often and the position would be updated with slower velocities. The correct formula for totally frame-independant position is:
newposition = oldposition + velocity*timedifference + accleration*timedifference*timedifference/2


Yeah, I know that is a problem with my code, but I have to do it that way, because the location of planets, and the ship's thrust engines, change acceleration all the time. Problems only appear at very low FPS, or if the time is way too fast, though.

I had also made this much better, by, instead of doing velocity = velocity + timedifference*acceleration only once, doing it repeatidly every time in a loop instead, with the number of loops depending on the time difference, but with a maximum on it. (This because I hadn't found any better physical formula at that time)
MGB
MGB
Quote:
Original post by Charles B
Some springs, or aerodynamics may start to cause catastrophic diverging effects.


The exact reason for this post - I have a spring system that diverges at higher timesteps.

DigitalDelusion/Mark/Lode: You are basically describing Euler integration - an unstable integrator - and the cause of the problem here.

CharlesB: So you're saying to for example do 4 separate physics steps at the original fixed dt for 4x compression..?

Having time compression and not being an expert on numerical analysis is why I think I need to find a physics approximation that doesn't depend on a stable integrator!
DigitalDelusion
DigitalDelusion
Quote:
Original post by Aph3x
DigitalDelusion/Mark/Lode: You are basically describing Euler integration - an unstable integrator - and the cause of the problem here.


Errr!!!! No Im avoiding that by fixing the timestep.

Quote:
Original post by Aph3x
CharlesB: So you're saying to for example do 4 separate physics steps at the original fixed dt for 4x compression..?


*I* said that, or I my posts and code that unclear?
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
MGB
MGB
Original post by DigitalDelusion
Errr!!!! No Im avoiding that by fixing the timestep.

Fixed timestep or not, its Euler!
DigitalDelusion
DigitalDelusion
True but at least I keep it deterministic and avoids the problems being talked about here, and I was refering to those, by fixing the timestep your character will jump the same height no matter what the FPS.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
markr
markr
Yes, I am using Euler integration. It is true that in some models there are stability problems with Euler, and this is possible to see in commercial games (Remember Operation Flashpoint? Remember its jumping barrels?)

But the models I've been using I've not encountered any stability problems with it yet.

However I am pretty much certain that verlet integration does not work with a variable timestep (I can't see how to make it work if it does), so if I changed to that, I would definitely need fixed timestep.

Also once I start getting into some proper rigid body stuff, I think it's going to have to go verlet, because it really does look a great deal easier (as well as more stable)

Mark
MGB
MGB
Yeah - just been doing more research - looks like implicit Euler will do the job for time deltas >= 0 - I think that is basically what the verlet scheme is - working 'backwards'.
grhodes_at_work
grhodes_at_work
Quote:
Original post by Aph3x
Yeah - just been doing more research - looks like implicit Euler will do the job for time deltas >= 0 - I think that is basically what the verlet scheme is - working 'backwards'.


The Verlet technique isn't an implicit technique. Implicit Euler doesn't work backwards, it merely solves for the new position and velocity simultaneously rather than one after the other.

The idea is that the updated velocity can be written as a function of the updated acceleration, and the updated position as a function of the updated velocity, e.g., Vel = function of accel; and Pos = function of Vel. Updated acceleration is a function of the forces being applied that include: a) weight (gravitational acceleration) b) spring and position dependent forces (such as spring forces or penetration constraint penalty forces); and, c) damping forces that are velocity dependent. Given the acceleration equation, you can solve for position (assuming you have position dependent forces). So, what you get is a function for velocity that is a function of position and a function for position that is dependent on velocity and that makes a set of coupled equations that have to be solved using, say, Gauss-Siedel iteration or Successive Over Relaxation (SOR). The explicit techniques, including Verlet, calculate acceleration based on the *old* position rather than the new, and this breaks the coupling of the equations making it possible to solve one after the other, e.g., calc acceleration first, then updated velocity----all based on the *old* position, then finally update the position. In a sense, acceleration and velocity lag the position.

The benefit of implicit methods is that no property lags another and this makes the system much more stable. For some implicit methods, called A-stable methods, you can use *any* positive time step and the simulation will still be stable. For these methods, you *could* have a physics step that floats with frame rate, but it still would not be a good idea!

A negative factor in implicit methods is that, though stable, they certainly will not be very accurate if you use large time steps.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
MGB
MGB
Thanks for the info grhodes, all this stuff is gradually beginning to make sense to me now (after much reading and thinking!)

DigitalDelusion: My apologies - you were solving my problem, I saw 'fDelta *= 4' and thought you were talking about Euler stuff.
DigitalDelusion
DigitalDelusion
Quote:
Original post by Aph3x
DigitalDelusion: My apologies - you were solving my problem, I saw 'fDelta *= 4' and thought you were talking about Euler stuff.


n/p glad I could help :)
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.