namespace Zinnia.Utility
{
using System.Collections.Generic;
using UnityEngine;
using Zinnia.Data.Type;
///
/// A collection of helper methods generating points on a bezier curve.
///
public static class BezierCurveGenerator
{
private static readonly List calculatedPoints = new List();
///
/// Generates points on a bezier curve.
///
/// The number of points to generate.
/// Points defining the bezier curve.
/// The generated points.
public static HeapAllocationFreeReadOnlyList GeneratePoints(int pointsCount, IReadOnlyList controlPoints)
{
calculatedPoints.Clear();
float stepSize = pointsCount != 1 ? 1f / (pointsCount - 1) : pointsCount;
for (int index = 0; index < pointsCount; index++)
{
calculatedPoints.Add(GeneratePoint(controlPoints, index * stepSize));
}
return calculatedPoints;
}
///
/// Generates a point at a specific location along the control points.
///
/// The collection of points where the point can be generated.
/// The specific location along the collection where to generate the point.
///
private static Vector3 GeneratePoint(IReadOnlyList controlPoints, float pointLocation)
{
int index;
if (pointLocation >= 1f)
{
pointLocation = 1f;
index = controlPoints.Count - 4;
}
else
{
pointLocation = Mathf.Clamp01(pointLocation) * ((controlPoints.Count - 1) / 3f);
index = (int)pointLocation;
pointLocation -= index;
index *= 3;
}
float normalizedPointLocation = Mathf.Clamp01(pointLocation);
float oneMinusT = 1f - normalizedPointLocation;
return oneMinusT * oneMinusT * oneMinusT * controlPoints[index] + 3f * oneMinusT * oneMinusT * normalizedPointLocation * controlPoints[index + 1] + 3f * oneMinusT * normalizedPointLocation * normalizedPointLocation * controlPoints[index + 2] + normalizedPointLocation * normalizedPointLocation * normalizedPointLocation * controlPoints[index + 3];
}
}
}