Dev:Bline Speed

From Synfig Studio :: Documentation
Jump to: navigation, search

Bline's parameter's "speed"

If you have played enough with Blines, "BLine Vertex" and "BLine Tangent" converts you perhaps have noticed that a change in the "Amount" parameter doesn't always step forward/backwards the same amount. For example, adding 0.1 to "Amount" doesn't move a "Bline Vertex" by the same distance all the time.

Near the bline's vertices (or near the curved parts) you'll notice that evenly spaced "Amount" values are either compressed together or expanded away from each other. Trying to make an object follow a bline will lead to the object changing speeds as it goes along it.

The problem lies in how Blines are defined and how a position in the Bline changes as the "Amount" parameter changes. I'll refer to the rate of change as the Bline's "speed".

Why does "speed" changes?

Firstly, a Synfig Bline is composed of several bezier sections. Each segment is a cubic bezier line. This sections are joined back to back, allowing for arbitrarily complex shapes. All the properties that for a single section, also hold true for any number of sections. So I'm gonna focus on Blines with a single section, in other words, Blines with only two vertexes.

A Bline with a single section reduces to a Cubic Bezier defined like this:

Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \mathbf{B}(t)=(1-t)^3\mathbf{P}_0+3t(1-t)^2\mathbf{P}_1+3t^2(1-t)\mathbf{P}_2+t^3\mathbf{P}_3 \mbox{ , } t \in [0,1].}

This equation describes the shape of the curve. As the Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!} parameter increases from zero up to one, the point defined by the equation moves from the Bezier's start (Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \mathbf{P}_0} ) towards its end (Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \mathbf{P}_3} ). The rate of the motion as Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!} increases describes the curve's "speed". Taking the derivative of this equation yields the "speed":

Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \frac{d\mathbf{B}(t)}{dt}= (1-t)^2 [ 3 ( \mathbf{P}_1 - \mathbf{P}_0 ) ] + 2t(1-t) [ 3 ( \mathbf{P}_2 - \mathbf{P}_1 ) ] + t^2 [ 3 ( \mathbf{P}_3 - \mathbf{P}_2 ) ] \mbox{ , }t \in [0,1]. }

You may have noticed that this equation is equivalent to a Quadratic Bezier. This tells us that the "speed" can and does change as the Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!} parameter changes.

Adjusting a Bline's "speed"

Our objective is now to compensate the derivative to achieve a desired "speed". We cannot change the control points to the curve without changing its shape. The only other thing we can change is the parameter Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!} . Therefore, we define a function Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle g(t)\,\!} so that:

Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \frac{d\mathbf{B}(g(t))}{dt}=\boldsymbol{s}(t)\,\,}

Where Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \boldsymbol{s}(t)} is a vector Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle (s_x(t),s_y(t))\,\!} that defines the desired speed as a function of Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!} . The curve needs to move in a whole range of directions as the curve describes its shape. Our objective is only to control its magnitude. This magnitude condition can be expressed as:

Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_x^2(t)+s_y^2(t)=s_{mag}^2(t)}

Where Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_{mag}(t)\,\!} is a function defining the desired "speed" magnitude.

We can expand our first equation a bit:

Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \frac{d\mathbf{B}(g(t))}{dt}=\frac{d\mathbf{B}(g(t))}{d(g(t))}\,\frac{dg(t)}{dt}=\boldsymbol{s}(t)\,\,}

Expanding the equation like this lets us use the original Bline's derivative definition, by replacing Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!} with Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle g(t)\,\!} . Next we replace the x and y components into the magnitude condition equation:

Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \Bigg[\frac{dB_x(g(t))}{d(g(t))}\,\frac{dg(t)}{dt}\Bigg]^2+\Bigg[\frac{dB_y(g(t))}{d(g(t))}\,\frac{dg(t)}{dt}\Bigg]^2=s_{mag}^2(t)}

Rearranging we obtain an ordinary non-linear differential equation:

Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \frac{dg(t)}{dt}=\frac{s_{mag}(t)}{\sqrt{\Big[\frac{dB_x(g(t))}{d(g(t))}\Big]^2+\Big[\frac{dB_y(g(t))}{d(g(t))}\Big]^2}}}

Solving this equation yields a function Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle g(t)\,\!} such that the curve's "speed" is dictated by the function Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_{mag}(t)\,\!} .

Solving the equation

All that is left is to solve the equation. It is quite complex and as I said before, the differential equation that we got is non-linear. This makes it hard to find Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle g(t)\,\!} in a clear formula.

But even such a complex equation is easy to solve numerically. Keeping in mind that what we want is simply the value of Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle g(t)\,\!} so we can plug it into "Amount". A numerical solution of the equation gives us just that, the value of Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle g(t)\,\!} at certain intervals.

The Runge-Kutta method serves this purpose quite well, and it's quite simple also. All we need is to evaluate the derivative of the function that we need to find, and feed the values into the Runge-Kutta method.

Let's try a simple case, constant speed. If Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_{mag}(t)\,\!} is a constant value, then it would need to be equal to the Bline's length, so that as the Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!} goes from 0.0 up to 1.0, the curve moves from the start to the end. Too little speed and the curve won't reach the end when Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!} reaches 1.0. Too much and the curve will go past the end when Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!} reaches 1.0.

Conveniently, this method also allows to find a Bline's length. If we assume Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_{mag}(t)=1\,\!} then the curve will reach its end when Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t=LENGTH\,\!} , where LENGTH is the Bline's length.