まず、3 次エルミート スプライン関数を作成しましょう。
/*
t - in interval <0..1>
p0 - Start position
p1 - End position
m0 - Start tangent
m1 - End tangent
*/
double CubicHermite(double t, double p0, double p1, double m0, double m1) {
t2 = t*t;
t3 = t2*t;
return (2*t3 - 3*t2 + 1)*p0 + (t3-2*t2+t)*m0 + (-2*t3+3*t2)*p1 + (t3-t2)*m1;
}
次に、イーズイン部分とイーズアウト部分の両方について、p0、p1、m0、および m1 を計算します。数学を書きやすくするために、いくつかの変数を追加しましょう。
double Interpolate(
double timeToAccel, double timeCruising, double timeToDecel,
double finalPosition,
double currentTime) {
double t1 = timeToAccel;
double t2 = timeCruising;
double t3 = timeToDecel;
double x = finalPosition;
double t = currentTime;
オブジェクトが加速を停止して減速を開始するときの位置を指定する必要があります。これらを好きなように指定して、スムーズな動きを生成することもできますが、ある程度「自然な」解決策が必要です。
巡航速度を としましょうv
。巡航中、オブジェクトは距離を移動しますx2 = v * t2
。ここで、オブジェクトが 0 から速度 v まで加速すると、距離 を移動しますx1 = v * t1 / 2
。減速も同様x3 = v * t3 / 2
。すべてをまとめる:
x1 + x2 + x3 = x
v * t1 / 2 + v * t2 + v * t3 / 2 = x
そこから、速度と距離を計算できます。
double v = x / (t1/2 + t2 + t3/2);
double x1 = v * t1 / 2;
double x2 = v * t2;
double x3 = v * t3 / 2;
すべてがわかったので、それを 3 次エルミート スプライン補間器に入力します。
if(t <= t1) {
// Acceleration
return CubicHermite(t/t1, 0, x1, 0, v*t1);
} else if(t <= t1+t2) {
// Cruising
return x1 + x2 * (t-t1) / t2;
} else {
// Deceleration
return CubicHermite((t-t1-t2)/t3, x1+x2, x, v*t3, 0);
}
}
これを Excel でテストしました。これは、同等の VBA コードです。境界条件にはゼロによる除算がいくつかあります。これに対する修正は、読者の演習として残します。
Public Function CubicHermite(t As Double, p0 As Double, p1 As Double, _
m0 As Double, m1 As Double) As Double
t2 = t * t
t3 = t2 * t
CubicHermite = (2 * t3 - 3 * t2 + 1) * p0 + _
(t3 - 2 * t2 + t) * m0 + (-2 * t3 + 3 * t2) * p1 + (t3 - t2) * m1
End Function
Public Function Interpolate(t1 As Double, t2 As Double, t3 As Double, _
x As Double, t As Double) As Double
Dim x1 As Double, x2 As Double, x3 As Double
v = x / (t1 / 2 + t2 + t3 / 2)
x1 = v * t1 / 2
x2 = v * t2
x3 = v * t3 / 2
If (t <= t1) Then
Interpolate = CubicHermite(t / t1, 0, x1, 0, v*t1)
ElseIf t <= t1 + t2 Then
Interpolate = x1 + x2 * (t - t1) / t2
Else
Interpolate = CubicHermite((t-t1-t2)/t3, x1+x2, x, v*t3, 0)
End If
End Function