2009-11-20 13 views
2

J'essaie de définir un chemin de points. Chaque point a un x, un y et un temps. Je veux ensuite interroger ce chemin et obtenir la position actuelle à ce moment-là. Laisse moi partager un pseudo code. Je suis en train d'implémenter ceci dans javascript en utilisant le tag de toile. Cependant, un échantillon dans n'importe quelle langue fera l'affaire. Est-ce que quelqu'un connaît une bibliothèque open source (dans n'importe quelle langue) qui crée ce genre de chemin queriable ??Chemin d'animation temporisé de Bezier

Note: J'ai essayé de comprendre cet exemple et ce code à partir du DynApi project mais le passage de cet exemple à un chemin sensible au temps est un étirement pour mes faibles compétences en animation.

Merci

Guido

Répondre

6

A Bézier curve a non seulement un point de début et de fin, mais aussi points de contrôle qui guident la forme de la courbe. Dans la démonstration DynApi que vous avez liée, les points de fin sont marqués en jaune et les points de contrôle sont marqués en rouge.

Votre chemin sera une suite de courbes de Bézier, connectées bout à bout.

Prenons donc votre pseudo-code, mais nous traiterons tous les points qui ont une propriété .time comme points de contrôle et non.

function Path(points) { 
    this.points = points; 

    // Sanity check. 
    if (points[0].time == undefined || points[points.length - 1].time == undefined) 
     throw new Error("all control points must be between two real points"); 
} 

Path.prototype.getXYAtTime = function (t) { 
    var points = this.points; 

    // First, see if t is out of range. 
    if (t < points[0].time) 
     return points[0]; 
    if (t > points[points.length - 1].time) 
     return points[points.length - 1]; 

    // OK, t is in range. Find out which Bezier curve we're in. 
    // 
    // Specifically we want 'start' and 'stop' to be the indexes of two points 
    // that each have a .time property, bracketing the current time t; and 
    // all the points in between 'start' and 'stop' should be control points. 
    // 
    var start = 0, stop = points.length - 1; 
    for (var i = 1; i < points.length; i++) { 
     var p = points[i]; 
     if (t < p.time) { 
      stop = i; 
      break; 
     } 
     if (p.time != undefined) 
      start = i; 
    } 
    var n = stop - start; 

    // Adjust t to be in the range [0, 1). 
    var t0 = points[start].time, t1 = points[stop].time; 
    t = (t - t0)/(t1 - t0); 
    var tInv = 1 - t; 

    // Now calculate the current position in the curve. 
    // Wikipedia says this is: 
    // sum for i = 0 to n of (n C i * (1 - t)^(n - i) * t^i * P[i]) 
    // 
    var x = 0, y = 0; 
    for (var i = 0; i <= n; i++) { 
     var p = points[start + i]; 
     var c = nCr(n, i) * Math.pow(1 - t, n - i) * Math.pow(t, i); 
     x += c * p.x; 
     y += c * p.y; 
    } 
    return {x: x, y: y}; 
} 

// The number of k-combinations of a set of size n. 
function nCr(n, k) { 
    var z = 1; 
    for (var i = 1; i <= k; i++) 
     z *= (n + 1 - i)/i; 
    return z; 
} 

Alors c'est la partie mathématique qui est faite. C'est à vous de l'accrocher à la toile et de la faire disparaître.

Voilà comment vous appelez cette méthode:

// Here's a Path consisting of a single Bezier curve. 
var path = new Path([ 
    {x: 200, y: 150, time: 0}, // start point 
    {x: 200, y: 500},   // 2 control points 
    {x: 250, y: 100}, 
    {x: 500, y: 300, time: 50} // end point 
    ]); 

var p = path.getXYAtTime(2.718); 
alert(p.x + ", " + p.y); 
+0

Wow, merci pour la réponse très descriptive. Je me sens maintenant stupide d'ajouter que le chemin (collection de points) que je possède ne contient aucun point de contrôle. Je devrais vraiment avoir mentionné que je veux juste adoucir ce chemin. Donc, au lieu d'un jagged rejoindre l'animation des points, je veux produire une animation lisse qui traverse ces points. J'ai joué avec le concept de «deviner» ces points de contrôle étant donné le point précédent et le point suivant (d'un segment de chemin à 2 points), mais cela ne m'amène pas trop loin. Tnx à nouveau pour une réponse grandement décrite. – gatapia

+0

Oh! Je me sens bête maintenant de ne pas comprendre ce que tu voulais. Cela semble être une approche raisonnable, mais il pourrait être difficile de deviner ces points de contrôle. Vous devez comprendre quelles sont les contraintes. Par exemple, un point donné et les points de contrôle juste avant et juste après doivent s'aligner. Sinon, vous aurez un changement soudain de direction au point. –

+0

Quelque chose que j'ai fait une fois dans cette situation est de (a) choisir la vélocité que je veux à chaque point, en fonction des points environnants; (b) en donnant deux points, et la vitesse désirée à chaque point, calculer la fonction cubique unique qui correspond à la facture. Dans votre cas, vous avez une contrainte supplémentaire, cependant: une durée fixe. –

0

Les points de contrôle d'une courbe de Bézier sont en fait exactement ce que vous obtenez en ajoutant le vecteur de vitesse désirée à chaque point final au point final. Par exemple, si vous voulez la vitesse vx0, vy0 au point x0, y0 et ensuite au point x1, y1 arrivant là avec la vitesse vx1, vy1, alors utilisez les quatre points suivants pour définir votre courbe de bezier: (x0,y0); (x0+vx0,y0+vy0); (x1-vx1,y1-vy1); (x1,y1). (les deux du milieu sont vos points de contrôle.)