Archived

This topic is now archived and is closed to further replies.

angry

updating physics

Recommended Posts

I made this very simple gravity simulation program, and the precision was awful. The calculation of acceleration I did was by dividing the acceleration of gravity by 1000 and then multiplied the result of that with the time passed since last calculation:
acceleration.y += (gravity.magnitude()/1000)*passedTime;
 
the passed time is usually around 16 milliseconds. And then I updated the point which in this example is the object which is affected by gravity:
point.y -= acceleration.magnitude()*0.01;
 
where 0.01 is a conversion unit, converting meters to openGL units, so that 1 meter is 0.1 openGl units... These calculations works absolutely fine if I only update my physics once per second, and then keeps going out of precision the more often I update it. For example if I update every loop run, ie every 16 millisecond. My point moves over 40 meters the first second, which is way off, as it only is supposed to move 10 meters(9.8 to be exact).. So any ideas of what I should do? [edited by - angry on January 6, 2004 7:57:44 AM]

Share this post


Link to post
Share on other sites
Accelerations, including that caused by gravity, are in meters per second squared ( assuming you're happy enough with metric measurements like all good, decent people ). I notice that you don't mention point velocities, which might be sensible. Something like this should work:

acceleration = gravity;

velocity += acceleration * passedTime;

point += velocity * passedTime;

I'm assuming here that passedTime is actually a float which is updated every frame with something like the following:

this_frame = SDL_GetTicks(); //or an equivalent function that returns the time in milliseconds.
passedTime = (float)(( this_frame - last_frame ) * 0.001f);
last_frame = this_frame;

This system should also allow you to go into the next iteration of the game loop as soon as the computer is ready to do so, rather than waiting for a certain amount of time to pass, which it sounds like you're doing at the minute.

Scaling by the time twice will allow for the "per second squared", and things should be smoother.

Edit: to allow for your conversion factor, I think that just scaling the gravity should be ok, e.g. for earth gravity:

gravity.SetValues( 0.0f, -9.81f * 10, 0.0f );



[edited by - Hamster on January 6, 2004 8:36:49 AM]

Share this post


Link to post
Share on other sites
the easiest way if to keep units identical to the real world. Then, if you need to, you can rescale the position into the opengl units for rendering.

this is how I''d do it for a particle moving through space, and under the influence of gravity.



struct CParticle
{
Vector Position;
Vector Velocity;
Vector Acceleration;

void CParticle(const Vector& Pos, const Vector& Vel)
: Position(Pos)
, Velocity(Vel)
, Acceleration(0, 0, 0)
{}

void Update(void);

void Render(void) const;

};
void CParticle::Update(float dt) // dt = passed time since last update

{
Acceleration = (0, -9.81f, 0); // gravity

Velocity += Acceleration * dt;
Position += Velocity * dt;
}

void CParticle::Render(void) const
{
Vector RenderPos = OpenGLRenderer::PhysicsUnitsToOpenGLUnits(Position);
glBegin(GL_POINTS);
glVertex3fv(&RenderPos.x);
glEnd();
}


but usually, either you set the viewport to a scale, or you apply a scaling modelview matrix to the whole world.

Share this post


Link to post
Share on other sites
Hey, big thanks to both of you. I finally got it up and running and it works like a charm.

Thanks alot.

Share this post


Link to post
Share on other sites