Interpolation mit kubischen Bezier-Kurven

7

Ich versuche, eine Interpolationsfunktion für eine Animationsbibliothek zu erstellen, um einen Tweening-Effekt zwischen Frames zu erzielen.

Ich möchte, dass dies mit Bezier-Kurven funktioniert. Ich habe eine jsFiddle ( hier ) meiner bisherigen Fortschritte erstellt.

Ich versuche, mit dieser Bezier-Definition ein lineares Tween zu erstellen:

{
    p0: new Vector(0,0), //Start point
    p1: new Vector(0,0), //Control point 1
    p2: new Vector(1,1), //Control point 2
    p3: new Vector(1,1)  //End point
}

Ich habe die Interpolationsfunktion aus diesem Tutorial implementiert .

var u = 1 - t;
var tt = t*t;
var uu = u*u;
var uuu = uu * u;
var ttt = tt * t;

var p = p0.multiply(uuu);
p = p.add(p1.multiply(3 * uu * t));
p = p.add(p2.multiply(3 * u * tt));
p = p.add(p3.multiply(ttt));

Das Problem, das ich habe, ist, dass die Animation beim Ausführen der Funktion nicht linear erscheint, sondern eher wie "Easy-In-Out".

Idealerweise möchte ich, dass die lineare Animation genauso funktioniert wie dieser CSS-Übergang .

Kann jemand sehen, warum es nicht linear animiert?

Jackson
quelle
1
Sie sollten sich die kubische (Einsiedler-) Interpolation ansehen. Es ist verwandt und ist die bessere Wahl imo! blog.demofox.org/2015/08/08/cubic-hermite-interpolation
Alan Wolfe

Antworten:

6

Nach dem Spielen mit dieser Funktion mehr. Mir ist klar, dass die Bezier-Kontrollpunkte ähnlich wie Magnete wirken.

Wenn ich die Kontrollpunkte so verteile, dass sie entlang einer geraden Linie mit gleichem Abstand zwischen ihnen positioniert sind, funktioniert die Animation wie erwartet

{
    p0: new Vector(0,0), //Start point
    p1: new Vector(.333,.333), //Control point 1
    p2: new Vector(.666,.666), //Control point 2
    p3: new Vector(1,1)  //End point
}
Jackson
quelle
Ich verstehe was du meinst. Wenn ich jedoch den ersten Kontrollpunkt auf den Endpunkt und den zweiten Kontrollpunkt auf den Startpunkt setze, erhalte ich einen "inversen" Easy-In-Out-Effekt - siehe hier .
Jackson
Entschuldigung für den mathematischen Fehler in meinem früheren Kommentar. Der Vektor vom Startpunkt zum ersten Kontrollpunkt ist ein Drittel der Anfangsgeschwindigkeit des interpolierten Punktes, wobei die Zeiteinheit die Interpolationsdauer ist. In ähnlicher Weise beträgt der Vektor vom letzten Kontrollpunkt bis zum Endpunkt ein Drittel der Endgeschwindigkeit. Wenn Sie also die Kontrollpunkte gleichmäßig auf 1/3 und 2/3 entlang der Linie verteilen, erhalten Sie eine konstante Lineargeschwindigkeit für die Interpolation, wie Sie es wünschen. Dies scheint auch für andere Ordnungen von Bézier zu gelten: Multiplizieren Sie den Anfangs- oder Endvektor mit der Ordnung, um die Geschwindigkeit zu erhalten.
DMGregory
Ich habe diese Antwort nicht bemerkt, als ich meine gemacht habe. Sie haben völlig Recht, dass kolineare Kontrollpunkte eine lineare Interpolation durchführen. Gute Arbeit bei der Suche nach der Lösung!
Alan Wolfe
5

Normalerweise löse ich das mit Catmull-Rom-Splines. Anstatt Kontrollpunkte zu verwenden, geben Sie einfach die beiden Punkte an, zwischen denen Sie interpolieren möchten, sowie einen "vorherigen" Punkt und einen "nächsten" Punkt. Wenn die 4 Punkte alle auf derselben Linie liegen und gleichmäßig verteilt sind, ist die Interpolation linear.

Katzenmull-Rom-Spline

