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]; } } }