# Function CubicSpline

## Summary

``````#include <Source/Falcor/Utils/Math/CubicSpline.h>

(1) CubicSpline(const T *controlPoints, uint32_t pointCount)

(2) CubicSpline(const T *points, uint32_t pointCount, float const *durations)
``````

## Synopsis

``````#include <Source/Falcor/Utils/Math/CubicSpline.h>

CubicSpline(const T *controlPoints, uint32_t pointCount)
``````

## Description

Creates a position-based cubic spline.

Parameters:

[ in ] `controlPoints` - Array of control points

[ in ] `pointCount` - Number of control points

## Source

``````CubicSpline(const T* controlPoints, uint32_t pointCount)
{
// The following code is based on the article from http://graphicsrunner.blogspot.co.uk/2008/05/camera-animation-part-ii.html
static const T kHalf  = T(0.5f);
static const T kOne = T(1);
static const T kTwo = T(2);
static const T kThree = T(3);
static const T kFour = T(4);
// Calculate Gamma
std::vector<T> gamma(pointCount);
gamma = kHalf;
for(uint32_t i = 1; i < pointCount - 1; i++)
{
gamma[i] = kOne / (kFour - gamma[i - 1]);
}
gamma[pointCount - 1] = kOne / (kTwo - gamma[pointCount - 2]);
// Calculate Delta
std::vector<T> delta(pointCount);
delta = kThree * (controlPoints - controlPoints) * gamma;
for(uint32_t i = 1; i < pointCount; i++)
{
uint32_t index = (i == (pointCount - 1)) ? i : i + 1;
delta[i] = (kThree * (controlPoints[index] - controlPoints[i - 1]) - delta[i - 1]) * gamma[i];
}
// Calculate D
std::vector<T> D(pointCount);
D[pointCount - 1] = delta[pointCount - 1];
for(int32_t i = int32_t(pointCount - 2); i >= 0; i--)
{
D[i] = delta[i] - gamma[i] * D[i + 1];
}
// Calculate the coefficients
mCoefficient.resize(pointCount - 1);
for(uint32_t i = 0; i < pointCount - 1; i++)
{
mCoefficient[i].a = controlPoints[i];
mCoefficient[i].b = D[i];
mCoefficient[i].c = kThree * (controlPoints[i + 1] - controlPoints[i]) - kTwo * D[i] - D[i + 1];
mCoefficient[i].d = kTwo * (controlPoints[i] - controlPoints[i + 1]) + D[i] + D[i + 1];
}
}
``````

## Synopsis

``````#include <Source/Falcor/Utils/Math/CubicSpline.h>

CubicSpline(const T *points, uint32_t pointCount, float const *durations)
``````

## Description

Create a position and time-based cubic spline

Parameters:

[ in ] `controlPoints` - Array of control points

[ in ] `pointCount` - Number of control points

[ in ] `durations` - Array containing durations/intervals for each control point

## Source

``````CubicSpline(const T* points, uint32_t pointCount, float const* durations)
{
// The following code is based on the article from http://graphicsrunner.blogspot.co.uk/2008/05/camera-animation-part-ii.html
// http://math.stackexchange.com/questions/62360/natural-cubic-splines-vs-piecewise-hermite-splines
// https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
if (pointCount >= 2)
{
mCoefficient.resize(pointCount);
// Calculate Gamma =: mCoefficient.a
mCoefficient.a = T(.5f);
for (size_t i = 1; i < pointCount - 1; i++) {
mCoefficient[i].a = durations[i] / (T(2.f) * (durations[i - 1] + durations[i]) - durations[i - 1] * mCoefficient[i - 1].a);
}
mCoefficient[pointCount - 1].a = 1.0f / (T(2) - mCoefficient[pointCount - 2].a);
// Calculate Delta =: mCoefficient.b
mCoefficient.b = T(3) / durations * (points - points) * mCoefficient.a;
for (size_t i = 1; i < pointCount - 1; i++) {
mCoefficient[i].b = (T(3) / (durations[i - 1] * durations[i]) * (
durations[i - 1] * durations[i - 1] * (points[i + 1] - points[i])
+ durations[i] * durations[i] * (points[i] - points[i - 1])
)
- durations[i - 1] * mCoefficient[i - 1].b) * mCoefficient[i].a / durations[i];
}
mCoefficient[pointCount - 1].b = (T(3) / durations[pointCount - 2] * (points[pointCount - 1] - points[pointCount - 2]) - mCoefficient[pointCount - 2].b) * mCoefficient[pointCount - 1].a;
// Calculate D := mCoefficient.d
mCoefficient[pointCount - 1].d = mCoefficient[pointCount - 1].b;
for (size_t i = pointCount - 1; i-- > 0;) {
mCoefficient[i].d = mCoefficient[i].b - mCoefficient[i].a * mCoefficient[i + 1].d;
}
// Calculate actual spline
for (size_t i = 0; i < pointCount - 1; i++) {
mCoefficient[i].a = points[i];
mCoefficient[i].b = mCoefficient[i].d * durations[i];
mCoefficient[i].c = T(3) * (points[i + 1] - points[i]) - T(2) * mCoefficient[i].d * durations[i] - mCoefficient[i + 1].d * durations[i];
mCoefficient[i].d = T(2) * (points[i] - points[i + 1]) + mCoefficient[i].d * durations[i] + mCoefficient[i + 1].d * durations[i];
}
mCoefficient.resize(pointCount - 1);
}
}
``````