Framerate Independent Interpolation:
So one of my favorite math tricks is simple damping. Say you have a moving object that you want to apply some drag to. The easy way to do it is to multiply the velocity of the object by a number slightly less than 1.0 each frame:
speed = speed*0.99
Despite the simplicity, this is a pretty good approximation of drag. The faster the object is moving, the faster it will slow down. Using a similar method, you can smooth out noisy input data or target positions for an object to follow:
value = lerp(value, targetValue, 0.1)
Each time this is called, value will move closer to targetValue, and the greater the difference, the faster it will converge.
Both of these suffer from a major problem. The damping value used is highly dependent on the framerate. If you call it once per frame and the framerate slows way down, so will the movement. That’s not good at all! You can always call it at a fixed rate, but that’s not alway convenient. Fortunately with a little extra math, you can fix this problem completely.
value = lerp(value, targetValue, pow(0.1, dt))
Where ‘dt’ is the time that has passed since you last called it. Before you were simply moving 10% of the way towards the target value each frame, now you are moving 10% per second. This is much better, and won’t get messed up when your framerate fluctuates.
Another related trick that I really like is logarithmic interpolation. A mistake that I often see in games is when they do something like this:
scale = lerp(scale, targetScale, 0.1)
Scale, zooming, and sound frequencies are not really perceived as linear quantities, and lerping between them will just seem off. The problem gets worse the greater the ratio between scale and targetScale. The correct way to interpolate such values is to do it logarithmicly. Basically, like this:
scale = exp(lerp(log(scale), log(targetScale), 0.1)
Use linear interpolation on the values after converting them to logarithmic values, then use
exp() to convert the logarithmic value back. That’s a lot of expensive math functions to call however! If you remember your log and power rules, you can simplify that to a single pow() call instead:
scale = scale*pow(targetScale/scale, 0.1)
You can combine this with the framerate independence trick from above too. Add these tricks to your math library and give them a whirl.