Unity - 贝塞尔曲线浅析

作者: 能不写代码么 | 来源:发表于2020-12-14 00:33 被阅读0次
    贤妻插画图

    定义

    • 在任意几个点坐标绘制出的一条曲线,就叫贝塞尔曲线
    • 用我的大白话理解就是:大事化小,小事化了。看到三次方你会发现其实就是通过四个点反复计算,首先是计算出这四个点组成的对应的三条线段上的三个t点,再次计算出三条线段中三个t点组成的两条线段对应两个新的t点,在下一步和之前一样了,就是求出最终的点,N次方的曲线更是同理(可能有点绕好好理解下)

    一次方公式

    //求公式过程
      B(t) = P0 + (P1 - P0)t
           = P0 + tP1 - tP0
           = (1 - t)P0 + tP1
      //当 t = 0 时,结果为起始点P0
      //当 t = 1 时,结果为终点P1
        //程序中使用
        Vector3 Bezier(Vector3 p0, Vector3 p1, float t)
        {
            return (1 - t) * p0 + t * p1;
        }
    

    二次方公式

    //求公式过程
      //由一次方公式得到下面这两个公式
      P0P1 = (1 - t)P0 + tP1
      P1P2 = (1 - t)P1 + tP2
      //图中的绿色点代表了我们最终想要得到的点B(t),可以看做是需要得到P0P1和P1P2这条线段上的一个点,再将P0P1和P1P2换为我们上面得到的公式
      B(t) = (1 - t)P0P1 + tP1P2
           = (1 - t) * ( (1 - t)P0 + tP1) + t * ((1 - t)P1 + tP2)
           = (1 - t)(1 - t)P0 + (1 - t) * tP1 + (1 - t) * tP1 + t²P2
           = (1 - t)²P0 + 2t(1 - t) * P1 + t²P2
      //这就是图中展示的最终公式了     
      //当 t = 0 时,结果为起始点P0P1
      //当 t = 1 时,结果为终点P1P2
       //程序中使用
        Vector3 Bezier(Vector3 p0, Vector3 p1, Vector3 p2, float t)
        {
            Vector3 p0p1 = (1 - t) * p0 + t * p1;
            Vector3 p1p2 = (1 - t) * p1 + t * p2;
            Vector3 result = (1 - t) * p0p1 + t * p1p2;
            return result;
        }
    

    三次方公式


    三次方的曲线其实和二次没有太大区别,不过是多了一个点,就多了一层要计算的插值

       //程序中使用
        Vector3 Bezier(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
        {
            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;
        }
    

    N次方公式

        //程序中使用
        // n阶曲线,递归实现
        public Vector3 Bezier(float t, List<Vector3> p)
        {
            if (p.Count < 2)
                return p[0];
            List<Vector3> newp = new List<Vector3>();
            for (int i = 0; i < p.Count - 1; i++)
            {
                Debug.DrawLine(p[i], p[i + 1]);
                Vector3 p0p1 = (1 - t) * p[i] + t * p[i + 1];
                newp.Add(p0p1);
            }
            return Bezier(t, newp);
        }
        // transform转换为vector3,在调用参数为List<Vector3>的Bezier函数
        public Vector3 Bezier(float t, List<Transform> p)
        {
            if (p.Count < 2)
                return p[0].position;
            List<Vector3> newp = new List<Vector3>();
            for (int i = 0; i < p.Count; i++)
            {
                newp.Add(p[i].position);
            }
            return Bezier(t, newp);
        }
    

    t就一个系数,取值范围是0-1,为0时返回值是曲线的出发点,为1时返回值是曲线的终点,为0.5时返回曲线的中间点

    相关链接

    https://www.cnblogs.com/mmc1206x/p/3709188.html
    https://blog.csdn.net/qq_35539447/article/details/80486247

    相关文章

      网友评论

        本文标题:Unity - 贝塞尔曲线浅析

        本文链接:https://www.haomeiwen.com/subject/uvedgktx.html