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