每天一个小技巧【8】·贝塞尔曲线

贝塞尔曲线是一种平滑曲线,常见于PS中的钢笔工具,在Unity中一般用来绘制弹道轨迹和轨道镜头  。其原理可以看成是将棱角沿中位线打磨,一直重复。这就要用到公式:

备忘:

 

应用贝塞尔曲线公式实现运动轨迹:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 贝塞尔曲线应用
/// </summary>
public class BezierCurve : MonoBehaviour
{
    public Transform[] transes;
    Vector3[] points;
    public float useTime=2;
    public EasingEquation easeType;
    
    Vector3[] Points
    {
        get
        {
            if(points==null)
            {
                points = new Vector3[transes.Length];
                for(var i = 0; i < transes.Length; i++)
                {
                    points[i] = transes[i].position;
                }
            }
            return points;
        }
        set
        {
            points = value;
        }
    }
    public void SetPoints(Vector3[] _points)
    {
        points = _points;
    }
    [ContextMenu("Play")]
    public void Play()
    {
        StartCoroutine(IE_Play());
    }
    IEnumerator IE_Play()
    {
        var _end = false;
        var _v = 0f;
        var _timer = 0f;
        var _useTime = useTime;
        var _orgV1 = 0f;
        var _endV1 = 1f;
        var _curV1 = _orgV1;
        while (!_end)
        {
            _timer += Time.deltaTime;
            _v = Mathf.Clamp01(_timer / _useTime);
            if (_v >= 1)
            {
                _end = true;
            }
            _curV1 = Mathf.LerpUnclamped(_orgV1, _endV1,  EasingManager.GetEaseProgress(easeType,_v));
            transform.position = bezier_interpolation_func(_curV1, Points);
            yield return null;
        }
    }  
    private static float calc_combination_number(int n, int k)
    {
        float[] result = new float[n + 1];
        for (int i = 1; i <= n; i++)
        {
            result[i] = 1;
            for (int j = i - 1; j >= 1; j--)
                result[j] += result[j - 1];
            result[0] = 1;
        }
        return result[k];
    }
    //根据指定路径返回贝塞尔轨迹
    public static Vector3 bezier_interpolation_func(float t, Vector3[] points)
    {
        var count = points.Length;
        Vector3 PointF = new Vector3();
        //float[] part = new float[count];
        float sum_x = 0, sum_y = 0,sum_z=0;
        for (int i = 0; i < count; i++)
        {
            float tmp;
            int n_order = count-1 ;    // 阶数
            tmp = calc_combination_number(n_order, i);
            sum_x += (float)(tmp * points[i].x * Mathf.Pow((1 - t), n_order - i) *  Mathf.Pow(t, i));
            sum_y += (float)(tmp * points[i].y * Mathf.Pow((1 - t), n_order - i) *  Mathf.Pow(t, i));
            sum_z += (float)(tmp * points[i].z * Mathf.Pow((1 - t), n_order - i) *  Mathf.Pow(t, i));
        }
        PointF.x = sum_x;
        PointF.y = sum_y;
        PointF.z = sum_z;
        return PointF;
    }
}

应用贝塞尔曲线公式绘制Mesh:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GLA_Tool
{
    public class DrawCurveMesh_Horizontal : MonoBehaviour
    {
        #region AssetClass
        ModuleAssetClass module;
        public ModuleAssetClass Module
        {
            get
            {
                if (module == null)
                    module = GetComponentInParent<ModuleAssetClass>();
                return module;
            }
            set
            {
                module = value;
            }
        }
        private void OnEnable()
        {
            Module.E_Play += Play;
            //Module.E_Stop += Stop;
            Module.Text.text = "创建贝塞尔曲线";
        }
        private void OnDisable()
        {
            Module.E_Play -= Play;
            //Module.E_Stop -= Stop;
        }
        void Play()
        {            
            CreateOne();
        }        
        #endregion
        #region Parameters
        Transform[] pointsTrans;
        Vector3[] pointsVec3;       
        public int count =10;
        public float width = 2;
        MeshFilter mf;
        #endregion
        #region Properties
        public Transform[] PointsTrans
        {
            get
            {
                    return transform.GetChildren().ToArray(); ;
            }
            set
            {
                pointsTrans = value;
            }
        }
        public Vector3[] PointsVec3
        {
            get
            {
                    pointsVec3 = new Vector3[PointsTrans.Length];
                for (var i = 0; i < pointsVec3.Length; i++)
                {
                    pointsVec3[i] = PointsTrans[i].localPosition;
                }
                return pointsVec3;
            }
            set
            {
                pointsVec3 = value;
            }
        }
        public MeshFilter Mf
        {
            get
            {
                if (mf == null)
                    mf = GetComponentInChildren<MeshFilter>();
                return mf;
            }
            set
            {
                mf = value;
            }
        }
        #endregion
        #region Private Methods  
        [ContextMenu("CreateOne")]
        void CreateOne()
        {
            var verticeList = new List<Vector3>();
            var indexList = new List<int>();
            var uvList = new List<Vector2>();
            for(var i = 0; i < count; i++)
            {
               var _vec0= BezierCurve.bezier_interpolation_func((float)i / (count -  1), PointsVec3);
                var _vec1 = _vec0 + Vector3.forward * width;
                verticeList.Add(_vec0);
                verticeList.Add(_vec1);
                uvList.Add(new Vector2(0, (float)i/(count-1)));
                uvList.Add(new Vector2(1, (float)i /( count-1)));
            }
            for(var i = 0; i < count-1; i++)
            {               
                    indexList.Add(i*2);
                    indexList.Add(i*2+1);
                    indexList.Add(i*2+2);             
                    indexList.Add(2*i+1);
                    indexList.Add(2*i+1+2);
                    indexList.Add(2*i+1+1);
            }
            var mesh = new Mesh();
            mesh.vertices = verticeList.ToArray();
            mesh.triangles = indexList.ToArray();
            mesh.uv = uvList.ToArray();
            Mf.mesh = mesh;
        }
        #endregion        
    }
}

返回目录:https://blog.csdn.net/yzy1987523/article/details/107739933

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值