OvertakingLegend/Assets/Script/Tool/BezierCurve.cs

112 lines
2.8 KiB
C#
Raw Normal View History

2025-03-24 03:08:22 +00:00
using System.Collections.Generic;
using UnityEngine;
/*<EFBFBD><EFBFBD>ַ
https://blog.csdn.net/linxinfa/article/details/116808549
*/
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߹<EFBFBD><DFB9><EFBFBD>
/// </summary>
public class BezierCurve : MonoBehaviour
{
/// <summary>
/// <20><><EFBFBD>Ƶ㣨<C6B5><E3A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD>
/// </summary>
[SerializeField]
private Transform[] points;
/// <summary>
/// <20><>ȷ<EFBFBD><C8B7>
/// </summary>
[SerializeField]
private int accuracy = 20;
private void Update()
{
// <20><><EFBFBD>Ʊ<EFBFBD><C6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Vector3 prev_pos = points[0].position;
for (int i = 0; i <= accuracy; ++i)
{
Vector3 to = CalculateBezierPoint(i / (float)accuracy, points);
Debug.DrawLine(prev_pos, to, Color.green);
prev_pos = to;
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.white;
// <20><><EFBFBD>ƿ<EFBFBD><C6BF>Ƶ㣨<C6B5><E3A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD>
for (int i = 0; i < points.Length; ++i)
{
if (i < points.Length - 1)
{
if (4 == points.Length && i == 1)
{
continue;
}
Vector3 current = points[i].position;
Vector3 next = points[i + 1].position;
Gizmos.DrawLine(current, next);
}
}
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
/// </summary>
/// <returns></returns>
public List<Vector3> GeneratePaths()
{
List<Vector3> paths = new List<Vector3>();
for (int i = 0; i <= accuracy; ++i)
{
Vector3 to = CalculateBezierPoint(i / (float)accuracy, points);
paths.Add(to);
}
return paths;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><E3B1B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
private Vector3 CalculateBezierPoint(float t, Transform[] controlPoints)
{
Vector3[] points = new Vector3[controlPoints.Length];
for (int i = 0; i < controlPoints.Length; i++)
{
points[i] = controlPoints[i].position;
}
return CalculateBezierPoint(t, points);
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><E3B1B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
private Vector3 CalculateBezierPoint(float t, Vector3[] points)
{
int n = points.Length - 1;
Vector3 result = Vector3.zero;
for (int i = 0; i <= n; i++)
{
result += BinomialCoefficient(n, i) * Mathf.Pow(1 - t, n - i) * Mathf.Pow(t, i) * points[i];
}
return result;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD>ʽϵ<CABD><CFB5>
/// </summary>
private int BinomialCoefficient(int n, int k)
{
if (k == 0 || k == n)
{
return 1;
}
return BinomialCoefficient(n - 1, k - 1) + BinomialCoefficient(n - 1, k);
}
}