 # Catmull-Rom Splines

I have been working on some code to generate procedural race tracks for a wipeout style game. Part of this work involved using splines to smooth out the track so it looks natural and curvy.

For this purpose I used a fourth order CatmulRom spline which has the nice property that its curve travels through the control points.

I also brushed of my high-school calculus and worked out a derivative function for the spline which is usefull for extracting normal vectors at any point on the curve.

``````// evaluate spine
// where t is between 0.f and 1.f
float catmullrom_spline(float t, float v0, float v1, float v2, float v3) {

const float c1 = /********/    1.0f * v1    /*******/   /********/;
const float c2 = -0.5f * v0 +  /*******/    0.5f * v2   /********/;
const float c3 =  1.0f * v0 + -2.5f * v1 +  2.0f * v2 + -0.5f * v3;
const float c4 = -0.5f * v0 +  1.5f * v1 + -1.5f * v2 +  0.5f * v3;

return (c4 * t*t*t) + (c3 * t*t) + (c2 * t) + c1;
}

// calculate spline derivative
// where t is between 0.f and 1.f
float catmullrom_spline_deriv(float t, float v0, float v1, float v2, float v3) {

const float c2 = -0.5f * v0 +  /*******/    0.5f * v2   /********/;
const float c3 =  1.0f * v0 + -2.5f * v1 +  2.0f * v2 + -0.5f * v3;
const float c4 = -0.5f * v0 +  1.5f * v1 + -1.5f * v2 +  0.5f * v3;

return (3.f * c4 * t*t) + (2.f * c3 * t) + (c2);
}``````

The above code is only one dimensional but it can be fairly easily scaled up to two or more dimensions as follows:

``````// evaluate spline
// where t is between 0.f and 1.f
float2 catmullrom_spline(float t, float2 v0, float2 v1, float2 v2, float2 v3) {
return float2{
catmullrom_spline(t, v0.x, v1.x, v2.x, v3.x),
catmullrom_spline(t, v0.y, v1.y, v2.y, v3.y)
};
}

// calculate spline derivative
// where t is between 0.f and 1.f
// note that the return value will most likely need to be normalized.
float2 catmullrom_spline_deriv(float t, float2 v0, float2 v1, float2 v2, float2 v3) {
return float2{
catmullrom_spline_deriv(t, v0.x, v1.x, v2.x, v3.x),
catmullrom_spline_deriv(t, v0.y, v1.y, v2.y, v3.y)
};
}``````

Hopefully these functions are usefull to someone at some point.