Unity拉格朗日曲线插值

作者:追风剑情 发布于:2024-10-12 21:56 分类:Unity3d

一、工程截图

22222222.png

二、插值脚本

using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 拉格朗日曲线插值类
/// 优点:曲线会经过型值点
/// 缺点:仅支持沿某条坐标轴插值,不支持曲线调头。
/// </summary>
public class LagrangeCurve : MonoBehaviour
{
    //输入点(即,曲线要经过的点)
    public List<Transform> transPoint = new List<Transform>();

    //插值坐标轴
    public enum LerpAxis
    {
        X,
        Y,
        Z
    }

    public static Vector3 Lerp(Vector3[] points, float t, LerpAxis axis = LerpAxis.X)
    {
        int count = points.Length;
        float x = 0, y = 0, z = 0;
        float ti = 0, tj = 0;

        switch (axis)
        {
            case LerpAxis.X: x = t; break;
            case LerpAxis.Y: y = t; break;
            case LerpAxis.Z: z = t; break;
        }

        Vector3 result = new Vector3(x, y, z);

        for (int i = 0; i < count; i++)
        {
            x = points[i].x;
            y = points[i].y;
            z = points[i].z;
            //型值点的值与混合函数值相乘
            for (int j = 0; j < count; j++)
            {
                if (i != j)
                {
                    Vector3 ipos = points[i];
                    Vector3 jpos = points[j];
                    switch (axis)
                    {
                        case LerpAxis.X:
                            ti = ipos.x;
                            tj = jpos.x;
                            break;
                        case LerpAxis.Y:
                            ti = ipos.y;
                            tj = jpos.y;
                            break;
                        case LerpAxis.Z:
                            ti = ipos.z;
                            tj = jpos.z;
                            break;
                    }
                    x *= (t - tj) / (ti - tj);
                    y *= (t - tj) / (ti - tj);
                    z *= (t - tj) / (ti - tj);
                }
            }

            //线性组合
            switch (axis)
            {
                case LerpAxis.X:
                    result.y += y;
                    result.z += z;
                    break;
                case LerpAxis.Y:
                    result.x += x;
                    result.z += z;
                    break;
                case LerpAxis.Z:
                    result.x += x;
                    result.y += y;
                    break;
            }
        }

        return result;
    }

    public Vector3 Lerp(float t, LerpAxis axis = LerpAxis.X)
    {
        Vector3[] points = new Vector3[transPoint.Count];
        for (int i = 0; i < points.Length; i++)
            points[i] = transPoint[i].position;
        return Lerp(points, t, axis);
    }
}


using UnityEngine;
/// <summary>
/// 测试类
/// </summary>
public class LagrangeCurveTest : MonoBehaviour
{
    [SerializeField]
    private LagrangeCurve curve;
    [SerializeField]
    private Transform startPoint;
    [SerializeField]
    private Transform endPoint;

    void Update()
    {
        //步长
        float step = 0.01f;
        float curx = startPoint.localPosition.x;
        float endx = endPoint.localPosition.x;

        Vector3 startPos = curve.Lerp(curx);
        curx += step;
        Vector3 endPos = curve.Lerp(curx);

        while (curx < endx)
        {
            //仅在Scene窗口可见
            Debug.DrawLine(startPos, endPos, Color.red);
            
            startPos = endPos;
            curx += step;
            endPos = curve.Lerp(curx);
        }
    }
}


运行测试
111.gif

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号