using System; using System.Collections.Generic; using UnityEngine; namespace PhysicsTools { public class Bezier { private Vector3[] knots; private Vector3[] firstControlPts; private Vector3[] secondControlPts; private int lastIndex = 1; private float lengthCovered; private float indexedLength; private float totalLength; public Bezier(List points) { Vector3[] array = new Vector3[points.Count]; for (int i = 0; i < points.Count; i++) { array[i] = points[i].pos; } init(array); } public Bezier(Vector3[] points) { init(points); } private void init(Vector3[] points) { knots = new Vector3[points.Length]; for (int i = 0; i < points.Length; i++) { knots[i] = points[i]; if (i != 0) { totalLength += (knots[i] - knots[i - 1]).magnitude; } } GetCurveControlPoints(knots, out firstControlPts, out secondControlPts); indexedLength = (knots[1] - knots[0]).magnitude; } public float TotalLength() { return totalLength; } public PosOri getNext(float deltaLen) { return new PosOri(getNextPos(deltaLen), Quaternion.identity); } public Vector3 getNextPos(float deltaLen) { bool flag = false; float num = indexedLength; float num2 = indexedLength; while (!flag) { num = indexedLength; num2 = indexedLength - (knots[lastIndex] - knots[lastIndex - 1]).magnitude; if (lengthCovered + deltaLen > num) { lastIndex++; if (lastIndex == knots.Length) { flag = true; deltaLen = num - lengthCovered; lastIndex = knots.Length - 1; } else { indexedLength += (knots[lastIndex] - knots[lastIndex - 1]).magnitude; } continue; } break; } float num3 = (lengthCovered + deltaLen - num2) / (num - num2); Vector3 result = (float)Math.Pow(1f - num3, 3.0) * knots[lastIndex - 1] + 3f * (float)Math.Pow(1f - num3, 2.0) * num3 * firstControlPts[lastIndex - 1] + 3f * (1f - num3) * num3 * num3 * secondControlPts[lastIndex - 1] + num3 * num3 * num3 * knots[lastIndex]; lengthCovered += deltaLen; return result; } private void GetCurveControlPoints(Vector3[] knots, out Vector3[] firstControlPoints, out Vector3[] secondControlPoints) { if (knots == null) { throw new ArgumentNullException("knots"); } int num = knots.Length - 1; if (num < 1) { throw new ArgumentException("At least two knot points required", "knots"); } if (num == 1) { firstControlPoints = new Vector3[1]; firstControlPoints[0].x = (2f * knots[0].x + knots[1].x) / 3f; firstControlPoints[0].y = (2f * knots[0].y + knots[1].y) / 3f; firstControlPoints[0].z = (2f * knots[0].z + knots[1].z) / 3f; secondControlPoints = new Vector3[1]; secondControlPoints[0].x = 2f * firstControlPoints[0].x - knots[0].x; secondControlPoints[0].y = 2f * firstControlPoints[0].y - knots[0].y; secondControlPoints[0].z = 2f * firstControlPoints[0].z - knots[0].z; return; } float[] array = new float[num]; for (int i = 1; i < num - 1; i++) { array[i] = 4f * knots[i].x + 2f * knots[i + 1].x; } array[0] = knots[0].x + 2f * knots[1].x; array[num - 1] = (8f * knots[num - 1].x + knots[num].x) / 2f; float[] firstControlPoints2 = GetFirstControlPoints(array); for (int j = 1; j < num - 1; j++) { array[j] = 4f * knots[j].y + 2f * knots[j + 1].y; } array[0] = knots[0].y + 2f * knots[1].y; array[num - 1] = (8f * knots[num - 1].y + knots[num].y) / 2f; float[] firstControlPoints3 = GetFirstControlPoints(array); for (int k = 1; k < num - 1; k++) { array[k] = 4f * knots[k].z + 2f * knots[k + 1].z; } array[0] = knots[0].z + 2f * knots[1].z; array[num - 1] = (8f * knots[num - 1].z + knots[num].z) / 2f; float[] firstControlPoints4 = GetFirstControlPoints(array); firstControlPoints = new Vector3[num]; secondControlPoints = new Vector3[num]; for (int l = 0; l < num; l++) { firstControlPoints[l] = new Vector3(firstControlPoints2[l], firstControlPoints3[l], firstControlPoints4[l]); if (l < num - 1) { secondControlPoints[l] = new Vector3(2f * knots[l + 1].x - firstControlPoints2[l + 1], 2f * knots[l + 1].y - firstControlPoints3[l + 1], 2f * knots[l + 1].z - firstControlPoints4[l + 1]); } else { secondControlPoints[l] = new Vector3((knots[num].x + firstControlPoints2[num - 1]) / 2f, (knots[num].y + firstControlPoints3[num - 1]) / 2f, (knots[num].z + firstControlPoints4[num - 1]) / 2f); } } } private float[] GetFirstControlPoints(float[] rhs) { int num = rhs.Length; float[] array = new float[num]; float[] array2 = new float[num]; float num2 = 2f; array[0] = rhs[0] / num2; for (int i = 1; i < num; i++) { array2[i] = 1f / num2; num2 = ((i >= num - 1) ? 3.5f : 4f) - array2[i]; array[i] = (rhs[i] - array[i - 1]) / num2; } for (int j = 1; j < num; j++) { array[num - j - 1] -= array2[num - j] * array[num - j]; } return array; } } }