Unity曲线编辑器和bezier曲线插值-----该篇是对上篇的曲线间平滑过渡问题的展开。
上面的曲线间平滑多度强烈依赖于2条二阶曲线粘合处的平滑。
1.5点线性平滑处理,大致思想是通过历史点信息 通过线性预测方法得出插值的点,该方法如果不加以校正的话,会蝴蝶效应,例如依据的点是越来越偏离真实点。图中 A B就是根据历史p0 p1 p2 一定方法(一般可以是曲率做为参考依据)计算出来
2.利用三阶bezier曲线的,一个三点一线特性,大致是第一条曲线的第二个控制点和第一条曲线的终点和第二条曲线的第一个控制点,三点在一条线上的话,连接处就是平滑的,但是在实践的时候发现1个问题,虽然连接处平滑了,但是曲线 的曲率变化可能会偏差很大,导致过渡后曲率偏离过大, 也会导致抖动问题,看起来像是拐角突然变大or小。也依赖于拖动曲线的时候的让曲线间曲率变化不大。
如图p2 p3 p4 在同一条线上。这个特性在editor时候可以做自动微调计算,让他们在同一个线段上
3.一片论文提到的方法 http://www.ixueshu.com/document/720e4fbfdf8eec55318947a18e7f9386.html
4.之所以不平滑是因为他们交合处角度,位置的偏差导致,平滑计算可以针对角度和位置分别进行插值处理
5.RungeKutta 算法 可用在mspline 等曲线计算中,解决步长带来的精度的问题
6.欧拉渐进法euler,也可以实现和5一样的效果,是一阶的 RungeKutta 算法
(https://www.zhihu.com/question/34780726 赵恒的回答)
------------------------------------------------------------------------
M-Spline方法 的一个实现, 这种方法和bezier方法区别是,这种方法生成的曲线是过控制点的,并且每个点会影响全局生成的曲线信息,因此各自的适用情况不一样。而且比例是0-1全局的,因此一个完整的曲线不适用于过大的曲线描述,受限于float精度。。
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using System.Collections;
public class MSplineScript : MonoBehaviour
{
public static MSplineScript ins = null;
protected Vector3[] dtbl;
protected Vector3[] ftbl;
public bool isMaked;
private float length_;
protected int lengthDiv = 8;
public Vector3[] posTbl;
protected float[] sectionLength;
protected Method useMethod = Method.ImprovedEuler;
void Awake()
{
ins = this;
}
ArrayList mpoints = new ArrayList();
void Start()
{
ins = this;
var ps = this.GetComponentsInChildren<Transform>();
var vs = new Vector3[ps.Length];
int i = 0;
foreach (var p in ps)
{
vs[i] = p.position;
++i;
}
this.Make(vs);
mpoints.Clear();
var pp = this.GetComponentsInChildren<MPont>();
foreach (var p in pp)
{
for (float iter = 0f; iter < 1f; iter += 0.001f)
{
if (Vector3.Distance(this.GetPoint(iter), p.transform.position) < 1f)
// 注意这个1f的距离取决于 曲线的精度,如果曲线很长,那么这个1可能不够
{
p.rate = iter;
break;
}
}
mpoints.Add(p);
}
}
public BezierDirection GetDirection(float rate)
{
for (int i = mpoints.Count - 2; i >= 0; i--)
{
var p = mpoints[i] as MPont;
if (rate >= p.rate)
{
return p.direction;
}
}
return BezierDirection.None;
}
protected f