Creación de la curva Unity Bezier

Creación de la curva Unity Bezier

Efecto

Por favor agregue una descripción de la imagen

Principio de la curva de Bezier

La curva de Bezier comúnmente utilizada es una curva matemática para aplicaciones de gráficos bidimensionales. Definición de la curva: punto inicial, punto final, punto de control. Al ajustar los puntos de control, la forma de la curva Bezier cambia.

recta de primer orden

Cómo agregar CC en la imagen de abajoEl punto C está dentro del tiempo establecido, desdeAAEl punto A se mueve aBBPunto B ? Aquí establece un tiempot , t ∈ ( 0 , 1 ) t ,t \in(0,1)t ,t( 0 ,1 ) ,

establecer _OA ⃗ \vec{OA}en el tiempo tO A Igualmente abreviado a OE ⃗ \vec{OE}Equipo original , OB ⃗ \vec{OB}transmisión exterior El vector unitario de se extiende a OF ⃗ \vec{OF}DE
OE ⃗ = OA ⃗ ( 1 − t ) \vec{OE}=\vec{OA}(1-t)Equipo original =O A ( 1t )
DE ⃗ = OB ⃗ × t \vec{OF}=\vec{OB}\times tDE =transmisión exterior ×t
OC ⃗ = OA ⃗ ( 1 − t ) + OB ⃗ × t \vec{OC}=\vec{OA}(1-t)+\vec{OB}\times tjefe =O A ( 1t )+transmisión exterior ×t

De esta manera puedes obtener CCEl punto C está dentro del tiempo establecido, desdeAAEl punto A se mueve aBBInterpolación del punto B.

 Vector3 AB = (1 - t) * OA + t * OB;

curva de segundo orden

El segundo orden se basa en el algoritmo de primer orden, que trata con AB ⃗ \vec{AB} por separadoun b BC ⃗ \vec{BC}antes de Cristo

 Vector3 AB = (1 - t) * OA + t * OB;
 Vector3 BC = (1 - t) * OB + t * OC;

Entonces AB ⃗ \vec{AB}un b BC ⃗ \vec{BC}antes de Cristo También realiza el procesamiento de algoritmos de primer orden.

 Vector3 ABC = (1 - t) * AB + t * BC;

curva de tercer orden

El tercer orden es similar al segundo orden y continúa acumulándose.

   Vector3 AB = (1 - t) * OA + t * OB;
   Vector3 BC = (1 - t) * OB + t * OC;
   Vector3 CD = (1 - t) * OC + t * OD;

   Vector3 ABC = (1 - t) * AB + t * BC;
   Vector3 BCD = (1 - t) * BC + t * CD;

   result = (1 - t) * ABC + t * BCD;

Los siguientes cuatro de alto nivel y así sucesivamente. El tercer orden es de uso común en la vida diaria, es decir, cuatro puntos determinan una curva.

Aplicación en unidad

El propósito es obtener los puntos de la curva a través de la curva Bezier para establecer los datos de la trayectoria del movimiento.

Cree una herramienta Bézier a través de la herramienta de extensión de edición de la interfaz.

#if UNITY_EDITOR
    public class BesselPathCreat : ScriptableWizard
    {
        public string Name = "Path";
        // 点的半径
        public float radius = 1;
        // 曲线取点的密度
        public int densityCurve = 1;
        /// <summary>
        /// 绘制曲线控制点 -- 此脚本的子物体
        /// </summary>
        public List<GameObject> PathPointList = new List<GameObject>();

        DrawGizmosLine drawGizmosLint;
        GameObject game;

        [MenuItem("FrameWorkSong//FrameWork/3.创建贝塞尔路径", false, 3)]
        static void CreateBasselPath()
        {
            ScriptableWizard.DisplayWizard<BesselPathCreat>("CreateBasselPath", "创建", "加点");

        }
        /// <summary>
        /// 创建按钮触发
        /// </summary>
        void OnWizardCreate()
        {
            if (PathPointList.Count > 4)
            {
                var level = ScriptableObject.CreateInstance<BasselPathTemplet>();
                level.BasselPathPoints = drawGizmosLint.CurvePoints;
                AssetDatabase.CreateAsset(level, @"Assets/FrameWorkSong/Data/" + Name + ".asset");//在传入的路径中创建资源
                AssetDatabase.SaveAssets(); //存储资源
                AssetDatabase.Refresh(); //刷新

            }


            DestroyObject();
        }
        /// <summary>
        /// 关闭触发
        /// </summary>
        void DestroyObject()
        {
            if (game)
            {
                DestroyImmediate(game);
            }
            for (int i = 0; i < PathPointList.Count; i++)
            {
                DestroyImmediate(PathPointList[i]);
            }
        }
        void OnWizardUpdate()
        {
            
        }
        /// <summary>
        /// 加点按钮触发
        /// </summary>
        // When the user presses the "Apply" button OnWizardOtherButton is called.
        void OnWizardOtherButton()
        {

            if (PathPointList.Count == 0)
            {
                game = new GameObject();
                drawGizmosLint = game.AddComponent<DrawGizmosLine>();
            }
            BasselPath basselPath = new BasselPath();
            DrawGizmosPointLine drawGizmos = basselPath.MianPiont.AddComponent<DrawGizmosPointLine>();
            PathPointList.Add(basselPath.FrontPiont);
            PathPointList.Add(basselPath.MianPiont);
            PathPointList.Add(basselPath.BackePiont);
            drawGizmos.SelfPoint = basselPath.Piont;
            drawGizmosLint.SelfPoint = PathPointList;
            drawGizmosLint.densityCurve = densityCurve;
            drawGizmosLint.radius = radius;
        }
        void OnDestroy()
        {
            DestroyObject();
        }


    }
