Files
korenkonder_PD_Tool/KKdBaseLib/Interpolation/MOTI.cs
T
2021-04-29 07:41:23 +03:00

132 lines
3.6 KiB
C#

namespace KKdBaseLib.Interpolation
{
public class MOTI : IInterpolation<float> // MOT Interpolation
{
private KFT2[] array;
private int length;
private float f;
private float t;
private float v;
private float df;
private float @if;
private float rf;
private KFT2 firstKey;
private KFT2 lastKey;
public float RequestedFramerate { get => rf; set { rf = value; df = @if / rf; } }
public float Frame => f;
public float Time => t;
public float Value => v;
public bool IsNull => array == null || array.Length < 1;
public bool NotNull => array != null && array.Length > 0;
public MOTI(KFT2[] array, float interpolationFramerate = 60, float requestedFramerate = 60)
{
length = 0;
this.array = array; f = -1; df = @if = rf = t = v = 0;
@if = interpolationFramerate;
firstKey = lastKey = default;
RequestedFramerate = requestedFramerate;
f = -df;
ResetFrameCount();
if (array != null && array.Length > 0)
{
firstKey = array[0];
lastKey = array[array.Length - 1];
length = array.Length;
}
}
public float SetTime(float time)
{
t = time;
f = time * @if;
if (array == null || length < 1) v = 0.0f;
else v = Interpolate(f);
return v;
}
public float SetFrame(float frame)
{
t = frame / rf;
f = frame * df;
if (array == null || length < 1) v = 0.0f;
else v = Interpolate(f);
return v;
}
public float NextFrame(float time)
{
t += time;
f = t * @if;
if (array == null || length < 1) v = 0.0f;
else v = Interpolate(f);
return v;
}
public float NextFrame()
{
f += df;
t = f / @if;
if (array == null || length < 1) v = 0.0f;
else v = Interpolate(f);
return v;
}
private float Interpolate(float frame)
{
if (frame <= firstKey.F) return firstKey.V;
else if (frame >= lastKey.F) return lastKey.V;
KFT2 c, n;
unsafe
{
fixed (KFT2* ptr = array)
{
long key = 0;
long length = this.length;
long temp;
while (length > 0)
if (frame >= ptr[key + (temp = length >> 1)].F)
{
key += temp + 1;
length -= temp + 1;
}
else length = temp;
c = ptr[key - 1];
n = ptr[key];
}
}
float v;
if (frame <= c.F || frame >= n.F)
v = frame > c.F ? n.V : c.V;
else
{
float df = f - c.F;
float t = df / (n.F - c.F);
float t_1 = t - 1.0f;
return c.V + t * t * (3.0f - 2.0f * t) * (n.V - c.V) + (t_1 * c.T + t * n.T) * df * t_1;
}
return v;
}
public void ResetFrameCount() { f = -df; t = f / rf; }
public override string ToString() => $"F: {f}; T: {t}; V: {v}";
}
}