using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BezieTool
{
/// <summary>
/// 根據T值計算貝塞爾曲線
/// </summary>
/// <param name="t">T值</param>
/// <param name="p0">起始點</param>
/// <param name="p1">控制點</param>
/// <param name="p2">目標點</param>
/// <returns></returns> 根據T值計算出來的貝塞爾曲線點
private static Vector3 CalculateBezierPoint(float t, Vector3 p0,Vector3 p1,Vector3 p2)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 p = uu * p0;
p += 2 * u * t * p1;
p += tt * p2;
return p;
}
/// <summary>
/// 獲取存儲貝塞爾曲線的數組
/// </summary>
/// <param name="startPoint">起始點</param>
/// <param name="controlPoint">控制點</param>
/// <param name="endPoint">目標點</param>
/// <param name="segmentNum">採樣點的數量</param>
/// <returns></returns> 存儲貝塞爾曲線的數組
public static Vector3[] GetBeizePointList(Vector3 startPoint,Vector3 controlPoint, Vector3 endPoint,int segmentNum)
{
Vector3[] path = new Vector3[segmentNum];
for (int i= 1;i<=segmentNum; i++)
{
float t = i / (float)segmentNum;
Vector3 pixel = CalculateBezierPoint(t, startPoint, controlPoint, endPoint);
path[i - 1] = pixel;
}
return path;
}
/// <summary>
/// 根據T值計算貝塞爾曲線
/// </summary>
/// <param name="t">T值</param>
/// <param name="p0">起始點</param>
/// <param name="p1">控制點</param>
/// <param name="p2">目標點</param>
/// <returns></returns> 根據T值計算出來的貝塞爾曲線點
private static Vector3 CalculateBezierPoint3(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
float u = 1 - t;
float uu = (1-t) * (1-t);
float uuu = (1 - t) * (1 - t) * (1 - t);
float tt = t * t;
float ttt = t * t*t;
Vector3 p = uu * p0;
p = p0 * uuu + 3 * p1 * t * uu + 3*p2*tt*u + p3 * ttt;
return p;
}
/// <summary>
/// 獲取存儲貝塞爾曲線的數組
/// </summary>
/// <param name="startPoint">起始點</param>
/// <param name="controlPoint">控制點</param>
/// <param name="endPoint">目標點</param>
/// <param name="segmentNum">採樣點的數量</param>
/// <returns></returns> 存儲貝塞爾曲線的數組
public static Vector3[] GetBeizePointList3(Vector3 startPoint, Vector3 controlPoint1, Vector3 controlPoint2, Vector3 endPoint, int segmentNum)
{
Vector3[] path = new Vector3[segmentNum];
for (int i = 1; i <= segmentNum; i++)
{
float t = i / (float)segmentNum;
Vector3 pixel = CalculateBezierPoint3(t, startPoint, controlPoint1, controlPoint2 ,endPoint);
path[i - 1] = pixel;
}
return path;
}
//傳入頂點集合,得到高階的貝塞爾曲線,頂點數量不限
//vertexCount 爲構建曲線的頂點數,此數值越大麴線越平滑
public static Vector3[] GetBezierCurveWithUnlimitPoints(Vector3[] vertex, int vertexCount)
{
List<Vector3> pointList = new List<Vector3>();
pointList.Clear();
for (float ratio = 0; ratio <= 1; ratio += 1.0f / vertexCount)
{
pointList.Add(UnlimitBezierCurve(vertex, ratio));
}
pointList.Add(vertex[vertex.Length - 1]);
return pointList.ToArray();
}
public static Vector3 UnlimitBezierCurve(Vector3[] vecs, float t)
{
Vector3[] temp = new Vector3[vecs.Length];
for (int i = 0; i < temp.Length; i++)
{
temp[i] = vecs[i];
}
//頂點集合有多長,曲線的每一個點就需要計算多少次。
int n = temp.Length - 1;
for (int i = 0; i < n; i++)
{
//依次計算各兩個相鄰的頂點的插值,並保存,每次計算都會進行降階。剩餘多少階計算多少次。直到得到最後一條線性曲線。
for (int j = 0; j < n - i; j++)
{
temp[j] = Vector3.Lerp(temp[j], temp[j + 1], t);
}
}
//返回當前比例下曲線的點
return temp[0];
}
}
public void PlayBezie()
{
Debug.Log("xxxx----PlayBezie");
Vector3 startPoint = transform.position;
Vector3 controlPotint = new Vector3(startPoint.x+2, startPoint.y+2, startPoint.z);
Vector3 controlPotint2 = new Vector3(startPoint.x + 3, startPoint.y + 5, startPoint.z);
Vector3 endPoint = new Vector3(startPoint.x + 6, startPoint.y, startPoint.z);
path = null;
Vector3[] ctro = { startPoint, controlPotint, controlPotint2, endPoint };
path = null;
path = BezieTool.GetBeizePointList(startPoint, controlPotint, endPoint, 100);
//path = BezieTool.GetBezierCurveWithUnlimitPoints(ctro, 100);
bezieMove = true;
}
public void UpateBeziePos()
{
if (bezieMove)
{
timeNum += Time.deltaTime;
//if(timeNum >0.03f)
{
transform.position = path[index];
timeNum = 0;
index += 1;
if (index == path.Length)
{
bezieMove = false;
index = 0;
}
}
}
}