Before I knew about bézier curves and splines my idea of a curve was very basic It was either the classic y=x²-1 or a circular arc But curves that could move in all directions that could do loops and all sorts of things, were still a mystery to me But once you start unraveling the construction of these curves the idea of chaining them together to form splines, come naturally They let you define a path in a way that is computationally very elegant Properties like the tangent and normal directions of the curve let you orient objects or construct a coordinate space around each point which is very useful for generating procedural geometry You can analyze these curves based on their radius of curvature find what direction they're turning and at what rate You can analytically evaluate their bounding box which is useful in a lot of optimization problems, such as when doing intersection tests We're going to take a look at how to calculate some of these things and how they collectively make up what I consider to be The Beauty of Bézier Curves Bézier curves, and more generally, splines, are ubiquitous in games You'd be hard-pressed to find any animations such as this camera moving along a path that are *not* based on splines These types of paths are everywhere, not just for animations but also 3D models generated along a path such as this rollercoaster track that you can manipulate by bending twisting and extending it I also use them in my own game Flowstorm to create the smooth curved track you slide on The level editor explicitly allows you to create connected curves in a spline and lets you control bezier curve handles which, might look familiar to those of you who have used the pen tool in Photoshop So how do you create bezier curves? Let's say you have two points: P0 and P1 connected by a line segment Now imagine a third point P between these two points The position of P could be described by what is called a t-value a value between 0 to 1, similar to a percentage where t-values at 1 moves it to P1 and t-values at 0 moves it to P0 and any values in between are a blend between the two This function is called linear interpolation or lerp for short Mathematically, you can write it as (1-t)P0*tP1 Now, what if we add another point? We now have two interpolated points one on each line segment "lerping" on their respective line based on the same t-value we saw earlier We can then connect these two points with another line segment If we then add a point on that line that also lerps based on the same t-value you can see that it follows a very specific path This path is a quadratic bézier curve but we don't have to stop here what if we add another point?
we repeat the same process add three points connect them add two points connect those and add the last point and this point will now follow the path of the cubic bézier curve what's beautiful about this construction is that it works no matter what points we use We can change the shape to anything and following the same rules it will give us this smooth path We're going to focus mostly on the cubic bézier curve for the rest of this video since it's the most common one This particular method of getting a point in a bézier curve based on nested lerps where each point along the way is calculated from lerps from the points that came before it eventually forming the path of the bézier curve is called De Casteljau's Algorithm I personally love it because of its numerical stability and just how easy it is to remember it's just lerps all the way down But there is another way we can interpret this Let's start by writing out the math for all of our lerps then, let's expand this formula entirely let's also color code the points for readability What you might be able to see is that we can rearrange this formula in terms of each point First, each point can be visualized as a vector from the origin But this is where it gets interesting Each of them are multiplied by four polynomials based on our t-value This is what they look like for all cubic bézier curves You might be able to tell that the values are sort of trading off with each other as weights as we change t in the beginning, the first weight is 1 but as the t-value increases the values shift across the points until the last weight has a value of 1 This is called a weighted sum where each of these weights together add up to 1 at any given t value Let's apply these weights to the vectors of the points As you can see, they trade off weights exactly the same way so let's add them together What we get is exactly the same behavior as with the lerps but using a different interpretation of the same math This follows the very same bézier curve we got with the lerps This is called the Bernstein Polynomial Form of bézier curves Now that we've factored out the points in the formula we've isolated these polynomials Since the points are considered constants we can easily calculate the derivative of these functions but what does it actually represent? The derivative is the rate of change or velocity vector at the given t-value in the curve and for clarity let's just absolutely demolish the middle line it's getting in the way, and quite often it's not displayed whenever you see splines anyway Something I think is really fascinating with the derivative is that the derivative of the cubic bézier curve is, in and of itself a quadratic bézier curve This relationship holds for all bézier curves The derivative of a bézier curve is always another bézier curve of one degree lower You can see how the derivative changes as we change the shape of the curve So why is it useful? The derivative is tangent to the curve which means that if we normalize it we can not only get the tangent direction but also the normal direction of the curve by simply rotating it 90° As soon as we have the tangent and normal directions we can start getting local coordinates that are offset from the curve This is the key to getting offset points that we can use to generate things such as roads in 3d But what happens if we derive it again?
The first derivative can be considered the velocity of the points so if we extend this idea to the second derivative that would be the acceleration of the point in other words the rate of change of velocity As I mentioned before, the velocity can be visualized as a quadratic bézier curve Similarly, the acceleration can be visualized as a linear bézier curve which is simply a line segment or we could just call it a lerp But we can go one step further The third derivative is called jerk or jolt and represents the rate of change of acceleration For the cubic bézier curve, jolt is simply a point In other words it's a two-dimensional constant If we animate t from zero to one you can perhaps see how they are all pulling on each other as they move through the curve So why am I talking about all of these derivatives? Well, using the velocity and acceleration. .
. (not this jerk let's remove it) . .
. we can calculate a fascinating property called curvature Curvature can be expressed with a surprisingly simple formula not just for bézier curves but for any parametric curves like this We take the determinant between the velocity and the acceleration divided by the speed cubed This gives us curvature usually denoted with a κ (kappa) symbol Curvature roughly represents how bent the curve is at any given point If the curvature is 0, the curve is flat The further away the curvature is from 0, the more tightly bent it is Now, the unit this is expressed in is perhaps a little confusing I like interpreting it as radians per meter, but you can also interpret curvature as reciprocal radius That is, the reciprocal of the radius of a circle with the same curvature This means we can calculate the radius of what's called the osculating circle As you can see, the osculating circle's curvature matches that of the curve Let's look at a more interesting example Here, the curvature starts out being negative marked blue in cyan before switching over to being positive marked red and yellow The point where the curvature changes sign as in, passes through zero, is called an inflection point at that point, the osculating circle is undefined since we can't divide by zero and there is no radius that would give us a straight line That's how you calculate the curvature of a cubic bézier curve A perhaps unexpected use of the derivative is to calculate the bounding box of the curve Bounding boxes are used extensively in game development to optimize culling and intersection testing with, say, an infinite line, we can first check if the line intersects its bounding box before doing the more expensive curve intersection test So how do we get this box? The naïve solution is to simply use the control points of the bézier curve This can be good enough, but what we really want is the tight bounding box In some cases, the difference between the two is huge If you look at the bounding box you can see that it's touching three points on the curve these are the points we want to find The first step to give us some insight is to split the curve into its two component functions, for x and y separately What we find is that the local minima and maxima coincide with the points we marked on the curve If we then change the shape of the curve so that the left point is no longer part of the bounds the local minima also disappears from the left x position graph and so these local extrema they exist where the derivatives change sign So if we instead look at the derivatives their roots are the t-values where we have the points we're interested in Note that not all points are part of the bounding box they are simply potential points that we should include in our bounds because they are local extrema So if we look at the formula for the derivative it's currently expressed in terms of our points but we can rearrange it to be in terms of t after that, we can easily plug these terms into the familiar quadratic formula in order for us to find the roots of our derivatives this gives us four potential t-values: two from X and two from Y Note that some of these values should be discarded either because they're outside the 0-1 range we're interested in or the value inside the square root is negative (those t-values aren't real, ignore them) We can also look at the derivative in 2D With this interpretation, the roots are the t-values at which the quadratic derivative curve crosses the X and Y axes And again, you can see how the derivative changes as we change the shape of the curve And that's how you analytically get the bounding box of a cubic bézier curve So far throughout this video, we've been working with t-values a simple value from 0 to 1 representing where the point is along the curve but how far has it actually moved?
And for that matter how long is this curve? What is the arc length of this curve? Unfortunately, this is where bézier curves are less beautiful because there is no closed form solution to the length of a cubic bézier curve This integral is an elliptic integral, in other words sadness and despair so we have to approximate it one way of doing that, is to subdivide the curve into line segments and then sum the length of each individual line segment The more segments we add the more accurate our measurement will be Though of course, it will also be more expensive to calculate the more samples we have Mathematically, I think you can express it like this I'm not sure why I added this formula here because this is less descriptive but for fans of math notation there you go So now that we have the arc length of the curve, instead of using a t-value, what if we instead want to get the point at a specific distance along the curve?
Well we have the full arc length we can simply divide our distance value by the arc length and we'll get our t-value, which we can then evaluate as usual So we can simply place dots on our curves and animate them by distance right? Well, unfortunately, this is where things get even more ugly If we change our control points, our dots are not equally spaced anymore Clearly, our distance values don't correctly translate into t-values and the dots move at different speeds at different points in the curve The reason for that is that, equally spaced t values are not equally spaced by distance in bézier curves they just so happen to be very equal in this particular curve But why? One way to analyze this is, again, using the derivative The derivative can be interpreted as the velocity of the points If our points moved at different speeds along the curve, it means the magnitude of the derivative is not constant In this particular case, you can see the derivative lies within a circle which means the speed is almost constant across the entire curve but use any other curve, and you can see that it's no longer circular at all Now the speed changes across the curve and our dots no longer have equal spacing Pushing it to the extreme, the differences in point spacing will become very apparent So how do we solve this?
Since there is no closed form solution for the arc length we'll have to again approximate it One way of doing this is to subdivide the curve and generate what's called a lookup table in this table, we can save the arc length or distance along the curve to each t value we sample in the table as usual, the more samples we have the more accurate it will be but in turn it would also be more expensive to compute What this allows us to do, is to input our distance value and from there we can relatively easily find what t-value it would have had based on the neighboring distance samples What we're doing here, is effectively an approximation of finding the root of what would have been a pretty complicated polynomial After we get the t-value from this lookup table we can evaluate the curve as usual For reference, this is what my code looks like to do this very thing It's basically a list of distance values and it returns the normalized position within that list, as in, a value from 0 to 1 So what we had before were equally spaced t-values But what we actually want is equally spaced distance values Now if we bring back our dots as we change from equally spaced t values to equally spaced distances they reach a much more uniform spacing and our animation has a nice uniform speed across the curve Approximating it like this is a little messy, but it's unfortunately what we're left with as cubic béziers just don't have a closed form solution but it's usually good enough in practice what we just did was an approximate solution to what is called Arc Length Parameterization as you can see, bézier curves are sometimes a little messy but with the simplicity of their construction and the flexibility of their uses I think they're beautiful, despite their flaws~ I don't have to know the exact arc length you know we can approximate that, it's okay I can still animate a camera along a path and make it fly through some fancy scenery, just like in my favorite games I even used 3D bézier curves in RGB color space when I wanted to blend the point colors of the curve back in the polynomial section Of course, bézier curves are not the only ones out there There's a whole cinematic universe of splines But for now, that's it from me Thanks for watching 💗 okay that was probably the the longest video project I've ever worked on and I guess it's kind of the first time I jump into this type of thing I just want to say thank you so much for supporting me on Patreon for all of you scrolling by, it's absolutely insane that I can like see 3Blue1Brown be like, hey wouldn't it be neat if people made math videos? And then I can just dedicate like a month to doing that and that's exactly what I did and it's just amazing that I'm able to do that, because of all of you! So thank you all so much for supporting me it means the world to me so thank you all so much I would also like to thank Jazz Mickle for making the music in this video Jazz makes like really cool music in general and you should check out her stuff I'm gonna link it in the description along with everyone else!
Big thanks to 3Blue1Brown or Grant Sanderson for pushing me to actually do this I've been wanting to make videos like math videos for a long time but it's mostly been like gifs on twitter but never like a full full video like this It's been an interesting experience and it's been fun! I might do more videos like this, if all of you like this style of video and if you want to see more of it, I can probably do that! I just need to find ideas that I want to make videos on topics that might be interesting Obviously, we can go super deep into splines, talk about B-splines we didn't actually talk much about splines we mostly talked about bézier curves but yeah so there's a lot that we could go into, so if you're interested in seeing that kind of stuff let me know because I genuinely have no idea what my audience wants my youtube is like improvisational game dev stuff and our D&D campaign and some old game projects and like it's very difficult to know what kind of audience I have so input is super appreciated!
Just let me know in the comments So for those of you curious, the way that I made this video- I streamed a lot of it on twitch, so if you you're curious, the VODs, they're going to be up for another, I don't know 30 days? It's created in Unity, I did most of the animations and, actually all of the animations that are not like footage from other things, are created in Unity I made this sort of like custom timeline tool that helped me like arrange procedural animation one after the other and then most of it is just code driven animation I use my own math library called Mathfs, which is just useful for bézier curves and other like range remapping things that I might use I also have my own frame recorder that exports a . png sequence and then I edited the rest of the video in DaVinci Resolve so basically I just exported out a long series of screenshots and then I just edit the video from there All of the vector graphics is done using my own plugin for unity called Shapes it's a vector graphics plugin, and it was sort of made specifically for these types of things except it's also like made for you know real-time applications and games and not just you know, offline rendering but yeah that's how the video was made Thank you so much for watching I hope you like this and I hope it was interesting or otherwise educational Thank you all so much bye~ 💖 [freya] [hey] [mom] [pls] Boy [;-;] Hey [bed pls] I'm gonna go to bed don't worry [now!
!