



Bézier curves are, to me, one of the best examples of mathematical beauty. It's fascinating what such a simple function on some points can achieve. Here's a step-by-step visualization of how a cubic Bézier curve can be constructed. Note each point's position along its own line





If you look closely, you may see we're using Linear interpolation, or, lerp! Lerping the original points, and then between the resulting points, gives rise to curves. Looking at the second set of points - we can see that even they themselves form two *quadratic* Bézier curves





How does it work in code? To get a point in the curve, you simply provide a value between 0 and 1, known as the t-value, to this set of lerps:



a = lerp( p0, p1, t );

b = lerp( p1, p2, t );

c = lerp( p2, p3, t );

d = lerp( a, b, t );

e = lerp( a, b, t );

point = lerp( d, e, t );

While the code above is easy to understand, there are computationally more efficient ways of evaluating this. If you work out the math behind all lerps, and simplify, you end up with four equations that act as weights on each point, which, when visualized, looks like this





Mathematically, we're using Bernstein polynomials here!



point =

p0*(-t³+3t²-3t+1)+

p1*(3t³-6t²+3t)+

p2*(-3t³+3t²)+

p3*(t³)



Or, in code:



omt = 1 - t;

omt2 = omt * omt;

t2 = t * t;



point =

p0 * ( omt2 * omt ) +

p1 * ( 3 * omt2 * t ) +

p2 * ( 3 * omt * t2 ) +

p3 * ( t2 * t );

Give it a try!

❱ http://acegikmo.com/bezier/





Addendum!

A quirk when using Bézier curves is that the t-value is actually not the same thing as percentage of distance along the curve. The difference in t-value between each segment here is constant, and the animation is linearly animating t, yet the speed is not constant





This is often a problem for animation. One solution to this, is to build a lookup table that can help you convert percentage along the spline to t, that way you can animate uniformly, like this!





If you want more information on how to do this lookup table, you can check out some slides from a talk of mine! Slides 75-82:

https://docs.google.com/presentation/d/10XjxscVrm5LprOmG-VB2DltVyQ_QygD26N6XC2iap2A …

Also, many of you have correctly pointed out that in the fourth tweet, it should be:

e = lerp( b, c, t );



Let's pretend I did that typo just to make sure you were paying attention 😶



(Also Twitter let us edit tweets already geez)

Some have asked how to know we should use Bernstein polynomials. The truth is, I only found out they were called that *after* I derived those equations. I arrived at them naturally by doing the math:



v = lerp( a, b, t )



is mathematically



v = (1-t)a + bt

Now let's look at our Bézier evaluation again, this time with lerps expressed as math:



a = (1-t)p₀ + tp₁

b = (1-t)p₁ + tp₂

c = (1-t)p₂ + tp₃

d = (1-t)a + tb

e = (1-t)b + tc

point = (1-t)d + te

Before we can simplify, let's collapse it all into a single equation. First, substitute in a, b and c into d and e:



d = (1-t)((1-t)p₀+tp₁)+t((1-t)p₁+tp₂)

e = (1-t)((1-t)p₁+tp₂)+t((1-t)p₂+tp₃)

point = (1-t)d + te

Then d and e into the point equation, to create this monster:



point = (1-t)((1-t)((1-t)p₀+tp₁)+t((1-t)p₁+tp₂)) + t((1-t)((1-t)p₁+tp₂)+t((1-t)p₂+tp₃))



This is the last we'll see of the lerp-like equations!

We now expand to untangle all the points and t values. What you end up with, is this:



point =

-p₀t³ + 3p₀t² - 3p₀t + p₀ +

3p₁t³ - 6p₁t² + 3p₁t -

3p₂t³ + 3p₂t² +

p₃t³



If you look at each line here, you can see that each belong to a specific point

With that in mind, we can finally simplify it by separating out each point as a lone factor:



pt =

p₀(-t³+3t²-3t+1) +

p₁(3t³-6t²+3t) +

p₂(-3t³+3t²) +

p₃t³



And thus, we now have our basis functions, which happen to be Bernstein polynomials, for our cubic Bézier curve :)

If you have more questions - I just went live! I stream development of a game of mine, where I just so happen to be using Béziers for its level editor! Feel free to tune in, hang out, and chat about curves⁓

❱ http://twitch.tv/acegikmo





This thread is now also available as a single post over at Medium, with some minor corrections and non-compressed .gifs 💞



https://medium.com/@Acegikmo/the-ever-so-lovely-b%C3%A9zier-curve-eb27514da3bf …

You can follow @FreyaHolmer.

____

Tip: mention @threader_app on a Twitter thread with the keyword “compile” to get a link to it.



Enjoy Threader? Sign up.



Since you’re here...



... we’re asking visitors like you to make a contribution to support this independent project. In these uncertain times, access to information is vital. Threader gets 1,000,000+ visits a month and our iOS Twitter client was featured as an App of the Day by Apple. Your financial support will help two developers to keep working on this app. Everyone’s contribution, big or small, is so valuable. Support Threader by becoming premium or by donating on PayPal. Thank you.



Download Threader on iOS.