Vector3 calculate(float percentage) { var low = 0; var high = points.Length - 2; while (low < high) { var mid = (low + high) / 2; if (points[mid + 1].percentageOfPathTraveled < percentage) { low = mid + 1; } else { high = mid; } } var segmentPercentage = (percentage - points[low].percentageOfPathTraveled) / (points[low + 1].percentageOfPathTraveled - points[low].percentageOfPathTraveled); switch (method) { case InterpolationMethod.Linear: return(Vector3.Lerp( points[low].point, points[low + 1].point, segmentPercentage )); case InterpolationMethod.Cubic: return(InterpolationUtils.cubicGetPt( idx => points[idx].point, points.Length, low, segmentPercentage, closed )); case InterpolationMethod.Hermite: return(InterpolationUtils.hermiteGetPt( idx => points[idx].point, points.Length, low, segmentPercentage, closed )); case InterpolationMethod.CatmullRom: return(InterpolationUtils.catmullRomGetPt( idx => points[idx].point, points.Length, low, segmentPercentage, closed )); default: throw new ArgumentOutOfRangeException(); } }
public Vector3Path( InterpolationMethod method, bool closed, ImmutableArray <Vector3> positions, Option <Transform> relativeTo, int pathResolution ) { this.method = method; this.closed = closed; this.relativeTo = relativeTo; resolution = pathResolution; points = segmentLengthRatios(); //Distance to the last node is the whole path distance realLength = points[points.Length - 1].realDistanceToThisPoint; constantSpeedTable = new ConstantSpeedTable(resolution, calculate); // Returns list of Points with Vector3 coordinates, // length and segment length ratios added to prev element ratio and // distance from the start to this point ImmutableArray <Point> segmentLengthRatios() { switch (method) { case InterpolationMethod.Linear: { var builder = ImmutableArray.CreateBuilder <Point>(positions.Length); var length = positions.Aggregate(0f, (node, current, idx) => idx == 0 ? current : current + Vector3.Distance(positions[idx - 1], node) ); builder.Add(new Point(positions[0], 0f, 0f)); for (var idx = 1; idx < positions.Length; idx++) { var distanceBetweenPositions = Vector3.Distance(positions[idx - 1], positions[idx]); var previousPoint = builder[idx - 1]; builder.Add(new Point( positions[idx], distanceBetweenPositions / length + previousPoint.percentageOfPathTraveled, distanceBetweenPositions + previousPoint.realDistanceToThisPoint )); } return(builder.MoveToImmutable()); } case InterpolationMethod.Hermite: { return(getSegmentRatios( positions, (segmentIndex, percentageOfPath) => InterpolationUtils.hermiteGetPt( idx => positions[idx], positions.Length, segmentIndex, percentageOfPath, closed ))); } case InterpolationMethod.Cubic: { return(getSegmentRatios( positions, (segmentIndex, percentageOfPath) => InterpolationUtils.cubicGetPt( idx => positions[idx], positions.Length, segmentIndex, percentageOfPath, closed ))); } case InterpolationMethod.CatmullRom: { return(getSegmentRatios( positions, (segmentIndex, percentageOfPath) => InterpolationUtils.catmullRomGetPt( idx => positions[idx], positions.Length, segmentIndex, percentageOfPath, closed ))); } default: throw new ArgumentOutOfRangeException(); } } }