#endif

Usada aquí, la clase se deriva para crear asistentes de edición. Para obtener más información, consulte la API oficial https://docs.unity3d.com/cn/current/ScriptReference/ScriptableWizard.html

Cómo crear Bézier

 public class BasselPath
    {
        List<GameObject> piont = new List<GameObject>();
        GameObject mianPiont;
        GameObject frontPiont;
        GameObject backePiont;
        public BasselPath()
        {
            mianPiont = new GameObject();
            mianPiont.transform.position = Vector3.zero;
            frontPiont = new GameObject();
            frontPiont.transform.position = Vector3.zero + (Vector3.right * 5);

            backePiont = new GameObject();
            backePiont.transform.position = Vector3.zero + (Vector3.left * 5);

            piont.Add(frontPiont);
            piont.Add(mianPiont);
            piont.Add(backePiont);
            backePiont.transform.SetParent(mianPiont.transform);
            frontPiont.transform.SetParent(mianPiont.transform);
            mianPiont.AddComponent<DrawGizmosPoint>();
            frontPiont.AddComponent<DrawGizmosPoint>();
            backePiont.AddComponent<DrawGizmosPoint>();
        }

        public GameObject MianPiont { get => mianPiont; set => mianPiont = value; }
        public GameObject FrontPiont { get => frontPiont; }
        public GameObject BackePiont { get => backePiont; }
        public List<GameObject> Piont { get => piont; }
    }



    /// <summary>
    /// 绘制节点
    /// </summary>
    public class DrawGizmosPoint : MonoBehaviour
    {
        public float radius = 1;
        private void OnDrawGizmos()
        {
            //绘制点
            Gizmos.color = Color.blue;
            Gizmos.DrawSphere(transform.position, radius * 0.5f);
        }
    }
    /// <summary>
    /// 绘制节点线
    /// </summary>
    public class DrawGizmosPointLine : MonoBehaviour
    {
        public float radius = 1;
        public List<GameObject> SelfPoint = new List<GameObject>();
        private void OnDrawGizmos()
        {
            List<Vector3> controlPointPos = SelfPoint.Select(point => point.transform.position).ToList();



            //绘制曲线控制点连线
            Gizmos.color = Color.red;
            for (int i = 0; i < controlPointPos.Count - 1; i += 3)
            {
                Gizmos.DrawLine(controlPointPos[i], controlPointPos[i + 1]);
                Gizmos.DrawLine(controlPointPos[i + 1], controlPointPos[i + 2]);
            }
        }
    }
    /// <summary>
    /// 绘制曲线
    /// </summary>
    public class DrawGizmosLine : MonoBehaviour
    {
        public float radius;
        public int densityCurve;
        public List<GameObject> SelfPoint;
        public List<Vector3> CurvePoints;
        private void OnDrawGizmos()
        {
            List<Vector3> controlPointPos = SelfPoint.Select(point => point.transform.position).ToList();
            if (controlPointPos != null)
            {
                CurvePoints = GetDrawingPoints(controlPointPos, densityCurve);
            }

            //绘制曲线
            if (CurvePoints.Count >= 4)
            {
                Gizmos.color = Color.green;
                //点密度
                foreach (var item in CurvePoints)
                {
                    Gizmos.DrawSphere(item, radius * 0.5f);
                }
                //曲线
                for (int i = 0; i < CurvePoints.Count - 1; i++)
                {
                    Gizmos.DrawLine(CurvePoints[i], CurvePoints[i + 1]);
                }
            }


        }
        /// <summary>
        /// 获取绘制点
        /// </summary>
        /// <param name="controlPoints"></param>
        /// <param name="segmentsPerCurve"></param>
        /// <returns></returns>
        public List<Vector3> GetDrawingPoints(List<Vector3> controlPoints, int segmentsPerCurve)
        {
            List<Vector3> points = new List<Vector3>();
            // 下一段的起始点和上段终点是一个,所以是 i+=3
            for (int i = 1; i < controlPoints.Count - 4; i += 3)
            {

                var p0 = controlPoints[i];
                var p1 = controlPoints[i + 1];
                var p2 = controlPoints[i + 2];
                var p3 = controlPoints[i + 3];
                float dis = Vector3.Distance(p0, p3);
                int count = Mathf.CeilToInt(segmentsPerCurve * dis);
                if (count < segmentsPerCurve)
                {
                    count = segmentsPerCurve;
                }

                for (int j = 0; j <= count; j++)
                {
                    var t = j / (float)count;
                    points.Add(CalculateBezierPoint(t, p0, p1, p2, p3));
                }
            }
            return points;
        }
        // 三阶公式
        Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
        {
            Vector3 result;

            Vector3 p0p1 = (1 - t) * p0 + t * p1;
            Vector3 p1p2 = (1 - t) * p1 + t * p2;
            Vector3 p2p3 = (1 - t) * p2 + t * p3;

            Vector3 p0p1p2 = (1 - t) * p0p1 + t * p1p2;
            Vector3 p1p2p3 = (1 - t) * p1p2 + t * p2p3;

            result = (1 - t) * p0p1p2 + t * p1p2p3;
            return result;
        }

    }


Supongo que te gusta

Origin blog.csdn.net/dxs1990/article/details/125932828
Recomendado
Clasificación