我正在尝试实现此circle spline scheme(付费专区)以便在Unity游戏中生成流畅的轨迹。想法是制作一条平滑的曲线,并在可能的情况下使用圆弧段进行无限延伸。我得到的代码确实在点之间插值,但是只要在每个点之间画一条直线即可,而与平滑度无关。
这是我作为单个函数的实现。对于[0,1]范围内的数字,它应该返回一个函数,该函数返回一系列点,描绘出current
和next
之间的平滑曲线。外部生成函数还需要知道current
之前的点previous
,以及next
之后的点future
,以便使曲线保持在current
和next
。除了点名称外,我还尝试遵守本文中的命名约定。
Func<float, Vector3> splineFunction (Vector3 current, Vector3 next, Vector3 previous, Vector3 future) {
Vector3 a, b, c, d, e;
a = (current - previous).normalized;
b = (next - current).normalized;
c = (next - previous).normalized;
d = (future - next).normalized;
e = (future - current).normalized;
float tau_current = Mathf.Acos(Vector3.Dot(a, c));
float tau_next = Mathf.Acos(Vector3.Dot(e, d));
Func<float, float> tau = u => {
float expression1 = Mathf.Cos(u * Mathf.PI / 2);
float expression2 = Mathf.Sin(u * Mathf.PI / 2);
return tau_current * expression1 * expression1 + tau_next * expression2 * expression2;
};
Vector3 axis_current = Vector3.Cross(b, a);
Vector3 t_current = Quaternion.AngleAxis(tau_current, axis_current) * b;
Vector3 axis_next = Vector3.Cross(b, d);
Vector3 tM_next = Quaternion.AngleAxis(-tau_next, axis_next) * b; // t_{i+1} mirrored about the perpendicular bisector of (current, next)
Vector3 swivel_axis = Vector3.Cross(t_current, tM_next);
Func<float, Vector3> t = u => {
return Quaternion.AngleAxis(tau(u), swivel_axis) * b; // unsure about the b term here
};
return u => {
Vector3 axis = Vector3.Cross(t(u), b);
float distance = Vector3.Distance(current, next) * Mathf.Sin(u * tau(u)) / Mathf.Sin(tau(u));
float angle = (1 - u) * tau(u);
return current + (Quaternion.AngleAxis(angle, axis) * b * distance);
};
}
根据this MathExchange question,我认为问题的部分原因在于我对“旋转”切线函数t
的解释;更笼统地说,我觉得我错过了失败的几何图形。据我所知,除了t
之外,这是作者编写程序时逐个单词的重写。为什么要跟踪一系列直线而不是平滑曲线?