[Monkey] Kubische Bézier-Interpolation

Übersicht Andere Programmiersprachen Codearchiv & Module

Neue Antwort erstellen

Holzchopf

Meisterpacker

Betreff: Kubische Bézier-Interpolation

BeitragSo, Sep 24, 2017 0:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich bin über diesen Artikel gestolpert und habe mir gedacht, dass doch so eine cubic-bezier-Interpolation noch ganz nützlich sein könnte Wink

BlitzMax: [AUSKLAPPEN]
' Cubic Bézier interpolation for easing curves
' pA ... pD are Bézier curve points
' pX the value for which the corresponding curve Y value shall be found
' pPrecision defines up to which error in Y the result shall be
' Returns: curve Y value at pX
Function CubicBezierEase:Float(pA:Float, pB:Float, pC:Float, pD:Float, pX:Float, pPrecision:Float = 0.0001)
' boundary conditions
If pX <= 0 Then Return 0
If pX >= 1 Then Return 1
' polynomial factors, precalculated for performance
Local pQuadr:Float = 3*pC - 6*pA
Local pCubic:Float = 1 + 3*pA - 3*pC
' A cubic bezier spline is a vector function
' (x, y) = f(t)
' The algorithm finds t for a given x
' iteratively
' and returns the corresponding y value.
' start at t = pX
Local t:Float = pX
' old value of t, step of t, how much t actually changed and next best guess for t
Local oldt:Float, tstep:Float, dt:Float, dttarget:Float
' value of x, old value of x and how much x actually changed in last iteration
Local x:Float, oldx:Float, dx:Float
' first iteration is special (in respect to calculation of tstep)
Local firstrun:Int = True
' iterate
Repeat
' calculate x of cubic bezier spline
x = 3*pA*t + pQuadr * t*t + pCubic * t*t*t
' accurately found t?
If Abs(x - pX) <= pPrecision Then
Exit
' no, move t
Else
' update tstep
' in first iteration
If firstrun Then
firstrun = False
' tstep by how much x differs from target x
tstep = pX - x
' after that
Else
' adapt tstep by how much the value over- or undershoot
dx = x - oldx
dt = t - oldt
dttarget = (pX - oldx) / dx * dt
tstep = -dt + dttarget
EndIf
' update t and clamp
oldt = t
t += tstep
If t > 1 Then t=1
If t < 0 Then t=0
EndIf
oldx = x
Forever
' calculate y of cubic bezier spline and return
Return 3*pB*t + (3*pD - 6*pB) * t*t + (1 + 3*pB - 3*pD) * t*t*t
End Function


pA bis pD sind die Steuerpunkte für die Bézierkurve. pX ist der Punkt, für den der Kurvenwert gesucht werden soll. Der optionale Parameter pPrecision steuert, bis auf welche Präzision der Kurvenwert gefunden werden soll.

Der Rückgabewert ist der Kurvenwert bei pX.

Es gibt einige Seiten, auf denen man an den Steuerpunkten rumspielen kann. z.B: http://cubic-bezier.com

LG
Holzchopf
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Holzchopf

Meisterpacker

BeitragDi, Nov 14, 2017 22:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe die Funktion aktualisiert. So nimmt sie zwei zusätzliche Parameter, pY0 und pY1 welche angeben, wo die Kurve startet resp. aufhört. So kann man auch Pulse und Fade Outs machen.

BlitzMax: [AUSKLAPPEN]
' Cubic Bézier interpolation for easing curves
' (Imagine a curve on the X-Y plane. Returns curve value at pX)
' pY0 and pY1 are curve Y values at X=0 and X=1 respectively
' pA ... pD are Bézier curve points
' pX the value for which the corresponding curve Y value shall be found
' pPrecision defines up to which error in Y the result shall be
' Returns: curve Y value at pX
Function CubicBezierEase:Float(pY0:Float, pY1:Float, pA:Float, pB:Float, pC:Float, pD:Float, pX:Float, pPrecision:Float = 0.0001)
' boundary conditions
If pX <= 0 Then Return pY0
If pX >= 1 Then Return pY1
' polynomial factors, precalculated for performance
Local pLin:Float = 3*pA
Local pQuadr:Float = 3*pC - 6*pA
Local pCubic:Float = 1 + 3*pA - 3*pC
' A cubic bezier spline is a vector function
' (x, y) = f(t)
' The algorithm finds t for a given x
' iteratively
' and returns the corresponding y value.
' start at t = pX
Local t:Float = pX
' old value of t, step of t, how much t actually changed and next best guess for t
Local oldt:Float, tstep:Float, dt:Float, dttarget:Float
' value of x, old value of x and how much x actually changed in last iteration
Local x:Float, oldx:Float, dx:Float
' first iteration is special (in respect to calculation of tstep)
Local firstrun:Int = True
' iterate
Repeat
' calculate x of cubic bezier spline
x = pLin * t + pQuadr * t*t + pCubic * t*t*t
' accurately found t?
If Abs(x - pX) <= pPrecision Then
Exit
' no, move t
Else
' update tstep
' in first iteration
If firstrun Then
firstrun = False
' tstep by how much x differs from target x
tstep = pX - x
' after that
Else
' adapt tstep by how much the value over- or undershoot
dx = x - oldx
dt = t - oldt
dttarget = (pX - oldx) / dx * dt
tstep = -dt + dttarget
EndIf
' update t and clamp
oldt = t
t += tstep
If t > 1 Then t=1
If t < 0 Then t=0
EndIf
oldx = x
Forever
' calculate y of cubic bezier spline and return
Return pY0 + (3*pB - 3*pY0) * t + (3*pY0 - 6*pB + 3*pD) * t*t + (pY1 + 3*pB - 3*pD - pY0) * t*t*t
End


Die Parameter sind vorne angehängt, weil es mir viel logischer erscheint die Reihenfolge "interpoliere von, nach, via, an Punkt X" zu haben.

Neue Antwort erstellen


Übersicht Andere Programmiersprachen Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group