在Unity中使用贝塞尔曲线_02
前言
上一篇贝塞尔曲线的研究只能满足一段曲线的生成,今天将实现任意曲线生成(多节点连续曲线)。
设计原理
指定一段曲线的两个端点(p0,p3)以及两个控制点(p1,p2)然后使用三阶贝塞尔公式即可生成一段连续的曲线,将这一段曲线理解成第
n个节点到n+1个节点之间的三阶贝塞尔。
接下来就是创建N个节点了,每一个节点和其对应的下一个节点为一组曲线,最后一个节点不计算。
如何处理多节点之间的平滑过渡
每一个节点都有且仅有一个控制点,控制点左边的曲线相当于三阶贝塞尔中的p2点,而右侧则先计算其镜像的坐标作为公式中的p1,这样便可以做到一个控制点同时调节左右曲线的曲率,效果如下。
两条曲线中间节点的控制点 设计原理
BezierNodeObject :节点对象,包含一个控制点属性
public class BezierNodeObject : MonoBehaviour
{
public Transform BezierOffset;
private BezierNode bezierNode;
public BezierNode GetBezierNode()
{
bezierNode.nodeOffset = BezierOffset.position;
bezierNode.nodePos = transform.position;
return bezierNode;
}private void Update()
{
Debug.DrawLine(BezierOffset.position, transform.position - (BezierOffset.position - transform.position), Color.yellow);
}
}
【在Unity中使用贝塞尔曲线_02】BezierData : 将所有节点和控制点数据保存,并提供三阶贝塞尔函数接口
[CreateAssetMenu(fileName = "BezierData", menuName = "Config/BezierData")]
public class BezierData : ScriptableObject
{
[Header("数据集名称")]
public string DataName;
[Header("数据节点集")]
public List bezierNodes;
[Header("精度系数,越大越平滑,性能消耗越高"), Range(10, 100)]
public int accuracy = 10;
///
/// 计算并返回指定一段曲线的坐标位置数组
///
/// 区间下标数值
///
public Vector3[] GetBezierDatas(int region) {
if (region < bezierNodes.Count) {
Vector3[] datas = new Vector3[accuracy];
for (int i = 0;
i < accuracy;
i++)
{
BezierMath.Bezier_3ref(
ref datas[i],
bezierNodes[region].nodePos,
bezierNodes[region].getReverseNodeOffset(),
bezierNodes[region + 1].nodeOffset,
bezierNodes[region + 1].nodePos,
i/(accuracy-1.0f)
);
}
return datas;
}
return null;
}
public void SetBezierNode(List bezierNodeObjects) {
if (bezierNodes == null) bezierNodes = new List();
bezierNodes.Clear();
foreach (var item in bezierNodeObjects)
{
bezierNodes.Add(item.GetBezierNode());
}
}
}
BezierLine : 按照一定的精度从BezierData中获取每一段曲线上的坐标,将坐标信息传递给Unity的LineRenderer并绘制出line
public class BezierDrawLine : MonoBehaviour
{
private List bezierNodeObjects;
private BezierData bezierData;
private List vector3s;
public Transform NodesRoot;
[Header("精度系数,表示每一段有多少个节点"),Range(10 , 100)]
public int accuracy;
private void Start()
{
bezierNodeObjects = new List();
bezierData = https://www.it610.com/article/new BezierData();
vector3s = new List();
}private void Update()
{
if (!NodesRoot) return;
bezierNodeObjects.Clear();
bezierNodeObjects.AddRange(NodesRoot.GetComponentsInChildren());
bezierData.SetBezierNode(bezierNodeObjects);
bezierData.accuracy = accuracy;
drawline();
}void drawline() {
for (int i = 0;
i < bezierNodeObjects.Count - 1;
i++)
{
var lineRenderer = bezierNodeObjects[i].GetComponent();
if (lineRenderer == null) lineRenderer = bezierNodeObjects[i].gameObject.AddComponent();
lineRenderer.positionCount = accuracy;
lineRenderer.SetPositions(bezierData.GetBezierDatas(i));
}
}
}
以上代码仅供参考,如果需要,下方将提供git项目地址。
实际效果展示 多节点贝塞尔曲线
文章图片
可调细分程度 [项目地址:BezierTool]
推荐阅读
- 热闹中的孤独
- 你到家了吗
- Shell-Bash变量与运算符
- JS中的各种宽高度定义及其应用
- 闲杂“细雨”
- 杜月笙的口才
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 深入理解Go之generate
- 赢在人生六项精进二阶Day3复盘
- 祖母走了