Il est possible d'approcher une solution à ce problème pour la plupart des trajectoires paramétriques. L'idée est la suivante: si vous zoomez assez profondément sur une courbe, vous ne pouvez pas distinguer la courbe elle-même de sa tangente à ce point.
En faisant cette hypothèse, il n'est pas nécessaire de précalculer plus de deux vecteurs (trois pour les courbes de Bézier cubiques, etc. ).
Donc pour une courbe M(t) on calcule son vecteur tangent dMdtt∥ dMréT∥Δ t∥ dMréT∥ Δ tLL ÷ ∥ dMréT∥
Application: courbe de Bézier quadratique
Si les points de contrôle de la courbe de Bézier sont , et , la trajectoire peut être exprimée comme:UNEBC
M( t )= ( 1 - t )2A + 2 t ( 1 - t ) B + t2C= t2( A - 2 B + C) + t ( - 2 A + 2 B ) + A
La dérivée est donc:
réMrét= t ( 2 A - 4 B + 2 C) + ( - 2 A + 2 B )
Il vous suffit de stocker les vecteurs et quelque part. Alors, pour un donné , si vous voulez avancer d'une longueur , vous faites:v⃗ 1= 2 A - 4 B + 2 Cv⃗ 2= - 2 A + 2 BtL
t = t + Ll e n gt h ( t ⋅ v⃗ 1+ v⃗ 2)
Courbes cubiques de Bézier
Le même raisonnement s'applique à une courbe avec quatre points de contrôle , , et :UNEBCré
M( t )= ( 1 - t )3A + 3 t ( 1 - t )2B + 3 t2( 1 - t ) C+ t3ré= t3( - A + 3 B - 3 C+ D ) + t2( 3 A - 6 B + 3 C) + t ( - 3 A + 3 B ) + A
Le dérivé est:
réMrét= t2( - 3 A + 9 B - 9 C+ 3 D ) + t ( 6 A - 12 B + 6 C) + ( - 3 A + 3 B )
Nous précalculons les trois vecteurs:
v⃗ 1v⃗ 2v⃗ 3= - 3 A + 9 B - 9 C+ 3 D=6A−12B+6C=−3A+3B
et la formule finale est:
t=t+Llength(t2⋅v⃗ 1+t⋅v⃗ 2+v⃗ 3)
Problèmes de précision
Si vous utilisez une fréquence d'images raisonnable, (qui doit être calculé en fonction de la durée de la trame) sera suffisamment petit pour que l'approximation fonctionne.L
Cependant, vous pouvez rencontrer des inexactitudes dans des cas extrêmes. Si est trop grand, vous pouvez faire le calcul par morceaux, par exemple en utilisant 10 parties:L
for (int i = 0; i < 10; i++)
t = t + (L / 10) / length(t * v1 + v2);
L
est suffisamment petit, cette approximation est en fait toujours plus précise que la réponse ci-dessous, oui. Il utilise également moins de mémoire (car il utilise le dérivé au lieu de stocker toutes les valeurs de points). LorsqueL
commence à grandir, vous pouvez utiliser la technique que je suggère à la fin.Vous devez re-paramétrer la courbe. La manière la plus simple de le faire est de calculer les longueurs d'arc de plusieurs segments de la courbe et de les utiliser pour déterminer d'où vous devez échantillonner. Par exemple, peut-être à t = 0,5 (à mi-chemin), vous devez passer s = 0,7 à la courbe pour obtenir la position "à mi-chemin". Pour ce faire, vous devez stocker une liste des longueurs d'arc de divers segments de courbe.
Il existe probablement de meilleures façons, mais voici un code C # très simple que j'ai écrit pour le faire dans mon jeu. Il devrait être facile de porter sur l'objectif C:
Edit: Il convient de noter que cela ne vous donnera pas la longueur d'arc exacte, car il est impossible d'obtenir la longueur d'arc d'une courbe cubique. Il ne s'agit que d'estimer la longueur des différents segments. Selon la longueur de la courbe, vous devrez peut-être augmenter la résolution pour l'empêcher de changer de vitesse lorsqu'elle atteint un nouveau segment. J'utilise généralement ~ 100, avec lesquels je n'ai jamais eu de problème.
la source
Une solution très légère consiste à approximer la vitesse plutôt qu'à approximer la courbe. En fait, cette approche est indépendante de la fonction de courbe et vous permet d'utiliser n'importe quelle courbe exacte au lieu d'utiliser des dérivés ou des approximations.
Voici le code pour C # Unity 3D:
Bien que la solution soit indépendante de la fonction de la courbe, je voulais la noter ici car je cherchais également comment atteindre une vitesse constante sur une courbe de Bézier, puis j'ai trouvé cette solution. Compte tenu de la popularité de la fonction, cela peut être utile ici.
la source
Je ne sais rien de cocos2, mais une courbe de Bézier est une sorte d'équation paramétrique, vous devriez donc être en mesure d'obtenir vos valeurs x et y en termes de temps.
la source