Im obigen Bild gibt es vier Punkte p0, p1, p2 und p3. Die folgende Zeile des C ++ - Codes interpoliert zwischen p1 und p2, wobei t im Bereich [0 ... 1] liegt:

return p1 + 0.5*t*(p2-p0 + t*(2*p0-5*p1+4*p2-p3 + t*(3*(p1-p2)+p3-p0)));

Sie können jede Art von Werttyp interpolieren, solange der Typ die Addition und Multiplikation mit einem Skalar unterstützt.

Wenn die Werte nicht auf einer Linie liegen oder nicht gleichmäßig verteilt sind, erzeugt die Catmull-Rom-Interpolation eine glatte Kurve. Die Interpolation ist nicht linear:

Catmull-Rom-Kurve

Wenn es keinen "vorherigen" oder "nächsten" Punkt gibt (z. B. am Anfang oder Ende einer Reihe von Kurvensegmenten), verwenden Sie die folgenden Gleichungen:

p0 = 2 * p1 - p2;
p3 = 2 * p2 - p1;
Paul Houx
quelle
Danke für die Antwort. Dies sieht nach einer guten Interpolationsfunktion aus, die ich untersuchen werde.
Jackson
Wenn es in Ihrem letzten Codebit keinen vorherigen oder nächsten Punkt gibt, würde dies zu Unity führen, wie es ist? Multipliziert dies einfach jede Vektorkomponente mit 2 und subtrahiert dann den anderen Vektor? Ich versuche nur zu visualisieren, was dies tatsächlich tut. Vielen Dank.
Doug.McFarlane
@ Doug.McFarlane - Die beiden Formeln "reflektieren" einfach Punkte. Stellen Sie sich beispielsweise im Fall von p0 einen Vektor von p1 nach p2 vor und multiplizieren Sie ihn dann mit -1. Das Ergebnis ist p0 = p1 + (p1 - p2) = 2 * p1 - p2. Auf diese Weise behalten wir die richtige Richtung und den richtigen Abstand bei, was zu einer kohärenteren Interpolation führt. Sie könnten auch p0 auf p1 setzen, aber dann sehen Sie deutlich einen Easy-In-Effekt auf die Interpolation.
Paul Houx
2

Bezier-Kurven dienen von Natur aus dazu, glatte Kurven zu erstellen. Die lineare Interpolation ist einfacher. Um zwei Punkte linear zu interpolieren, können Sie einfach die folgende Formel für die Zeit t in [0,1] anwenden:

interpolatedPoint = startPoint * (1 - t) + endPoint * t

Wenn t = 0 ist, ist der interpolierte Punkt genau gleich dem Startpunkt. In ähnlicher Weise ist der interpolierte Punkt genau gleich dem Endpunkt, wenn t = 1 ist. Wenn t zwischen 0 und 1 liegt, liegt es irgendwo auf der Linie zwischen den beiden Punkten.

Ich habe Ihre jsfiddle gegabelt und modifiziert, um Folgendes zu verdeutlichen: http://jsfiddle.net/kevinAlbs/3em6br3b/1/

kevinAlbs
quelle
Danke für deine Antwort. Ich würde es vorziehen, wenn die Animation flexibel wäre, damit sie mit einer kubischen Bezierkurve sowohl linear als auch gekrümmt sein kann.
Jackson
2

Warum verwenden Sie Bezierkurven für eine lineare Interpolation? Sie können einfach eine lineare Interpolation verwenden, um eine lineare Interpolation durchzuführen, und überhaupt keine Kurven verwenden.

Wenn der Grund dafür ist, dass Sie ein allgemeineres kurvenbasiertes Interpolationssystem wünschen und versuchen, es dazu zu bringen, eine lineare Interpolation für einen bestimmten Anwendungsfall durchzuführen, gibt es einen Weg.

Grundsätzlich müssen die Kontrollpunkte Punkte auf einer Linie sein. Zum Beispiel würden die Kontrollpunkte 0, 0,333, 0,666, 1,0 eine lineare Interpolation zwischen 0 und 1 ergeben, wenn Sie dazu eine kubische Bezierkurve verwenden.

Wenn Sie jedoch eine lineare Interpolation wünschen, gibt es keinen Grund, eine Kurve zu verwenden.

Alan Wolfe
quelle