Skip to content

Instantly share code, notes, and snippets.

@brihernandez
Last active August 24, 2021 19:45
Show Gist options
  • Save brihernandez/7a9912c0eb85e62709d52740d0a7dc54 to your computer and use it in GitHub Desktop.
Save brihernandez/7a9912c0eb85e62709d52740d0a7dc54 to your computer and use it in GitHub Desktop.
Like AnimationCurve, but dead simple and linear only. Is it really even a curve?
using System.Collections.Generic;
/// <summary>
/// Creates a very simple linear graph that can be sampled along arbitrary points. Clamps to
/// the nearest value when sampled out of range. This class assumes that all points given are
/// ALREADY SORTED from smallest to largest in the X axis. There is NO automatic sorting.
/// </summary>
public class InterpolatedCurve
{
public List<(float, float)> Points = new List<(float, float)>();
public InterpolatedCurve(List<UnityEngine.Vector2> values)
{
foreach (var v in values)
Points.Add((v.x, v.y));
}
public InterpolatedCurve(UnityEngine.AnimationCurve curve)
{
foreach (var keyframe in curve.keys)
Points.Add((keyframe.time, keyframe.value));
}
public InterpolatedCurve(IEnumerable<(float, float)> points)
{
Points.AddRange(points);
}
public void AddPoint(float x, float y)
{
Points.Add((x, y));
}
public void Clear()
{
Points.Clear();
}
public float Sample(float x)
{
if (Points.Count == 0)
return 0f;
// Check lower bounds.
if (x <= Points[0].Item1)
return Points[0].Item2;
// Check upper bounds.
if (x >= Points[Points.Count - 1].Item1)
return Points[Points.Count - 1].Item2;
// Typical case for on a curve.
for (int i = 0; i < Points.Count - 1; ++i)
{
if (Points[i].Item1 <= x && Points[i + 1].Item1 > x)
{
//var lerp = Mathf.InverseLerp(Points[i].Item1, Points[i + 1].Item1, x);
//return Mathf.Lerp(Points[i].Item2, Points[i + 1].Item2, lerp);
return Maths.Remap(
Points[i].Item1, Points[i + 1].Item1,
Points[i].Item2, Points[i + 1].Item2,
x);
}
}
return 0f;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment