貝塞爾曲線

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


            }
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章