Interpolation

Started by
8 comments, last by slicer4ever 10 years, 11 months ago

Hey

I am having a lot of problems on my actual project, mostly because of the frame rate, which tends to lag sometimes. So far, I found out that interpolation is used to make the motion smoother. But I can't find any article or example that could help me understand it. Do you know any tutorials covering this technique?

Advertisement

The "The final touch" section of "Fix Your Timestep!" covers it a little bit:

http://gafferongames.com/game-physics/fix-your-timestep/

Interpolation is used to smoothly transition from one fixed value to another.

A variable in the range ( 0.0 - 1.0 ) is used to 'map' those two fixed values onto a relative scale, where 0.0 represents the first value, and 1.0 represents the last. 0.5 represents the one value right inbetween them, and so on.

Say for example that you wish to gradually move an object from point A to point B and you want to do it in 10 frames rather than instantly. All you have to do then is interpolate inbetween those two points, starting at 0.0 and adding 0.1 to the reference value each frame until it reaches a value of 1.0.

There are a few different types of interpolations with slightly different output, but the most straightforward one is called lerp (short for linear interpolation). Here's the logic in pseudocode:


float lerp(float start, float end, float percent)
{
   return start + percent*(end - start);
}

You should know however, that this logic is still bound to the frame rate!

I don't get it :/ Let's say I have set 60 FPS. So one second is like:


frame 1:
event();
logic();
render();

frame2:
event();
logic();
render();

.
.
.
frame60:
event();
logic();
render();

Let's say my object moves from (0,0) to (1,1) every frame (its speed is [1,1]). So it moves 60 on the X and 60 on the Y axis every second.

Now I want to add interpolation. As in the example that @papulko gave, I want it to move from (0,0) to (1,1) in 10 frames instead of 1. That would slow the object 10 times, right? Rather than 60X, 60Y it would move 6X and 6Y every second. I don't really see the link between frame rate and interpolation. For me it's just slowing down the object :/

Edit: another thing came on my mind..

game loop:

events();

logic();

render();

as in the example above, let's say I want to move object from (0,0) to (1,1), using interpolation, so it moves like (0,0)->(0.1 , 0.1)->...->(0.9 , 0.9)->(1,1), which takes 10 frames. But every frame logic and events part is used, so every frame the destination point will change. Start: I want to move 0,0 -> 1,1. So, with the interpolation, in the second frame the object is on the 0,1 . 0,1 coordinates. BUT, also the object changes its destination, now it is moving from 1,1 to 2,2.. It is really confusing me wacko.png

http://nccastaff.bournemouth.ac.uk/jmacey/RobTheBloke/www/opengl_examples/frameRate.zip


vec2 ObjectPosition(0, 0);
vec2 ObjectVelocity(1, 1);
 
void logic( float dt )
{
   ObjectPosition += ObjectVelocity * dt;
}

and if you have 60frames per second, your time increment (dt) per frame will be 1 / 60.0

To be honest, I still don't get it :S But I have done something in my project, and it works, so I wanted to ask you guys for opinion + I have some questions.

I have my main loop:


	while(CurrentID!=STATE_EXIT)
	{

			int start=clock();
			CurrentState->events(this);

			CurrentState->logic(this);

			ChangeState();
	
			CurrentState->render(this);
			if((clock()-start)/CLOCKS_PER_SEC < one_frame )
			{
				//calculate how much frame time left
				sf::Time t1=sf::seconds(one_frame-((clock()/-start)/CLOCKS_PER_SEC));
				sf::sleep(t1);
			}
	}

framerate is set to 60 FPS, fraps shows 58.. I will work on that later, for now let's say everything is fine.

Events part does nothing for now, the logic part calculates the next position based on the velocity. If there is an obstacle or something needs to be changed, the velocity is changed. And now comes the render part:


int render_frames=20;
	while(render_frames--)
	{
		game->screen.draw(background);
		ball.show(game->screen);
		game->screen.display();
	}

The main loop (especially the logic part) calculated next position by calculating the velocity of the ball. So one game loop moves the ball from Originpoint to Originpoint+velocity. The moving part is rendered in (render_frames) number of frames. In this case the ball moves 20 times, everytime velocity/20 is added to its position. At the end of the render part the ball will be on the right position. Render part finished, main loop starts again etc..

But this has some drawbacks.

Let's say I have my velocity set to (10,10). Normally, it would travel the 800x600 window in a little more than 1 second, because it would move 600 pixels in one second. But when using the idea above, the ball just slows down, I would say it is a huge slowdown. So I have to set higher velocity, but then the rendering isn't smooth as it would be with lower velocity.. so I make the (render_frames) higher, but this causes the ball to slow down again. Like a loop :/

interpolation is what you do when you know where something was, and is going to be, and you need to make it traverse between those two points smoothly.

eg: you may be rendering at 60hz, but executing physics at 10hz, giving you new positions and velocities every 6 frames. To keep the physics from appearing to be running at 10hz, you would interpolate the old position toward the new position over the course of 6 frames.

The same situation takes place in multiplayer situations, where updates are only being received every couple of frames, you must make up for the sparseness of the data, and that's where interpolation comes in, smoothly blending from the last known position to the newly received position, instead of just popping objects to their updated position all herky jerky style.

Talking about interpolation, how you're supposed to handle it if the game for some reason goes slower than your fixed time step?

I tried to smooth out movement in a 3d map I did by interpolating the player's position (prolly side effect of crappy height detection on my part). If the frame time goes lower than the interpolation interval (in my case it was 50ms I think), crazy stuff starts to happen.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Talking about interpolation, how you're supposed to handle it if the game for some reason goes slower than your fixed time step?

I tried to smooth out movement in a 3d map I did by interpolating the player's position (prolly side effect of crappy height detection on my part). If the frame time goes lower than the interpolation interval (in my case it was 50ms I think), crazy stuff starts to happen.

That's one of the dirty little secrets of game development.

The frame that is shown to the user is actually several frames old.

What the user sees is often two, three, or more simulation steps behind the game.

Here are some concepts:
* Now. The time step in the game simulator.
* Latest step. The step you completed last 'now'. It is the last completed step in the game simulator, used for rendering.
* Previous step. This used to be Latest Step. It is kept around for rendering purposes, and sometimes for networking purposes.

* Current frame. The frame being composed. It is built by interpolating between the latest step and the previous step.
* Last frame, aka visible frame. The frame that has been swapped out and is being shown to the user.


Some hardware, such as the PS2, the last frame goes through additional post processing steps so the visible frame is often 3-5 simulation steps behind 'now'.

Decoupling the simulation from rendering enables quite a lot of useful tools, but it also can present quite a difficult learning curve.

Some hardware, such as the PS2, the last frame goes through additional post processing steps so the visible frame is often 3-5 simulation steps behind 'now'.

hmm, i've never built a game around this concept. woudn't running the renderer ~5 steps behind the simulation cause the user to have potentially noticeable input lag on heavy twitch based games?

I've adopted to using a fixed-time step simulation, and generally I split the renderer and simulation into different threads. this does mean that if my renderer is running slow, simulation steps might be skipped from being rendered, as when i construct the current render scene, i take the current simulation step to build my scene. but generally i try to make sure my target hardware can support my target simulation rate.

Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.

This topic is closed to new replies.

Advertisement