Unity画贝塞尔曲线自定义图片组件

“密集度 mesh数量”可以看成是要生成多少个图片元素

“mesh宽度”可以看成你要生成图片元素的大小

``````public static class Bezier
{
/// <summary>
/// 获取绘制点
/// </summary>
/// <param name="controlPoints">控制点列表</param>
/// <param name="density">密度</param>
/// <returns></returns>
public static Vector3[] GetPointList(List<Vector2> controlPoints, int density)
{
List<Vector3> points = new List<Vector3>();
for(int i = 0; i <= density; i++)
{
points.Add(BezierMath(i / (float)density, controlPoints.Count - 1, controlPoints));
}
return points.ToArray();
}

/// <summary>
/// 贝塞尔曲线的函数
/// </summary>
/// <param name="t">分段参数</param>
/// <param name="lineNum">线段数量</param>
/// <param name="controlPoints">锚点列表</param>
/// <returns></returns>
public static Vector2 BezierMath(float t, int lineNum, List<Vector2> controlPoints)
{
Vector2 result = new Vector2();

for (int i = 0; i <= lineNum; i++)
{
float temp = BaseBezier(t, i, lineNum);
result.x += controlPoints[i].x * temp;
result.y += controlPoints[i].y * temp;
}

return result;
}
/// <summary>
/// 贝塞尔基函数
/// </summary>
/// <param name="t">参数</param>
/// <param name="index">线段序号</param>
/// <param name="lineNum">线段数量</param>
/// <returns></returns>
public static float BaseBezier(float t, int index, int lineNum)
{
float result = Factorial(lineNum) * Mathf.Pow(t, index) * Mathf.Pow(1 - t, lineNum - index) / (Factorial(index) * Factorial(lineNum - index));
return result;
}

/// <summary>
/// Factorial 阶乘
/// </summary>
/// <param name="step"></param>
/// <returns></returns>
public static int Factorial(int step)
{
int result = 1;
for (int j = step; j > 1; j--)
{
result *= j;
}
return result;
}
}``````
``````public class BezierMeshImage : Image
{
/// <summary> 密集度 mesh数量 </summary>
public int density = 50;
/// <summary> mesh 宽度  </summary>
public float width;
/// <summary> 控制点列表 </summary>
public List<Vector2> controlList = new List<Vector2>();

/// <summary> 贝塞尔点数组 </summary>
Vector3[] bezierPoints;

protected override void OnPopulateMesh(VertexHelper vh)
{
bezierPoints = Bezier.GetPointList(controlList, density);
vh.Clear();
for (int index = 0; index < bezierPoints.Length; index++)
{
Vector3 baseVector = bezierPoints[index];
var i = index * 4;
vh.AddVert(baseVector + new Vector3(-width/2, -width/2, 1), color, new Vector2(0f, 0f));
vh.AddVert(baseVector + new Vector3(-width/2, width/2, 1), color, new Vector2(0f, 1f));
vh.AddVert(baseVector + new Vector3(width/2, width/2, 1), color, new Vector2(1f, 1f));
vh.AddVert(baseVector + new Vector3(width/2, -width/2, 1), color, new Vector2(1f, 0f));
vh.AddTriangle(i, i + 1, i + 2);
vh.AddTriangle(i + 2, i + 3, i);
}
}
}``````
``````[CustomEditor(typeof(BezierMeshImage))] // 定义子类的编辑器扩展
public class BezierMeshImageEditor : ImageEditor
{
private BezierMeshImage be;
public List<Vector2> pointList;
public static bool isOpenList;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
be = (BezierMeshImage)base.target;
//be.controlV2 = EditorGUILayout.Vector2Field("控制点坐标", be.controlV2);
be.density = EditorGUILayout.IntField("密集度 mesh数量", be.density);
be.width = EditorGUILayout.FloatField("mesh 宽度 ", be.width);
pointList = be.controlList;
isOpenList = EditorGUILayout.Foldout(isOpenList, "控制点列表");
if(isOpenList)
{
for(int i = 0; i < pointList.Count; i++)
{
pointList[i] = EditorGUILayout.Vector2Field(name, pointList[i]);
}
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("+"))
{
Vector2 point = new Vector2();
point = EditorGUILayout.Vector2Field(name, point);
}
if (GUILayout.Button("-"))
{
if (pointList.Count > 0)
pointList.RemoveAt(pointList.Count - 1);
}
EditorGUILayout.EndHorizontal();
}
be.controlList = pointList;
if (HasPreviewGUI())
{
be.enabled = false;
be.enabled = true;
}
}

}
``````

THE END