我试图解决的问题是我似乎无法以恒定速度沿着三次贝塞尔曲线移动二维点。
我最初按照这个教程实施了此曲线:http://catlikecoding.com/unity/tutorials/curves-and-splines/,并且它效果非常好。但是,当尝试以恒定速度近似点时,它偏差非常大。
从我到目前为止所读的内容来看,您应该遍历曲线,在每个时间步长计算弧长和间隔距离。然后,将这些距离与目标距离(弧长*时间)进行比较,以找到最接近的距离。具有足够高分辨率时,这应该具有很小的误差,并足以满足我的需求。
以下是我目前拥有的代码:
点计算:
在上述代码中,我传入了介于0和1之间的时间(u),以返回一个可用于评估表示x轴运动的立方贝塞尔曲线上的点的时间。
结果如下图所示:Cubic Bezier Image 红点表示仅通过使用贝塞尔公式评估原始时间返回的正常点。黄点表示传递近似的时间后的“恒定”速度位置。它看起来相当准确,直到我开始更改切线为相当夸张的情况。我还尝试增加时间间隔,但这并没有帮助什么。
总之,任何帮助都将是美妙的。我还不是非常擅长阅读公式(我确定问题来自何处),因此请使用代码示例帮助一下。 :>
谢谢!
我最初按照这个教程实施了此曲线:http://catlikecoding.com/unity/tutorials/curves-and-splines/,并且它效果非常好。但是,当尝试以恒定速度近似点时,它偏差非常大。
从我到目前为止所读的内容来看,您应该遍历曲线,在每个时间步长计算弧长和间隔距离。然后,将这些距离与目标距离(弧长*时间)进行比较,以找到最接近的距离。具有足够高分辨率时,这应该具有很小的误差,并足以满足我的需求。
以下是我目前拥有的代码:
点计算:
public static Vector3 GetPoint (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
t = Mathf.Clamp01(t);
float oneMinusT = 1f - t;
return
oneMinusT * oneMinusT * oneMinusT * p0 +
3f * oneMinusT * oneMinusT * t * p1 +
3f * oneMinusT * t * t * p2 +
t * t * t * p3;
}
试图在恒定时间内计算点的失败尝试:
private float GetApproximatedTime(float u)
{
int resolution = 100;
float ratio = 1.0f / resolution;
float arcLength = 0.0f;
Vector3 p0 = SelectedSpline.Evaluate(0.0f);
List<MultiCurveUtility.ArcTimeLength> arcTimeLengthMap = new List<MultiCurveUtility.ArcTimeLength>();
arcTimeLengthMap.Add(new MultiCurveUtility.ArcTimeLength(0.0f, 0.0f));
for (int i = 1; i <= resolution; i++)
{
float t = ((float)i) * ratio;
Vector3 p1 = SelectedSpline.Evaluate(t);
arcLength += Vector3.Distance(p0, p1);
arcTimeLengthMap.Add(new MultiCurveUtility.ArcTimeLength(t, arcLength));
p0 = p1;
}
float target = u * arcLength;
int low = 0;
int high = 1;
float min = 0.0f;
float max = 0.0f;
for (int i = 1; i < arcTimeLengthMap.Count; i++)
{
max = arcTimeLengthMap[i].ArcLength;
if (target > min && target < max)
{
high = i;
low = i - 1;
break;
}
min = max;
}
float p = (target - min) / (max - min);
float lowTime = arcTimeLengthMap[low].ArcTime;
float highTime = arcTimeLengthMap[high].ArcTime;
float lowHighDelta = highTime - lowTime;
return arcTimeLengthMap[low].ArcTime + (lowHighDelta * p);
}
在上述代码中,我传入了介于0和1之间的时间(u),以返回一个可用于评估表示x轴运动的立方贝塞尔曲线上的点的时间。
结果如下图所示:Cubic Bezier Image 红点表示仅通过使用贝塞尔公式评估原始时间返回的正常点。黄点表示传递近似的时间后的“恒定”速度位置。它看起来相当准确,直到我开始更改切线为相当夸张的情况。我还尝试增加时间间隔,但这并没有帮助什么。
总之,任何帮助都将是美妙的。我还不是非常擅长阅读公式(我确定问题来自何处),因此请使用代码示例帮助一下。 :>
谢谢!