Решение этой задачи можно аппроксимировать для большинства параметрических траекторий. Идея заключается в следующем: если вы достаточно сильно приблизитесь к кривой, вы не сможете отличить саму кривую от ее касательной в этой точке.
Делая это предположение, нет необходимости предварительно вычислять что-либо больше, чем два вектора (три для кубических кривых Безье и т . Д. ).
Таким образом, для кривой M(t) мы вычисляем ее касательный вектор dMdt в точкеt. Норма этого вектора∥dMdT∥иследовательнорасстояниепройденноетечение длительностиΔtможет быть аппроксимировано как∥dMdT∥Δt. Отсюда следует, что расстояниеLпреодолевается за времяL÷∥dMdT∥.
Применение: квадратичная кривая Безье
Если контрольными точками кривой Безье являются A , B и С , траектория может быть выражена как:
M( т )= ( 1 - т )2A + 2 т ( 1 - т ) B + т2С= т2(A−2B+C)+t(−2A+2B)+A
Таким образом, производная:
dMdT= t ( 2 A - 4 B + 2C)+(−2A+2B)
Вам просто нужно хранить векторы v⃗ 1=2A−4B+2C и v⃗ 2=−2A+2B где-нибудь. Затем для заданного t , если вы хотите продвинуться на длину L , вы делаете:
t=t+Llength(t⋅v⃗ 1+v⃗ 2)
Кубические кривые Безье
То же самое относится и к кривой с четырьмя контрольными точками A , B , C и D :
M(t)=(1−t)3A+3t(1−t)2B+3t2(1−t)C+t3D=t3(−A+3B−3C+D)+t2(3A−6B+3C)+t(−3A+3B)+A
Производная это:
dMdt=t2(−3A+9B−9C+3D)+t(6A−12B+6C)+(−3A+3B)
Мы предварительно вычислим три вектора:
v⃗ 1v⃗ 2v⃗ 3=−3A+9B−9C+3D=6A−12B+6C=−3A+3B
и окончательная формула:
t=t+Llength(t2⋅v⃗ 1+t⋅v⃗ 2+v⃗ 3)
Accuracy issues
If you are running at a reasonable framerate, L (which should be computed according to the frame duration) will be sufficiently small for the approximation to work.
However, you may experience inaccuracies in extreme cases. If L is too large, you can do the computation piecewise, for instance using 10 parts:
for (int i = 0; i < 10; i++)
t = t + (L / 10) / length(t * v1 + v2);