대표적인 Spline들은 다음과 같습니다.
복잡한 곡선을 분할해(spline) 3차 다항식의 근사를 이용하기 때문에 모두 4개의 샘플값을 인자로 받고(v0, v1, v2, v3), 추가적으로 주어진 구간중 어디를 원하는지를 t1을 통해 인자로 받게 됩니다.
inline float catmullRom(float t1, float v0, float v1, float v2, float v3)
{
float t2 = t1 * t1;
float t3 = t2 * t1;
return (( - t3 + 2.0f * t2 - t1 ) * v0 +
( 3.0f * t3 - 5.0f * t2 + 2.0f) * v1 +
(-3.0f * t3 + 4.0f * t2 + t1 ) * v2 +
( t3 - t2 ) * v3) / 2.0f;
}
inline float bSpline(float t1, float v0, float v1, float v2, float v3)
{
float t2 = t1 * t1;
float t3 = t2 * t1;
return (( - t3 + 3.0f * t2 - 3.0f * t1 + 1.0f) * v0 +
( 3.0f * t3 - 6.0f * t2 + 4.0f) * v1 +
(-3.0f * t3 + 3.0f * t2 + 3.0f * t1 + 1.0f) * v2 +
( t3 ) * v3) / 6.0f;
}
inline float hermite(float t1, float v0, float v1, float v2, float v3)
{
float t2 = t1 * t1;
float t3 = t2 * t1;
return (( 2.0f * t3 - 3.0f * t2 + 1.0f) * v0 +
(-2.0f * t3 + 3.0f * t2 ) * v1 +
( t3 - 2.0f * t2 + t1 ) * v2 +
( t3 - t2 ) * v3);
}
inline float bezier(float t1, float v0, float v1, float v2, float v3)
{
float t2 = t1 * t1;
float t3 = t2 * t1;
return (( - t3 + 3.0f * t2 - 3.0f * t1 + 1.0f) * v0 +
( 3.0f * t3 - 6.0f * t2 + 3.0f * t1 ) * v1 +
(-3.0f * t3 + 3.0f * t2 ) * v2 +
( t3 ) * v3);
}
v0, v1, v2, v3 는 각각 4개의 점의 y좌표라 생각하시면 되고,
t1은 v1 과 v2사이의 어디를 보간할 것인가를 0과 1 사이의 값으로 전달한 인자입니다.
v1 v2사이의 t1거리에 해당하는 v값을 리턴합니다.
위 함수중 하나를 선택하셔서, x에 대해 보간하시고, y에 대해 보간하시면 2차원상의 보간이,
x, y, z 에 대해 보간하시면 3차원상의 보간이 되는거죠.
물론 1차원 보간이 필요할 뿐이라면 x에 대해서만 보간하시면 됩니다.
catmullRom 은 해당하는 v값들을 정확히 지나는 특성을 가지고,
bSpline이나 bezier는 그러지 못하며, bSpline은 가장 완만한 형태를 갖게 됩니다.
hermite는 위와 달리 인자로 v0, v1을 지날때의 기울기를 추가 인자로받게 되는데,
이를 0으로 셋팅하면 각점을 수평으로 지나는 곡선을 얻을 수 있고,
지그재그로 표현되는 주파수의 변곡점을 수평으로 보간할때 유용하게 사용하실 수 있을 뿐 아니라
변곡점의 기울기가 0일때는 당연히 표현도 줄어들게 됩니다.
inline float hermite0(float t1, float v0, float v1)
{
float t2 = t1 * t1;
float t3 = t2 * t1;
return (( 2.0f * t3 - 3.0f * t2 + 1.0f) * v0 +
(-2.0f * t3 + 3.0f * t2 ) * v1);
}
많은 자료를 고속으로 처리해야 할 때 위에 열거한 spline 들의 atom 함수를 최적화 하기 위한 포인트는
v0, v1, v2, v3의 재사용입니다.
만약 등간격의 monotone 을 구현하신다면, (증가 또는 감소만 하는)
t1, t2, t3도 재사용해 보다 빠른 코드(곱하기 네 번, 더하기 세 번, 대입 한 번만 하는 코드)를 작성하실 수 있습니다.
계속 고민하고 있는 중인데 도움 부탁드립니다.