4
\$\begingroup\$

I would like to find out what Y is if X is a certain number from a cubic bezier curve to make a custom easing function, like it's done on this site: http://cubic-bezier.com/
Does anyone know a formula or a function to find Y if X is something of a cubic-bezier? (Coding in C#/XNA)

\$\endgroup\$
3
  • 2
    \$\begingroup\$ There are several correct values for y in a generic cubic bezier. \$\endgroup\$
    – AturSams
    Commented Mar 13, 2014 at 9:35
  • \$\begingroup\$ The answer is now updated with an implementation. \$\endgroup\$
    – AturSams
    Commented Mar 13, 2014 at 21:39
  • 1
    \$\begingroup\$ Is it necessary that the curve be a Bezier specifically, or will any function that smoothly maps the range [0,1] onto a curve beginning at 0 and ending at 1 with controllable tangents suffice? If the latter is okay, there are options for computing y as a function of x directly, rather than via an intermediate parameter t. Cubic Hermite is one example, although it's not as expressive as a Bezier (can't express vertical tangents, but it can mimic any of the standard easing types listed along the bottom of the example link), it's simpler and faster than searching for the right t. \$\endgroup\$
    – DMGregory
    Commented Mar 14, 2014 at 3:36

1 Answer 1

4
\$\begingroup\$

Lets look at two approaches:

  1. Binary search - assuming the Bezier is set with values where there is one Y for each X, meaning that there is an injective function that receives an X and returns a Y then you can search for the correct t value that will return the x,y pair you are looking for.

  2. Precomputation: Computing 1000 values for t between in the range [0 1] should only take an instant and you can place the results in 200 buckets. Afterwards, you could easily get a tiny set of relevant x,y pairs by simply picking the relevant bucket from the array.

Lets explore this in more depth (this is the formula):

bezier formula

To do a binary search, we'll assume that you create a specialized function h(t) that commputes the x value for a given t and returns it.

We are looking for the y value where x=a for some a so we need to find the correct t such that h(t) (nearly) equals x.

h(t) : return (1 - t)^3 * x0 + 3(1 - t)^2t * x1 + 3(1 - t)t^2 * x2 + t^3 * x3;

//Util
sign(z) : (z >= 0)? 1 : -1;
abs(z) : z * sign(z);

//binary search :
lookup(a) : 
  t = 0.5;
  step = 0.5;
  precision = 0.0001;
  While(abs(h(t) - a) > precision) :
    step /= 2.0;
    t += sign(a - h(t)) * step;

I did not check the code for faults so you"re welcome to look for errors.

Other method:

Calculate the Y and X values for a 1000 values of t (in advance). Put the results into buckets in an array of length N. x is between [0 1] so place all results between M/N and (M + 1)/N in the list in index M in the bucket array. You can later use a (fast) lookup to find the x,y pair you want (by radix/range). Binary search (and Newton Raphson) are you friends when you want to quickly answer complex mathematical questions with the use of a computer. You can still use the binary search to increase precision after the look up by searching between the two closest values.

A quick recap: you store the x,y pairs in linked-lists within an array of buckets by creating lists of x,y pairs where the values of x(s) that are between [m/n (m+1)/n] are all stored in the mth index (i.e. in listarray[m]).

\$\endgroup\$
12
  • \$\begingroup\$ If you need an clarification, feel welcome \$\endgroup\$
    – AturSams
    Commented Mar 13, 2014 at 9:49
  • \$\begingroup\$ A binary search is probably overkill for tweening. A numerically-precalculated 1D lookup table with fixed spacing on the X axis is probably a better approach. (Not sure how a hash is applicable here.) \$\endgroup\$ Commented Mar 13, 2014 at 11:04
  • \$\begingroup\$ Actually, if you're willing to do a binary search, and you can figure out if the curve is a function (possibly numerically or by constraining the inputs), then you don't even need the lookup table. You can do a binary search on B(t).X itself, and save yourself the lookup table (it's probably faster). \$\endgroup\$ Commented Mar 13, 2014 at 11:07
  • \$\begingroup\$ What you described as a 1D lookup table is what I described as a hash in my answer. ;) I mean the hash function is simply one that will provide the set of values between m/n and (m+1)/n when you look for some fraction representing x between 0 and 1. Hope that makes sense. \$\endgroup\$
    – AturSams
    Commented Mar 13, 2014 at 11:09
  • \$\begingroup\$ @AndrewRussell Again, doing a binary search on the function (using t) is also the second part of the answer. \$\endgroup\$
    – AturSams
    Commented Mar 13, 2014 at 11:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .