每天一个小技巧【8】·贝塞尔曲线
程序员文章站
2022-07-12 22:43:15
...
贝塞尔曲线是一种平滑曲线,常见于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
上一篇: Cocos - 贝塞尔曲线 Bezier
下一篇: Flutter 贝塞尔曲线实现案例