Simo Virokannas

Writings and ramblings

Spline interpolation in Swift

Just so that the next person can avoid having to do the wikipedia-math-formula-to-Swift conversion, here’s a simple Catmull-Rom interpolation method for linear y=x data. I’m using it to create simple ski jump hill profiles for a possibly upcoming game, it’s so easy to describe a hill profile by just giving it control points and let the interpolator do the math. This will work just fine for any time-based keyframe data, too.

Notes: you need to give 4 different points of data – if you give duplicates, the formula will turn the return value into a NaN for obvious reasons.

I’m using a simple 2d point data to feed the thing.

[cc lang=”swift”]
class Point {
var x : Float = 0.0
var y : Float = 0.0
}

// t: relative position between p1 and p2, in 0 .. 1 range
// i left it as a relative value so that this can easily
// be turned into a general-purpose 2d curve interpolator
// p0, p1, p2, p3: the four points
func CatmullRom(t: Float, _ p0: Point, _ p1: Point, _ p2: Point, _ p3: Point) -> Float
{
let alpha : Float = 0.5
let t0 : Float = 0.0
let t1 = t0 + alpha * (sqrtf(powf(p1.x – p0.x, 2.0) + powf(p1.y – p0.y, 2.0)))
let t2 = t1 + alpha * (sqrtf(powf(p2.x – p1.x, 2.0) + powf(p2.y – p1.y, 2.0)))
let t3 = t2 + alpha * (sqrtf(powf(p3.x – p2.x, 2.0) + powf(p3.y – p2.y, 2.0)))
let tt = t * (t2 – t1) + t1

let a1 = (t1 – tt) / (t1 – t0) * p0.y + (tt – t0) / (t1 – t0) * p1.y
let a2 = (t2 – tt) / (t2 – t1) * p1.y + (tt – t1) / (t2 – t1) * p2.y
let a3 = (t3 – tt) / (t3 – t2) * p2.y + (tt – t2) / (t3 – t2) * p3.y

let b1 = (t2 – tt) / (t2 – t0) * a1 + (tt – t0) / (t2 – t0) * a2
let b2 = (t3 – tt) / (t3 – t1) * a2 + (tt – t1) / (t3 – t1) * a3

let c = (t2 – tt) / (t2 – t1) * b1 + (tt – t1) / (t2 – t1 ) * b2

return c
}
[/cc]

Source for the formula and picture:
https://en.wikipedia.org/wiki/Centripetal_Catmull–Rom_spline


Comments

4 responses to “Spline interpolation in Swift”

  1. Rohith Vishwajith

    Is there any chance you have this in 3D? I was having a hard time implementing it in 3D, since I’m still in school I don’t really understand this level of math yet, although I’ve recently started trying to learn it.

    Thanks!
    – Rohith

    1. This example shows how to turn four points into a parametric 2d curve between points p1 and p2 – to do the same in 3D, you would probably need to do the math in at least two parameter pairs (x/y and x/z) or even better, do it three times and have the whole thing be parametric as described in this stackexchange post. I might try that and post it one day.

      1. Rohith Vishwajith

        Hey!

        Just wanted to let you know I was able to do it in Unity and it ended up being quite easy! Thanks for the reference.

        1. Glad to hear that!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.