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.