# Curve interpolation

This week I struggled with creating a function of a certain shape. I want to position the camera in our game depending on the zoom level. To make this look smooth I was looking for a function that gave me a good looking trajectory based on the zoom level. The zoom level increases in a linear fashion. O BTW, the position of the camera is one dimensional value in my case (don’t ask me why). Basically I was looking for an interpolation function with a strange shape.

The function I was looking for should look somewhat like this (I drew this one by hand):

The first thing I did was turn to mathematics. I noticed that the function has two parts. First fast acceleration and then the very slow deceleration. So I started by using two function and then stitch them together. It was quite a hassle to glue the two function together because they have to have the same tangent at the end point of the first and the starting point of the second. In the end I came up with this:

It’s a two-fold piecewise eight order polynomial. I’m not going to bother you with the formula. Trust me: its a mess. But at least this worked. The camera moved naturally. However I noticed that when the player starts to zoom in or zooms all the way out there is giant change in camera position in a very short amount of time. You can clearly see this from the plot above at the start of the curve. It just wasn’t quite right. So I went back to the drawing board with my function.

After an hour of puzzling Adriaan came up to me and said: “Nice function bra, is it a cubic curve?” Sometimes this guy is an absolute genius. If I were to create a cubic curve I wouldn’t have so much trouble tweaking it. And it so happens that we already use bezier curves a lot. A cubic bezier curve is path controlled by four points. The formula for such is curve is:

[pmath size=12]B(t) = (1-t)^3P_1 + 3(1-t)^2tP_2 + 3(1-t)t^2P_3 + t^3P_4[/pmath]

Where P1 to 4 are the control points of the curve. Creating the curve was easy and I ended up with this:

That’s a hell of a lot better and super easy to tweak. But I quickly ran into the next problem. The function for the curve B(t) results in an *xy* position and has one parameter, namely *t*. I simply plugged the zoom level into the function and used the resulting *y* value for the position of the camera. However, *t* is not *x*. It so happens to be that there is a HUGE difference. The trick here is to first calculate *t* for *x *(the zoom level) and then use *t* to calculate *y*.

[pmath size=12]zoomlevel = B(t)_x[/pmath]

[pmath size=12]camera= B(t)_y[/pmath]

Solving this equation first requires us to convert the function to a third order polynomial:

[pmath size=12]B(t) = t^3(-P_1+3P_2 – 3P_3 + P_4) + t^2(3P_1 – 6P_2 + 3P_3) + t(-3P_1 + 3P_2) + P_1[/pmath]

Then solving the equation for *t* we can calculate *y*. Solving a third order polynomial is also quite tricky but with the help of my loyal Wikipedia and Google I was able to figure it out.

So that’s what I wanted to share with you. I am quite happy with the result and will probably be using interpolation with cubic curves a lot more.

Cheers!!

blog comments powered by Disqus