Проблема, которую я пытаюсь решить, заключается в том, что я не могу перемещать двумерную точку вдоль кубической кривой безье с постоянной скоростью.Постоянная скорость над кубической кривой Безье
Я следовал этому руководству: 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);
}
В приведенном выше коде Я прохожу через время (u) между 0 и 1, чтобы вернуть время, которое может быть использовано для оценки точки на кривой кубического безье, которая представляет движение оси х с постоянной скоростью.
В результате этого: Cubic Bezier Image
Красная точка представляет собой нормальную точку, возвращаемый только оценку оригинального времени с формулой Безье. Желтая точка представляет собой «постоянную» позицию скорости после прохождения по времени, которая была аппроксимирована. Это кажется довольно точным, пока я не начну менять касательные, чтобы быть довольно преувеличенными. Я также пытался увеличить интервалы, и это ничего не помогает.
В любом случае любая помощь будет замечательной. Я не очень хорошо разбираюсь в формулах (я уверен, откуда эта проблема), так что было бы здорово получить некоторую помощь, используя примеры кода, пожалуйста. :>
Спасибо!
это ... не имеет никакого смысла? Если у вас кривая четверть круга со строго положительным x-путешествием, то использование «горизонтальной длины» столь же бесполезно, как и все остальное, не связанное с длиной дуги. Вы будете путешествовать с совершенно разными скоростями на разных участках кривой. Для «выглядит достаточно правильно» просто сгладьте кривую, с привязками 't' в каждой вершине (по существу, постройте LUT), а затем выполните двоичный поиск следующей точки путешествия, сделанной ... http: // pomax. github.io/bezierinfo/#tracing –
Это на самом деле то, что я сделал. LUT состоит из горизонтальной длины и t. Но, тем не менее, факт, что мои локальные переменные называются длиной дуги, является смутным. Это больше не длина дуги, поскольку она состоит только из длины оси x. Спасибо за отзыв! :) – doomcake
нет, это также факт, что вы утверждаете, что горизонтальная длина прекрасна, что абсолютно неверно. Тривиальная монотонная кривая, подобная http://cubic-bezier.com/#.91,.05,.96,.27, должна уже сказать вам следующее: дальнейшие правые вдоль кривой вы идете, значения с одинаковым интервалом дают вам х интервалов, которые становятся все меньше и меньше, тогда как значения с одним и тем же интервалом дают вам большие и большие интервалы t. Ваше утверждение о том, что использование только горизонтальной длины достаточно хорошо, явно * неверно. –