Holmér Solves Bézier Velocity Skew With Arc-Length Lookup Tables

The Beauty of Bézier Curves — Freya Holmér

Freya Holmér

Because cubic Bézier curves lack a closed-form arc-length integral, developers must remap parameter values through numerical lookup tables to prevent objects from bunching and stretching during animation.

AI-assisted summary of The Beauty of Bézier Curves — original source. Check the original for full context.

Source published:

Key ideas

  • Bézier curves can be evaluated either geometrically using De Casteljau's algorithm through nested linear interpolations, or algebraically as a weighted sum of control points using Bernstein polynomials. (3:57)
  • Every derivative of an n-degree Bézier curve yields another Bézier curve of degree n-1, enabling analytical calculation of velocity, tangents, normals, acceleration, and curvature. (6:18)
  • Tight axis-aligned bounding boxes can be computed analytically by finding the roots of the first derivative component polynomials via the quadratic formula, avoiding naive overestimations. (11:05)
  • Cubic Bézier curves lack a closed-form symbolic solution for arc length due to an underlying elliptic integral, necessitating numerical approximations such as lookup-table arc-length parameterization for constant-speed animation. (14:03)

Detailed notes

## Background Published on YouTube by game developer and educator Freya Holmér on August 19, 2021, The Beauty of Bézier Curves explores the geometric foundations and practical mechanics of Bézier curves. The presentation demystifies how these curves operate behind the scenes in animation, procedural mesh generation, and vector art, utilizing custom procedural tools built in Unity with Holmér's Shapes and Mathfs libraries.

## TL;DR Freya Holmér deconstructs Bézier curves starting from basic linear interpolation (lerp), scaling from quadratic to cubic curves via De Casteljau's algorithm and the Bernstein polynomial formulation. She illustrates how successive derivatives define velocity, acceleration, and curvature, which establish dynamic coordinate frames and osculating circles for geometry extrusion. The breakdown also covers calculating exact, tight bounding boxes by solving derivative quadratic roots, before tackling the lack of a closed-form arc length solution through numerical arc length parameterization lookup tables for uniform motion.

## Atmosphere & style The presentation blends rigorous mathematical analysis with a warm, conversational, and visually mesmerizing aesthetic driven by crisp real-time vector graphics. Holmér guides the audience with infectious curiosity, effortlessly balancing technical calculus with self-deprecating humor about mathematical 'sadness and despair.' The experience feels intimate and intellectually satisfying, culminating in a charming late-night sign-off featuring her persistent cat demanding bedtime.

## Bulletin - [03:57](https://www.youtube.com/watch?v=aVwxzDHniEw&t=237s) Bézier curves can be evaluated either geometrically using De Casteljau's algorithm through nested linear interpolations, or algebraically as a weighted sum of control points using Bernstein polynomials. - [06:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=378s) Every derivative of an n-degree Bézier curve yields another Bézier curve of degree n-1, enabling analytical calculation of velocity, tangents, normals, acceleration, and curvature. - [11:05](https://www.youtube.com/watch?v=aVwxzDHniEw&t=665s) Tight axis-aligned bounding boxes can be computed analytically by finding the roots of the first derivative component polynomials via the quadratic formula, avoiding naive overestimations. - [14:03](https://www.youtube.com/watch?v=aVwxzDHniEw&t=843s) Cubic Bézier curves lack a closed-form symbolic solution for arc length due to an underlying elliptic integral, necessitating numerical approximations such as lookup-table arc-length parameterization for constant-speed animation.

## Key takeaways - [01:06](https://www.youtube.com/watch?v=aVwxzDHniEw&t=66s) Bézier curves provide an elegant, computationally efficient mechanism to define paths for camera fly-throughs, physics-based tracks, and dynamic procedural mesh extrusions. - [01:56](https://www.youtube.com/watch?v=aVwxzDHniEw&t=116s) Linear interpolation (lerp) forms the foundational building block for constructing quadratic and cubic Bézier curves through nested stages of parameterization. - [03:57](https://www.youtube.com/watch?v=aVwxzDHniEw&t=237s) De Casteljau's algorithm evaluates points on a curve through iterative lerps, offering high numerical stability and geometric simplicity. - [04:25](https://www.youtube.com/watch?v=aVwxzDHniEw&t=265s) The algebraic Bernstein polynomial form represents the curve as an affine combination of control points whose blending weights partition unity at every point along t. - [06:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=378s) Differentiating an n-degree Bézier curve always produces another Bézier curve of degree n-1, turning differentiation into a systematic reduction in polynomial degree. - [07:31](https://www.youtube.com/watch?v=aVwxzDHniEw&t=451s) The first derivative represents the instantaneous velocity along the curve, which normalizes to the unit tangent vector and rotates 90 degrees to form the curve normal. - [08:01](https://www.youtube.com/watch?v=aVwxzDHniEw&t=481s) Higher derivatives yield acceleration (linear Bézier) and jerk (a constant 2D vector for cubic curves), which combine to define the signed curvature of the path. - [09:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=547s) Curvature reflects the inverse radius of the local osculating circle, dropping to zero at straight paths or inflection points where the circle's radius expands to infinity. - [11:05](https://www.youtube.com/watch?v=aVwxzDHniEw&t=665s) Naive bounding boxes using control points frequently overestimate curve extents, wasting performance in spatial queries and collision checks. - [13:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=798s) Exact bounding boxes are determined analytically by solving for the roots where component derivatives X'(t) and Y'(t) cross zero, and testing valid roots alongside endpoints. - [14:03](https://www.youtube.com/watch?v=aVwxzDHniEw&t=843s) Cubic Bézier arc length requires evaluating an elliptic integral with no closed-form solution, making numerical approximation necessary for calculating physical travel distance. - [15:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=907s) Uniform sampling in parameter space t results in non-uniform physical motion because the magnitude of the velocity vector fluctuates along the curve. - [16:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=967s) Arc length parameterization using precomputed lookup tables and linear interpolation enables constant-speed traversal and equally spaced point distribution. - [19:13](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1153s) Despite mathematical quirks like non-uniform parameterization, Bézier curves remain highly practical and serve as an entry point into broader spline formulations.

## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=aVwxzDHniEw&t=0s) Introduction to Curves and Splines

Before discovering Bézier curves and splines, Freya Holmér’s concept of a mathematical curve was fairly basic—limited mostly to the standard parabola $y = x^2 - 1$ or a simple circular arc. Complex curves capable of turning in arbitrary directions, performing loops, and smoothly navigating multidimensional space seemed mysterious. Once the underlying construction of these curves is unraveled, however, linking them together into continuous splines feels entirely natural. As Freya explains, “They let you define a path in a way that is computationally very elegant.”

Understanding their core geometry unlocks a wide range of analytical tools. Tangent and normal vectors along the curve allow developers to orient objects along a trajectory or construct local coordinate frames at any point, providing the foundational mathematics needed to generate procedural geometry. Further analysis reveals how curves turn, their rate of rotation via the radius of curvature, and analytical methods to calculate their exact bounding boxes for collision detection and culling optimizations.

- **Analytical properties**: Tangents and normals establish moving local coordinate spaces at any point along the path. - **Curvature metrics**: Curvature radius determines the turning rate and direction of the path. - **Performance benefits**: Analytical bounding boxes enable high-performance spatial partitioning, culling, and intersection tests.

---

[01:06](https://www.youtube.com/watch?v=aVwxzDHniEw&t=66s) Ubiquitous Use Cases: Animation and Game Worlds

Splines and Bézier curves are foundational across real-time graphics and game development. Virtually every smooth camera fly-through or automated object movement relies directly on splines. Highlighting their dominance in 3D motion, Freya remarks, “You'd be hard-pressed to find any animations such as this camera moving along a path that are *not* based on splines.” Beyond motion, curves serve as the structural backbone for procedurally extruded 3D meshes, such as rollercoasters whose tracks can be dynamically bent, twisted, and extended by manipulating spline nodes.

Freya also highlights her own physics-based racing game, *Flowstorm*, where the smooth tracks that players slide across are constructed entirely out of connected Bézier segments. The built-in level editor exposes curve handles that mirror the familiar control points found in vector design software like Adobe Photoshop's pen tool, demonstrating how mathematical curve formulations translate directly into tactile artist interfaces.

- **Camera paths**: Smooth parametric interpolation drives cinematic animations and fly-throughs. - **Mesh generation**: Dynamic procedural geometry (such as roads, pipes, and rollercoaster rails) is extruded along spline paths. - **Game mechanics**: *Flowstorm* uses connected Bézier curves to build smooth sliding tracks for gameplay. - **Authoring tools**: Handle-based manipulation in level editors mirrors vector art conventions like Photoshop’s pen tool.

---

[01:56](https://www.youtube.com/watch?v=aVwxzDHniEw&t=116s) Constructing Bézier Curves via Lerp

The construction of a Bézier curve begins with the simplest building block in computer graphics: linear interpolation, or *lerp*. Given two endpoints, $P_0$ and $P_1$, connected by a straight line, any intermediate point $P$ can be parameterized by a scalar value $t$ ranging from $0$ to $1$, analogous to a completion percentage. At $t = 0$, the point sits exactly at $P_0$; at $t = 1$, it reaches $P_1$; and intermediate values represent a linear blend expressed mathematically as $(1 - t)P_0 + tP_1$.

```mermaid flowchart TD accTitle: De Casteljau Evaluation for a Cubic Bézier Curve accDescr: Diagram showing how four control points reduce to a single point on a cubic curve through three stages of linear interpolation.

subgraph Inputs["Control Points"] P0["P0"] P1["P1"] P2["P2"] P3["P3"] end

subgraph Stage1["First Interpolation Stage"] L01["Lerp(P0, P1, t)"] L12["Lerp(P1, P2, t)"] L23["Lerp(P2, P3, t)"] end

subgraph Stage2["Second Interpolation Stage"] Q0["Lerp(L01, L12, t)"] Q1["Lerp(L12, L23, t)"] end

subgraph Output["Curve Point"] C["Point on Cubic Curve: Lerp(Q0, Q1, t)"] end

P0 --> L01 P1 --> L01 P1 --> L12 P2 --> L12 P2 --> L23 P3 --> L23

L01 --> Q0 L12 --> Q0 L12 --> Q1 L23 --> Q1

Q0 --> C Q1 --> C ```

When a third control point is introduced, forming two line segments ($P_0P_1$ and $P_1P_2$), two separate points can be interpolated simultaneously using that same parameter $t$. Connecting those two interpolated points with a new segment and interpolating along *that* line using $t$ causes the resulting point to trace a smooth parabolic arc—a quadratic Bézier curve. Adding a fourth control point extends this hierarchy one step further: three initial lerps connect into two segments, which lerp into one final segment, yielding the cubic Bézier curve. Freya emphasizes the universal nature of this geometric system: “what's beautiful about this construction is that it works no matter what points we use.”

- **Linear interpolation (Lerp)**: $P(t) = (1 - t)P_0 + tP_1$, where $t \in [0, 1]$. - **Quadratic Bézier**: Formed by three control points via two parallel lerps chained into a third lerp. - **Cubic Bézier**: Formed by four control points via three sequential lerp stages (3 points $\to$ 2 points $\to$ 1 point). - **Flexibility**: The construction preserves smoothness regardless of how the control points are moved or transformed.

---

[03:57](https://www.youtube.com/watch?v=aVwxzDHniEw&t=237s) De Casteljau's Algorithm and the Bernstein Polynomial Form

The iterative, nested-lerp evaluation of Bézier points is formally known as De Casteljau’s algorithm. Freya champions this formulation for its clean computational properties: “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.” However, writing out the nested algebra and expanding the formula reveals an alternative interpretation. When fully multiplied out and grouped by control points, the curve can be rewritten as a weighted sum of the control point position vectors.

In this algebraic arrangement, each control point vector from the origin is scaled by a corresponding polynomial function of $t$. For a cubic Bézier curve, these four blending functions are the cubic Bernstein polynomials: - $B_0(t) = (1 - t)^3$ - $B_1(t) = 3(1 - t)^2 t$ - $B_2(t) = 3(1 - t) t^2$ - $B_3(t) = t^3$

At $t = 0$, the first weight is $1$ and all others are $0$. As $t$ advances, weight smoothly transitions across the intermediate points until $t = 1$, where the final control point has a weight of $1$. Because these weights always sum to exactly $1$ at any value of $t$, the formula is an affine combination—a weighted sum—that traces the identical spatial curve produced by the nested geometric lerps.

- **De Casteljau’s algorithm**: Evaluates points via successive geometric linear interpolations, minimizing floating-point precision loss. - **Bernstein polynomial form**: Expresses curve positions as an explicit sum $P(t) = \sum_{i=0}^{n} B_i(t) P_i$. - **Partition of unity**: The polynomial weights sum to $1$ for any $t \in [0, 1]$, ensuring affine invariance and scale-independent behavior.

---

[06:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=378s) Derivatives of Bézier Curves: Velocity, Tangents, and Normals

Because the Bernstein polynomial formulation treats the control points as constant vectors, differentiating the curve with respect to $t$ simply requires taking the standard derivative of each polynomial term. The resulting first derivative represents the instantaneous rate of change—the velocity vector—along the curve at a given $t$. To make the visualizations clear on screen, Freya jokes about decluttering the geometric display: “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.”

A fundamental mathematical elegance emerges from this differentiation: “The derivative of a bézier curve is always another bézier curve of one degree lower.” Thus, the derivative of a cubic Bézier curve is itself a quadratic Bézier curve whose control points are determined by the differences of the original points.

```mermaid flowchart LR accTitle: Bézier Derivative Cascade accDescr: Diagram illustrating how differentiating a cubic Bézier curve reduces its degree by one at each successive derivative step.

Cubic["Cubic Bézier (Position)\nDegree 3"] Quad["Quadratic Bézier (Velocity / 1st Deriv)\nDegree 2"] Linear["Linear Bézier / Lerp (Acceleration / 2nd Deriv)\nDegree 1"] Constant["Constant 2D Vector (Jerk / 3rd Deriv)\nDegree 0"]

Cubic -->|"d/dt"| Quad Quad -->|"d/dt"| Linear Linear -->|"d/dt"| Constant ```

This velocity vector points in the tangent direction of the curve. Normalizing this vector produces a unit tangent vector, and rotating it $90^\circ$ yields the 2D curve normal. Together, tangent and normal vectors form a dynamic, moving coordinate frame along the curve, which is critical for generating procedural meshes such as road surfaces, curbs, and extrusion profiles that must track path orientation.

- **Degree reduction rule**: Every derivative of an $n$-degree Bézier curve produces an $(n-1)$-degree Bézier curve. - **Velocity vector**: $P'(t)$ defines the instantaneous trajectory and speed along the path. - **Unit tangent**: $\hat{T}(t) = \frac{P'(t)}{\|P'(t)\|}$. - **Normal vector**: Obtained by rotating $\hat{T}(t)$ by $90^\circ$, enabling procedural 3D surface extrusions and lane offsets.

---

[08:01](https://www.youtube.com/watch?v=aVwxzDHniEw&t=481s) Higher Derivatives: Acceleration, Jerk, and Curvature

Continuing to differentiate reveals the higher-order physical properties of the curve. If the first derivative corresponds to velocity, the second derivative represents acceleration—the rate of change of the velocity vector. Because differentiation reduces the curve's degree by one, the acceleration of a cubic curve is a linear Bézier curve, which is simply a single lerp between two points. Taking the third derivative yields jerk (or jolt), representing the rate of change of acceleration. For a cubic curve, jerk drops to a degree-zero curve: a single, stationary 2D vector constant. Animating $t$ from $0$ to $1$ shows each vector pulling on the lower-order terms through the curve's traversal.

Dismissing jerk from further calculation—“(not this jerk let's remove it)”—Freya combines velocity and acceleration to define curvature. She emphasizes the generality of this relationship: “Curvature can be expressed with a surprisingly simple formula not just for bézier curves but for any parametric curves like this.” Curvature, denoted by $\kappa$ (kappa), measures how sharply a curve turns at any point:

$$\kappa = \frac{\det(P'(t), P''(t))}{\|P'(t)\|^3} = \frac{x'y'' - y'x''}{(x'^2 + y'^2)^{3/2}}$$

Curvature can be interpreted in units of radians per meter or as the reciprocal of the radius ($r = \frac{1}{\kappa}$) of the curve's *osculating circle* (the circle that best fits the curve locally). When curvature is zero, the path is completely straight and the osculating circle's radius expands to infinity. Where curvature changes sign (passing through zero from positive to negative), the curve hits an *inflection point*. At inflection points, the osculating circle is mathematically undefined due to division by zero, as no finite circle can match a straight line.

- **Second derivative ($P''$)**: Acceleration vector, represented geometrically by a linear Bézier segment. - **Third derivative ($P'''$)**: Jerk or jolt, which is a fixed 2D vector constant for any cubic Bézier. - **Curvature formula**: $\kappa = \frac{\det(v, a)}{\|v\|^3}$, providing a signed measurement of turning sharpness. - **Osculating circle**: Radius $r = \frac{1}{|\kappa|}$; its center lies along the normal line at that point. - **Inflection point**: A location where $\kappa = 0$ as the curve transitions between clockwise and counterclockwise winding.

---

[11:05](https://www.youtube.com/watch?v=aVwxzDHniEw&t=665s) Calculating Tight Bounding Boxes

An essential practical application of Bézier derivatives is calculating an exact, tight axis-aligned bounding box (AABB). Bounding boxes are ubiquitous in game engines for broad-phase collision detection, culling invisible geometry, and accelerating raycasts. Testing an intersection between a line and an exact cubic curve is computationally demanding, so engines first check whether the line intersects the curve's bounding box.

A naive bounding box can be quickly formed by simply taking the minimum and maximum coordinates of the four control points. However, Freya points out why this approximation often falls short: “This can be good enough, but what we really want is the tight bounding box.” The difference between the naive control polygon bounds and the true envelope of the curve can be substantial, resulting in wasted computation during intersection tests.

To find the true extents, the 2D curve $P(t) = (X(t), Y(t))$ is decomposed into independent 1D scalar functions for $X$ and $Y$. The boundary of the tight box must touch the curve at its local extrema, which occur precisely where the coordinate derivatives equal zero ($X'(t) = 0$ and $Y'(t) = 0$). By taking the derivative polynomials and rearranging their coefficients in terms of $t$, each component yields a standard quadratic equation:

$$a t^2 + b t + c = 0$$

Applying the quadratic formula produces up to four candidate roots: two for $X$ and two for $Y$. Any root that yields a negative discriminant is discarded as non-real, prompting the tongue-in-cheek reminder: “(those t-values aren't real, ignore them).” Similarly, real roots that fall outside the valid parameter range $[0, 1]$ are thrown out. Evaluating the curve at the remaining valid roots alongside the mandatory start and end endpoints ($t = 0$ and $t = 1$) yields the exact minimal and maximal coordinates required to assemble the tightest possible bounding box.

- **Bounding box utility**: Skips expensive curve-ray intersection calculations if the ray misses the bounding volume. - **Naive vs. tight bounds**: Control point envelopes are fast to compute but frequently overestimate curve bounds by large margins. - **Extrema isolation**: Splitting $P(t)$ into $X(t)$ and $Y(t)$ identifies local extrema where component derivatives cross zero. - **Root solving**: Differentiating cubic components produces quadratic equations, solved directly with the standard quadratic formula. - **Candidate pruning**: Roots with negative discriminants or values outside $t \in [0, 1]$ are discarded; valid roots and the endpoints $t \in \{0, 1\}$ define the true bounding box.

[13:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=798s) Analytically Finding the Bounding Box

Freya Holmér shows that the analytic bounding box of a cubic Bézier curve is found where the quadratic first derivative curve crosses the $X$ and $Y$ axes. As the shape of the cubic curve is manipulated, the derivative curve shifts correspondingly, directly exposing how the extrema along each axis move. Observing where these coordinate components equal zero provides the exact parameter values $t$ where the curve reaches its maximum and minimum bounds, allowing the tight bounding box to be resolved analytically.

```mermaid flowchart LR accTitle: Analytic Bounding Box Calculation accDescr: Process of deriving bounding box bounds by finding the roots of the first derivative. A["Cubic Bézier Curve"] --> B["Quadratic 1st Derivative"] B --> C{"Crosses X or Y axis?"} C -->|"Solve Roots"| D["Extrema Points"] D --> E["Tight Analytic Bounding Box"] ```

---

[14:03](https://www.youtube.com/watch?v=aVwxzDHniEw&t=843s) Arc Length: Sadness and Despair

Up to this stage in the analysis, curve evaluation relies entirely on parameter values: a scalar $t$ ranging from $0$ to $1$ defining position along the path. However, this parameterization ignores physical motion: how far has a point actually traveled, and what is the total arc length of the curve? Holmér points out that this is where Bézier curves lose their elegance: “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.”

Evaluating the curve length requires computing an elliptic integral, an operation she cheerfully summarizes as “sadness and despair.” Because an exact symbolic integral does not exist, the arc length must be approximated numerically. The most straightforward approach is sampling: subdividing the continuous curve into a series of discrete linear segments and summing their individual lengths. Increasing the sample count improves accuracy, but linearly increases the computational expense of the evaluation.

``` 1 L = ∫ || B'(t) || dt ---> No closed-form solution (elliptic integral) 0

Discrete approximation: L ≈ Σ || B(t_{i+1}) - B(t_i) || ```

---

[15:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=907s) Arc Length Parameterization and Velocity

A common operational requirement is sampling a curve by travel distance rather than an arbitrary $t$-value. Dividing a target distance by total arc length yields an initial scalar estimate. However, naively treating this ratio as a parameter value causes immediate visual failure: placing a series of dots along the curve reveals that they bunch up and stretch apart as control points are moved. Rather than maintaining uniform spacing, the dots drift at wildly different speeds across the curve.

This discrepancy arises because equally spaced values of $t$ do not correspond to equally spaced physical distances along a Bézier curve. The underlying mechanics are revealed by the first derivative, which represents the velocity vector of a point traversing the curve:

“If our points moved at different speeds along the curve, it means the magnitude of the derivative is not constant.”

When a curve's derivative plot traces out a near-circular path, speed remains relatively constant. But in typical configurations, the derivative's magnitude varies substantially, destroying uniform spacing and causing severe velocity distortion during animation.

```mermaid flowchart TD accTitle: Arc Length Parameterization via Lookup Table accDescr: Pipeline showing conversion from target distance to t parameter using a LUT. subgraph Offline["Table Generation"] S["Subdivide Curve"] --> LUT["Lookup Table: Distance vs t"] end subgraph Runtime["Runtime Query"] D["Target Distance"] --> Interp["Interpolate Neighboring Samples"] LUT -.-> Interp Interp --> T["Normalized t-Value"] T --> Eval["B(t) Point Evaluation"] end ```

To solve this non-uniformity without an analytical integral, Holmér demonstrates an approximate technique known as *Arc Length Parameterization*:

- **Lookup Table Generation**: The curve is subdivided into discrete steps to precalculate and store the cumulative arc length associated with each sampled $t$-value. - **Root Finding Approximation**: When queried with an arbitrary target distance, the lookup table finds the adjacent sample boundaries and linearly interpolates the correct $t$-value, effectively approximating the root of a complex polynomial. - **Implementation**: Holmér shares a snippet of her own C# code, which stores an array of distance samples and returns a normalized $[0, 1]$ parameter representing the remapped position. - **Uniform Results**: Switching from uniform $t$-stepping to arc-length-parameterized distance stepping restores equal visual spacing between dots and produces smooth, constant-speed animations along the path.

---

[19:13](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1153s) The Spline Universe and Outro

While Bézier curves feature mathematical quirks and require numerical approximations for physical measurements like arc length, Holmér emphasizes their practical utility: “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~” Approximations remain more than sufficient for high-end production tasks, such as sweeping a cinematic camera smoothly through complex video game environments.

Holmér reveals that she even leveraged 3D Bézier curves embedded directly inside RGB color space earlier in the video to smoothly interpolate the colors of the control points. She concludes the technical portion by observing that Bézier curves are merely an entry point into a vast domain: “There's a whole cinematic universe of splines.”

---

[20:05](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1205s) Production Notes, Tooling, and Late-Night Interruption

Wrapping up the video, Holmér reflects on the project's scale, noting that it was the longest project she had ever produced. She gives heartfelt credit to the people who made the project possible:

- **Grant Sanderson (3Blue1Brown)**: For providing the core push to create long-form educational math videos instead of brief Twitter animated clips: “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”. - **Jazz Mickle**: For composing the original music used throughout the video. - **Patreon Backers**: For funding her work and granting her the creative freedom to spend an entire month building procedural math visualizers.

Holmér explains that her YouTube channel has historically been an eccentric mix of improvisational game development, recorded *Dungeons & Dragons* sessions, and legacy game archives, making audience expectations unpredictable; she invites viewers to comment on whether they want deeper dives into B-splines and broader spline mathematics.

She also outlines the technical pipeline used to build and render the video: - **Unity**: Used as the core animation engine via code-driven procedural scripts and a custom timeline tool. - **Mathfs**: Holmér's custom open-source math library, used for Bézier curve evaluation and numeric range remapping. - **Shapes**: Holmér's proprietary vector graphics plugin for Unity, used to draw all vector curves, axes, and indicators in real time. - **DaVinci Resolve**: Used for final editing after exporting raw animations via a custom PNG sequence screenshot recorder. - **Twitch**: Where much of the development was live-streamed.

At 2:00 AM, as the recording wraps, Holmér is interrupted by her cat Thor demanding attention and begging for bedtime with subtitled meows (`[mom] [pls] [bed pls] [now!!] [im tired]`), prompting her to laugh, promise him she is going to bed, and sign off.

## Notable quotes > [06:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=378s) The derivative of a bézier curve is always another bézier curve of one degree lower. — Freya Holmér

> [19:13](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1153s) 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~ — Freya Holmér

## Mentioned Freya Holmér, Flowstorm, Adobe Photoshop, Pierre Bézier, Paul de Casteljau, Grant Sanderson (3Blue1Brown), Jazz Mickle, Pomax, Thor the cat, Unity, Shapes, Mathfs, DaVinci Resolve, Twitch, Patreon

## Video description Bézier curves - how do they do?

They're used for animation, text rendering, and all sorts of curved shapes! But how do they actually work? well, like, that's what the video is about, so, watch it to find out etc!!

• Lots of love to 💛 Jazz "queenjazz" Mickle for making the music ❱ https://queenjazz.bandcamp.com/ 💙 Grant "3Blue1Brown" Sanderson for pushing me to finally do this ❱ https://youtube.com/3blue1brown 🐦 Pomax for their wonderful writeup on Bézier curves ❱ https://pomax.github.io/bezierinfo 🐈 Thor the cat for.. hanging out.. when I was trying to record audio with no interruptions 🇫🇷 French subtitles by @damqui on Twitter

• How was this video made? 🔨 Created in the Unity game engine ⭕ Using Shapes, my vector graphics plugin ❱ https://u3d.as/1W37 📈 Using Mathfs, my math library ❱ https://github.com/FreyaHolmer/Mathfs ...along with a bunch of hacky, partially broken, procedural animation tools I made specifically for this video

• Did you know that "osculating" isn't pronounced that way? ✅ yes I do now in fact please stop commenting on it ;-; ❱ https://twitter.com/FreyaHolmer/status/1429472399389507591

• Links 💖 Patreon ❱ https://www.patreon.com/acegikmo 🐦 Twitter ❱ https://twitter.com/FreyaHolmer 📺 Twitch ❱ https://www.twitch.tv/acegikmo 💬 Discord ❱ https://discord.gg/v5VWuga 🌸 Instagram ❱ https://instagram.com/freya_holmer

00:00 Intro 01:06 Use Cases of Bézier Curves 01:56 Lerp 02:34 Quadratic Béziers 03:07 Cubic Béziers 03:57 De Casteljau's Algorithm 04:25 Bernstein Polynomial Form 06:18 1st Derivative (Velocity) 07:31 Tangents & Normals 08:03 2nd Derivative (Acceleration) 08:31 3rd Derivative (Jerk/Jolt) 09:07 Curvature 11:05 Bounding Box 14:14 Arc Length 15:07 Arc Length Parameterization & Uniform Animation 19:13 Outro 19:54 Credits 23:57 Thor helping me record this at 2am

[Source](https://www.youtube.com/watch?v=aVwxzDHniEw)

中文简报

Holmér利用弧长查找表解决贝塞尔曲线速度偏移问题 由于三次贝塞尔曲线缺乏闭式弧长积分,开发者必须通过数值查找表重映射参数值,以防止物体在动画过程中出现聚集和拉伸。 Freya Holmér从基础线性插值(lerp)入手解构贝塞尔曲线,通过德卡斯特里奥算法(De Casteljau's algorithm)和伯恩斯坦多项式形式,从二次曲线扩展至三次曲线。她展示了连续导数如何定义速度、加速度与曲率,从而为几何拉伸建立动态坐标系及密切圆。该解析还涵盖了通过求解导数二次方程的根来计算精确且紧凑的边界框,并在最后针对缺乏闭式弧长解的问题,提出利用数值弧长参数化查找表来实现匀速运动。 贝塞尔曲线既可以通过嵌套线性插值的德卡斯特里奥算法进行几何计算,也可以利用伯恩斯坦多项式作为控制点的加权和进行代数计算。 (3:57) n次贝塞尔曲线的每一阶导数都会生成一条n-1次的贝塞尔曲线,从而能够对速度、切线、法线、加速度和曲率进行解析计算。 (6:18) 通过二次方程公式求出一阶导数分量多项式的根,可以解析计算出紧凑的轴对齐边界框,避免了朴素估算带来的过大偏差。 (11:05) 由于潜在的椭圆积分,三次贝塞尔曲线缺乏弧长的符号闭式解,因此需要借助查找表弧长参数化等数值近似方法来实现匀速动画。 (14:03)

Reading summary

Freya Holmér shows that Bézier curves provide an elegant, computationally stable foundation for computer graphics and motion design by translating nested linear interpolations into polynomial calculus, even though physical constraints like arc length require numerical approximations. Geometric Interpolation and Polynomial Forms (1:56) Bézier curves are constructed from linear interpolation (lerp), defined as P(t) = (1 - t)P₀ + tP₁ for t in [0, 1]. Chaining lerps across control points generates higher-order curves: three points yield a quadratic curve via two sequential interpolation stages, while four points produce a cubic curve across three stages. Formally known as De Casteljau’s algorithm, this recursive evaluation preserves numerical stability by minimizing floating-point precision loss and remains robust regardless of control point placement. Expanding these recursive operations algebraically yields the Bernstein polynomial form, expressing curve positions as an affine combination where P(t) equals the sum of Bᵢ(t)Pᵢ. For a cubic curve, the four blending weights are (1 - t)³, 3(1 - t)²t, 3(1 - t)t², and t³. Because these polynomial weights satisfy the partition of unity—always summing to exactly 1 across the interval—the algebraic formulation maintains affine invariance while matching the spatial path traced by geometric lerps. Derivatives, Moving Frames, and Curvature Analysis (6:18) Differentiating an n-degree Bézier curve produces an (n-1)-degree Bézier curve, meaning the first derivative of a cubic curve is a quadratic Bézier representing its velocity vector. Normalizing this vector yields the unit tangent, and rotating it 90 degrees produces the 2D normal vector. Holmér explains that these vectors establish dynamic local coordinate frames, which are essential in game engines for orienting cinematic cameras and procedurally extruding 3D geometry such as pipes, roads, and rollercoaster rails. Higher-order differentiation reveals acceleration via a linear Bézier curve and jerk as a constant 2D vector. Combining velocity and acceleration defines signed curvature, calculated as the determinant of velocity and acceleration divided by the cubed speed: κ = (x'y'' - y'x'') / (x'² + y'²)^(3/2). This metric quantifies turning sharpness, with its reciprocal defining the radius of the osculating circle. At inflection points where curvature crosses zero, the osculating circle becomes mathematically undefined due to division by zero. Analytic Calculation of Tight Bounding Boxes (11:05) Axis-aligned bounding boxes (AABBs) accelerate spatial queries, broad-phase collision detection, and visibility culling by quickly rejecting objects that miss an intersection volume. Holmér notes that while deriving a bounding box from the minimum and maximum coordinates of the control points is fast, this naive approach frequently overestimates the curve's true envelope, causing wasted computation during raycasting. To calculate tight analytic bounding boxes, the 2D curve is separated into independent 1D functions for X and Y. Because spatial extents occur where coordinate derivatives equal zero, differentiating the cubic components yields standard quadratic equations: at² + bt + c = 0. Solving these equations with the quadratic formula identifies candidate extrema. Roots yielding negative discriminants or falling outside t in [0, 1] are discarded, while valid roots and the curve's endpoints at t = 0 and t = 1 establish the exact minimal and maximal coordinates. Arc Length Challenges and Distance Parameterization (14:03) Evaluating physical motion along a Bézier curve reveals a key mathematical limitation: cubic curves have no closed-form symbolic solution for total arc length, requiring an elliptic integral of the velocity vector magnitude. Furthermore, uniform increments in the parameter t do not correspond to uniform physical distances along the path. Because the velocity vector's magnitude varies during traversal, sampling points at equal parameter intervals causes them to bunch together or stretch apart. To achieve uniform pacing in animations and object placement, Holmér applies arc length parameterization using precomputed lookup tables. The curve is subdivided into discrete linear segments to map cumulative arc length against corresponding t-values. Querying a target travel distance prompts the system to find adjacent samples and linearly interpolate the appropriate parameter value, numerically solving the polynomial root to ensure constant-speed motion along the curve. Holmér concludes that although Bézier curves lack closed-form solutions for arc length and require numerical approximations for distance-based motion, their geometric elegance, algebraic stability, and analytical derivatives make them an indispensable foundation across real-time graphics and spline mathematics.

精炼阅读摘要

Freya Holmér 阐述了贝塞尔曲线(Bézier Curves)在数学构造与计算机图形学中的核心价值,指出其基于线性插值的几何构造优雅且应用广泛,但也存在缺乏弧长闭式解等数学局限,需结合数值方法进行工程近似。 线性插值与伯恩斯坦多项式形式 (1:56) 贝塞尔曲线的基本构建基石是线性插值(Lerp)。对于两个端点 P0 和 P1,通过标量参数 t(取值范围为 0 到 1)进行混合,公式为 (1 - t)P0 + tP1。当引入更多控制点时,可以通过嵌套插值实现更高阶的曲线:三个控制点通过两组线性插值再连接生成二次贝塞尔曲线,四个控制点通过三级递进插值生成三次贝塞尔曲线。这种逐级嵌套线性插值的几何计算方法被称为德卡斯特里奥算法(De Casteljau's algorithm),Holmér 强调该算法具有出色的数值稳定性且易于记忆。 从代数角度展开上述嵌套插值,曲线可以等价重写为各控制点位置矢量的加权和,即伯恩斯坦多项式形式(Bernstein polynomial form)。对于三次贝塞尔曲线,其四个基底多项式分别为 (1 - t)^3、3(1 - t)^2 t、3(1 - t) t^2 和 t^3。这些权重多项式在任意 t 值下的总和恒等于 1,满足单位分解(Partition of unity),从而保证了几何形态具有仿射不变性与尺度独立性。 导数阶梯递减与微分几何应用 (6:18) 对伯恩斯坦多项式形式求导揭示了贝塞尔曲线的一项重要性质:对 n 次贝塞尔曲线求导,得到的导数总是次数低一阶的 (n - 1) 次贝塞尔曲线。三次曲线的一阶导数表现为二次曲线,物理上对应沿曲线运动的速度矢量,该矢量的方向即为曲线的切线方向。将切线矢量归一化并旋转 90 度,即可建立二维法线矢量。切线与法线共同构成了曲线上的动态移动局部坐标系,为程序化生成道路表面、轨道和截面拉伸提供了基础。 继续求导可得到曲线的高阶物理属性。二次导数代表加速度矢量,在三次曲线上退化为一次线性插值;三次导数代表加加速度(Jerk),直接变为恒定的二维静态矢量。结合一阶速度矢量与二阶加速度矢量,可推导出曲率计算公式 κ = det(P'(t), P''(t)) / ||P'(t)||^3。曲率 κ 衡量了路径转弯的剧烈程度,其倒数定义了密切圆(Osculating circle)的半径。在曲率符号改变并穿过零点的拐点处,密切圆半径趋向于无穷大,数学上无法定义有限大小的圆。 导数求根求解紧密包围盒 (11:05) 在游戏引擎与实时图形学中,精确轴对齐包围盒(AABB)对于视锥裁剪、射线检测和粗略碰撞检测至关重要。直接采用四个控制点的坐标极值构造朴素包围盒虽然计算简单,但通常会严重高估曲线的实际边界范围,进而增加后续复杂相交测试的计算开销。 Holmér 指出,紧密包围盒的边界必须接触曲线局部的坐标极值点,这些极值点对应坐标导数等于零的位置。通过将二维曲线 P(t) 分解为独立的标量函数 X(t) 和 Y(t),并对其求一阶导数,三次曲线的分量导数会转变为一元二次方程 at^2 + bt + c = 0。利用标准求根公式可解出 X 与 Y 的候选参数值 t。在过滤掉判别式为负的虚根以及落在 [0, 1] 区间之外的实根后,将剩余有效根与起止端点 t=0、t=1 代入曲线方程进行评估,即可解析求出最小与最大坐标,构建出严密的边界盒。 弧长参数化困境与查找表解法 (14:03) 尽管贝塞尔曲线在多项式求值上表现优异,但在计算物理弧长时会遇到显著的数学困难。Holmér 指出,三次贝塞尔曲线的弧长积分属于椭圆积分,不存在代数闭式解。如果忽略物理距离、单纯按均匀步长的 t 参数沿曲线采样,曲线上的采样点在控制点被拉伸或弯曲时会出现聚拢与疏离,导致沿路径运动的速度产生严重畸变,因为一阶导数的模长在整条路径上并非恒定。 为实现恒定物理速度的平滑采样,工程上通常采用弧长参数化(Arc Length Parameterization)技术。具体实现方式是通过离散细分采样预先计算累积物理弧长并建立查找表(LUT)。当运行时需要查询指定物理距离对应的位置时,系统在查找表中检索相邻的采样区间并进行线性插值,以此逼近复杂多项式的根并重映射回 [0, 1] 区间的归一化参数 t。该工程近似方法能够消除速度突变,确保沿路径平滑运行。 游戏开发与图形渲染中的广泛工程实践 (1:06) 贝塞尔曲线及其连续样条是现代游戏开发与实时动画的基础组件。从运镜轨迹、自动化物体路径,到程序化挤压生成的过山车轨道与管道模型,均依赖其参数化插值机制。Holmér 在介绍其实体赛车游戏《Flowstorm》时提到,平滑的滑行赛道完全由相连的贝塞尔曲线构成,其关卡编辑器中的曲线手柄操作方式与 Adobe Photoshop 钢笔工具等矢量软件的设计规范完全契合。 除了空间位移,贝塞尔曲线的数学模型还能直接拓展至三维 RGB 颜色空间,用于实现控制点颜色的平滑过渡。Holmér 总结认为,尽管贝塞尔曲线在弧长等物理计算上存在必须依赖数值近似的不足,但其优雅的几何构建逻辑与灵活的功能特性,使其依然成为图形工业中不可或缺的基石工具。 贝塞尔曲线兼具简单的插值构造与强大的微分几何分析能力,尽管在精确弧长计算上缺乏闭式解而必须借助数值查找表近似,但它在实时渲染、碰撞优化以及程序化建模中仍然保持着核心的实用价值与工程生命力。

Detailed notes — zh

## Background 本内容由知名技术博主与游戏开发者 Freya Holmér 于 2021 年 8 月 19 日发布在 YouTube 平台。视频简介指出,贝塞尔曲线被广泛应用于动画、字体渲染和各类曲线图形绘制中,本期视频旨在深入浅出地拆解其底层的数学原理与几何运作机制。 ## TL;DR 视频从最基础的线性插值(Lerp)讲起,层层推进到德卡斯特里奥算法与伯恩斯坦多项式,全面拆解了二次及三次贝塞尔曲线的构建机制。Freya 深入探讨了曲线的一至三阶导数(速度、加速度与急动度)、切线与法线向量、曲率及吻切圆的几何含义,并展示了如何通过解析求解导数根来精准获取轴对齐紧密包围盒。随后,内容直面贝塞尔曲线缺乏闭式弧长解的工程痛点,详细剖析了均匀参数 t 与物理距离脱节导致的非匀速运动问题,并给出了基于查找表(LUT)的弧长参数化工程近似解。 ## Atmosphere & style 整部教程散发着优雅且极具美感的极客浪漫,将严谨抽象的数学公式转化为视觉震撼的程序化动态几何。Freya 的讲解清晰从容、幽默风趣,既有对优雅算法由衷的赞叹,也有面对复杂积分难题时接地气的自嘲。片尾展示自研 Unity 工具链的幕后花絮以及清晨两点猫咪蹭麦克风撒娇的温情镜头,为这堂硬核数学课增添了浓郁的亲切感与人情味。 ## Bulletin - [01:56](https://www.youtube.com/watch?v=aVwxzDHniEw&t=116s) 贝塞尔曲线在几何上可通过德卡斯特里奥算法以纯粹的线性插值(Lerp)逐层嵌套构建,在代数上则等价于伯恩斯坦基底多项式的加权求和。 - [06:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=378s) 三次贝塞尔曲线的一阶导数是二次贝塞尔曲线,利用其导数多项式求根可解析计算出紧密轴对齐包围盒,避免盲目采样。 - [14:14](https://www.youtube.com/watch?v=aVwxzDHniEw&t=854s) 三次贝塞尔曲线的弧长计算属于缺乏闭式解的椭圆积分,无法直接用参数 t 实现匀速运动,工程上通常依赖查找表进行数值弧长参数化。 - [20:05](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1205s) 视频中的全部程序化几何与数学动画均在 Unity 引擎内开发,结合了自研开源矢量插件 Shapes 与数学库 Mathfs。 ## Key takeaways - [00:00](https://www.youtube.com/watch?v=aVwxzDHniEw&t=0s) 贝塞尔曲线提供了一种在计算上极其优雅的路径定义方式,广泛用于相机运镜、程序化 3D 建模和矢量绘图软件。 - [02:34](https://www.youtube.com/watch?v=aVwxzDHniEw&t=154s) 二次贝塞尔曲线通过在两根线段的线性插值点之间进行第二次线性插值(Lerp)生成。 - [03:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=187s) 德卡斯特里奥算法将三次贝塞尔曲线完全拆解为嵌套线性插值,具有极佳的数值稳定性和实现直观性。 - [04:25](https://www.youtube.com/watch?v=aVwxzDHniEw&t=265s) 伯恩斯坦多项式形式展现了控制点权重的代数本质,任一时刻所有基底多项式的权重之和恒等于 1。 - [06:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=378s) n 次贝塞尔曲线的导数是一条 n-1 次贝塞尔曲线;三次曲线的一阶导数对应切线速度向量,旋转 90 度即可获取法线。 - [08:01](https://www.youtube.com/watch?v=aVwxzDHniEw&t=481s) 二阶导数对应质点运动的加速度(一次贝塞尔线段),三阶导数对应加加速度(Jerk/Jolt,固定常数向量)。 - [09:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=547s) 曲率可通过速度与加速度的二维叉积除以速率的三次方计算,其倒数为吻切圆半径,曲率为 0 处即为拐点。 - [11:05](https://www.youtube.com/watch?v=aVwxzDHniEw&t=665s) 通过对一阶导数的 x 和 y 分量求二次方程根,可以解析解出极值点,从而构建出极小且贴合的紧密轴对齐包围盒。 - [14:14](https://www.youtube.com/watch?v=aVwxzDHniEw&t=854s) 三次贝塞尔曲线的弧长计算属于椭圆积分,不存在解析闭式解,工程实现必须采用微元线段细分的数值近似累加。 - [15:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=907s) 参数 t 的均匀变化并不等同于物理空间的匀速位移,控制点形状变化会导致一阶导数模长不均,引发运动速度波动。 - [17:09](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1029s) 通过构建“物理弧长-参数 t”查找表并在相邻区间线性插值,能够实现等距点分布与恒定速度沿线漫游。 - [19:13](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1153s) 贝塞尔曲线可以拓展到更高维度(如三维 RGB 颜色插值),且只是更广阔的 B 样条等几何体系的一个子集。 - [20:05](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1205s) 整部教程是受 3Blue1Brown 启发并耗时一个月打造,工具链涵盖 Unity、Shapes 矢量渲染插件、Mathfs 库与 DaVinci Resolve。 ## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=aVwxzDHniEw&t=0s) 贝塞尔曲线的魅力与广泛应用 在接触贝塞尔曲线(Bézier Curves)和样条线(Splines)之前,Freya Holmér 对曲线的理解非常基础,局限于类似于 $y = x^2 - 1$ 的标准抛物线或简单的圆弧。对于那些能够在平面中任意转向、打结甚至盘旋成环的复杂曲线,她曾感到完全摸不着头脑。然而,一旦揭开这类曲线的几何构造逻辑,将它们首尾相连拼接成样条线的思路便顺理成章地浮现出来。正如 Freya Holmér 所指出的:“它们能让你以一种在计算上极其优雅的方式来定义路径。”(“They let you define a path in a way that is computationally very elegant”)借助曲线上每个点的切线(Tangent)与法线(Normal)方向,开发者可以轻松确定物体的朝向,或者围绕路径上的任意位置构建局部坐标系,这对于生成程序化几何体(Procedural Geometry)而言至关重要。此外,通过曲率半径(Radius of Curvature)还能分析曲线的转向速度与方向,甚至可以通过解析方法直接求出曲线的紧密包围盒(Bounding Box),用于极大地优化碰撞与相交测试。 贝塞尔曲线和样条线在游戏开发和计算机图形学中几乎无处不在。从最基础的摄像机沿轨道平滑运镜,到完全依赖样条线生成的 3D 模型——例如支持弯曲、扭转和拉伸的过山车轨道,无一例外都在底层依赖贝塞尔曲线。Freya Holmér 在制作自己的游戏《Flowstorm》时,也是依靠样条线来生成玩家驾驶飞船紧贴滑行的光滑弯道;其关卡编辑器甚至直接向玩家提供了可调整的贝塞尔曲线控制手柄,这种交互模式与 Photoshop 中的“钢笔工具(Pen Tool)”如出一辙。 - **常见用途**:游戏动画运镜、程序化 3D 道路与轨道建模、物理滑道轨迹以及各类矢量绘图软件的手柄调节。 - **数学与几何优势**:支持精确求导获取切线与法线、计算曲率半径,以及解析求取精准包围盒。 --- ### [01:56](https://www.youtube.com/watch?v=aVwxzDHniEw&t=116s) 线性插值(Lerp)与二次贝塞尔曲线 贝塞尔曲线的本质是从最简单的线性插值(Linear Interpolation,简称 Lerp)层层构建而来的。设想空间中存在由线段连接的两个端点 $P_0$ 和 $P_1$。如果在线段上引入第三个点 $P$,其位置便可以通过一个参数 $t$ 来精确描述:$t$ 的取值范围在 0 到 1 之间,类似于百分比进度。当 $t = 0$ 时,点 $P$ 落在 $P_0$;当 $t = 1$ 时,点 $P$ 移动到 $P_1$;而在 0 与 1 之间的任何数值都会生成两点间的加权过渡。在数学上,这一线性插值函数可以清晰地表述为 $(1-t)P_0 + tP_1$。 如果再额外引入第三个控制点构成两条线段,每条线段上都各有一个依赖于相同 $t$ 参数进行线性插值的点,事情就变得有趣起来。当我们在两根线段各自对应的插值点之间重新连接一条新的线段,并在这条新线段上以完全相同的 $t$ 参数再次进行插值时,这个处于最内层的插值点就会随着 $t$ 从 0 匀速演进到 1,在空间中勾勒出一条平滑优美的轨迹——这便是二次贝塞尔曲线(Quadratic Bézier Curve)。 ```mermaid flowchart TD accTitle: 二次贝塞尔曲线的几何插值构造流程 accDescr: 展示从三个控制点通过两轮线性插值推导二次贝塞尔曲线上单点的嵌套过程 subgraph Inputs ["控制点与一级插值"] P0["端点 P0"] P1["控制点 P1"] P2["端点 P2"] L01["插值点 Lerp(P0, P1, t)"] L12["插值点 Lerp(P1, P2, t)"] P0 --> L01 P1 --> L01 P1 --> L12 P2 --> L12 end subgraph Output ["二级插值"] CurvePoint["二次贝塞尔曲线上的点: Lerp(L01, L12, t)"] L01 --> CurvePoint L12 --> CurvePoint end ``` --- ### [03:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=187s) 三次贝塞尔曲线与德卡斯特里奥算法(De Casteljau's Algorithm) 顺着二次曲线的嵌套逻辑继续推广,如果添加第四个控制点,便能得到业界最常见的三次贝塞尔曲线(Cubic Bézier Curve)。它的几何构造步骤完全一致:由四个初始控制点连接成三条线段,在每条线段上按参数 $t$ 取得三个插值点;将这三个点连成两条新线段,再插值出两个点;连接这两个点并在最终的线段上执行最后一次线性插值,终点所走出的平滑轨迹就是三次贝塞尔曲线。这种几何机制的精妙之处在于,无论控制点摆放在三维或二维空间的何处,遵循这套简单的规则都能稳定生成一条连续平滑的曲线。 这种依靠层层嵌套线性插值来求取曲线上任意点的方法,正式名称为“德卡斯特里奥算法(De Casteljau's Algorithm)”。对于该算法,Freya Holmér 表达了极高的赞赏:“我个人非常喜欢它,因为它的数值稳定性极高,而且极其容易记忆:从头到尾它全都是插值(lerp)。”(“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.”)无论是编程实现还是心算推演,这种纯粹由线性插值构建的算法不仅健壮,而且避免了高次多项式在浮点运算中容易出现的精度坍缩问题。 --- ### [04:25](https://www.youtube.com/watch?v=aVwxzDHniEw&t=265s) 伯恩斯坦多项式形式(Bernstein Polynomial Form) 除了几何上的嵌套插值,贝塞尔曲线还有一种更为代数化的视角。如果将三次曲线中所有展开的嵌套插值公式完全写下并展开整理,会发现整个公式可以按照四个初始控制点重新编排。将每个控制点视作从原点出发的向量,它们各自乘以一个关于参数 $t$ 的三次多项式: $$B_0(t) = (1-t)^3$$ $$B_1(t) = 3(1-t)^2 t$$ $$B_2(t) = 3(1-t) t^2$$ $$B_3(t) = t^3$$ 这些多项式被称为伯恩斯坦基底多项式(Bernstein Polynomials)。当观察这四个多项式随着 $t$ 在 0 到 1 之间变动时的数值变化,会发现它们充当了控制点之间的权重分配角色:在 $t = 0$ 时,第一个多项式的权重为 1,其余全为 0;随着 $t$ 逐渐增加,权重逐渐向后续的控制点流动并交替主导,直到 $t = 1$ 时最后一个权重达到 1。在任意给定的 $t$ 值下,所有基底多项式的权重相加恒等于 1。这种加权求和的形式与德卡斯特里奥算法在数学上完全等价,却提供了一个纯粹的多项式函数视角。 - **加权求和特性**:任一时刻四个基底多项式之和恒等于 1,满足仿射组合(Affine Combination)性质。 - **数学等价性**:嵌套线性插值与伯恩斯坦多项式展开是同一数学对象的两种不同表现形式。 --- ### [06:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=378s) 导数、切线与法线(Tangents and Normals) 一旦将曲线拆解为伯恩斯坦多项式与常数控制点向量相乘的形式,对多项式求导便变得轻而易举。由于各个控制点在几何上是固定不变的常数,曲线的一阶导数便直接表示曲线在特定 $t$ 值下的变化率,即速度向量(Velocity Vector)。Freya Holmér 指出了一个非常迷人的数学性质:“三次贝塞尔曲线的导数,其本身正是一条二次贝塞尔曲线。”(“...the derivative of the cubic bézier curve is, in and of itself, a quadratic bézier curve.”)更广泛地说,任何 $n$ 次贝塞尔曲线的导数都是一条 $n-1$ 次的贝塞尔曲线。 速度向量与当前位置的曲线相切。将其进行归一化(Normalize)处理后,便能立即获得曲线在该点的切线方向(Tangent Direction);如果将该切线向量直接在平面内逆时针旋转 90 度,就能瞬间得到与之垂直的法线方向(Normal Direction)。有了切线和法线构成的局部正交基,开发者便能在曲线的任意位置向外计算偏移量(Offset Points),这正是程序化生成 3D 道路、管道壁厚以及挤出几何网格的核心数学工具。 --- ### [08:01](https://www.youtube.com/watch?v=aVwxzDHniEw&t=481s) 高阶导数:加速度与加加速度(Jolt / Jerk) 沿着导数链条继续向下推演,对一阶导数(速度)再次求导即可得到二阶导数。如果说一阶导数代表曲线上运动点的速度,那么二阶导数便直观地反映出该点的加速度(Acceleration),即速度向量随 $t$ 变化的变化率。由于三次曲线的一阶导数是二次贝塞尔曲线,其二阶导数顺理成章地退化为一条一次贝塞尔曲线(即一条连接两点的简单线段,本质上是一个基础线性插值)。 更进一步,对二阶导数继续求导会得到三阶导数,物理学上称之为“急动度”或“加加速度”(Jerk 或 Jolt),代表加速度的变化率。对于三次贝塞尔曲线而言,三阶导数已经不再包含任何与 $t$ 相关的变量,它退化成了一个固定不变的二维常数向量。当参数 $t$ 从 0 扫描至 1 时,这些阶梯式递减的导数系统就像一组相互牵引的力臂,精准控制着曲线上质点的轨迹流动。 | 导数阶数 | 物理概念 | 几何表现形式(对于三次曲线) | 数学意义 | |:--- |:--- |:--- |:--- | | **0阶** | 位置 (Position) | 三次贝塞尔曲线 (Cubic Bézier) | 空间坐标点轨迹 | | **1阶** | 速度 (Velocity) | 二次贝塞尔曲线 (Quadratic Bézier) | 切线方向与瞬时速率 | | **2阶** | 加速度 (Acceleration) | 一次贝塞尔曲线 (线段 / 单个 Lerp) | 速度的变化方向与速率 | | **3阶** | 加加速度 (Jerk / Jolt) | 单个固定的二维常数点 (Constant Vector) | 加速度的变化率 | --- ### [09:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=547s) 曲率与吻切圆(Curvature & Osculating Circle) 结合一阶导数(速度)与二阶导数(加速度),可以计算出一个极具几何深度的参数——曲率(Curvature,通常用希腊字母 $\kappa$ 表示)。对于任意参数化曲线,曲率的计算公式出人意料地简洁: $$\kappa = \frac{\det(v, a)}{|v|^3}$$ 即速度向量 $v$ 与加速度向量 $a$ 的行列式(二维叉积)除以速度模长(速率)的立方。曲率直观地描述了曲线在某一微小局部到底弯曲得多剧烈:当曲率为 0 时,说明当前曲线在该点瞬间呈现笔直状态;曲率的绝对值越大,曲线在该点折弯得就越紧绷。 在物理量纲上,Freya 习惯将其理解为“弧度每米(Radians per meter)”,但另一种更加经典的直观诠释是“曲率半径的倒数”。由此可以推导出当前点的吻切圆(Osculating Circle):吻切圆紧贴在曲线凹侧,其局部曲率与曲线在该点的曲率完全吻合,其圆心位于法线方向上。当曲线反向弯曲时,曲率会从负值穿过 0 变成正值。这个曲率穿过零点的分界位置被称为拐点(Inflection Point)。在拐点处,由于曲线瞬间呈绝对直线,分母曲率变为 0,吻切圆的半径趋于无穷大,因而吻切圆在该点未定义(无法除以零)。 - **吻切圆半径公式**:$R = \frac{1}{|\kappa|}$。 - **拐点特征**:曲率变号且等于 0 的临界点,局部曲率中心与吻切圆半径无法以有限数值定义。 --- ### [11:05](https://www.youtube.com/watch?v=aVwxzDHniEw&t=665s) 解析求取曲线的紧密包围盒(Bounding Box) 导数的一个非常实用且常被忽视的用途,是解析计算贝塞尔曲线的轴对齐紧密包围盒(Tight Bounding Box)。在游戏引擎和图形管线中,轴对齐包围盒被广泛用于视锥剔除(Frustum Culling)和相交测试初筛:例如在判断一条射线是否与复杂曲线相交之前,先用计算开销极低的包围盒进行碰撞测试;只有射线穿过包围盒时,才进一步调用高精度的曲线求交算法。 直接取四个控制点的极值坐标生成包围盒是一种朴素(Naïve)的近似解法,但这种外接盒往往过于松散,与实际曲线边界之间存在巨大冗余。为了求得真正贴合曲线边界的极小包围盒,必须找到曲线上 $x$ 和 $y$ 坐标分别达到局部极小值(Local Minima)和局部极大值(Local Maxima)的点。将曲线沿坐标轴拆解为 $x(t)$ 与 $y(t)$ 两个独立的一维标量函数后,这些局部极值点恰好出现在一阶导数等于零的位置: 1. **多项式重组**:将曲线的一阶导数多项式重新按变量 $t$ 降幂排列,整理为形如 $a t^2 + b t + c = 0$ 的标准一元二次方程。 2. **求取导数根**:利用标准求根公式(Quadratic Formula)分别对 $x'(t) = 0$ 和 $y'(t) = 0$ 进行求解,理论上最多可以得到 4 个潜在的候选 $t$ 值($x$ 方向两个,$y$ 方向两个)。 3. **筛选合法解**:必须筛除平方根内部为负数的非实数解(正如 Freya 调侃道:“those t-values aren't real, ignore them”),以及不在 $[0, 1]$ 参数区间内的无效解。 4. **包围盒合成**:将筛选出的有效极值点坐标与曲线的起点($t=0$)和终点($t=1$)坐标汇总,取其中的最小与最大 $x$、$y$ 坐标,即可拼凑出完全契合曲线轮廓的紧密轴对齐包围盒。 ### [13:18](https://www.youtube.com/watch?v=aVwxzDHniEw&t=798s) 解析求解贝塞尔曲线的包围盒 通过观察二次导数曲线(即一阶导数)与 X 轴和 Y 轴相交的位置,可以精确找到三次贝塞尔曲线在水平和垂直方向上的极值点。当动态调整曲线的形状时,导数曲线的交点也会实时变化,展示出极值点在空间中的平移过程。Freya Holmér 总结道:“And that's how you analytically get the bounding box of a cubic bézier curve.” 借助这种基于求导找零点(根)的解析方法,计算系统无需对曲线进行密集的步进采样,就能精准获取三次贝塞尔曲线严丝合缝的轴对齐包围盒(Bounding Box)。 ### [14:14](https://www.youtube.com/watch?v=aVwxzDHniEw&t=854s) 弧长难题与数值细分近似 整部视频的前半部分一直依赖 $t$ 参数(取值范围为 0 到 1)来表示点在曲线上的相对进度,但随之而来的关键问题是:这个点实际上究竟移动了多远?整条曲线的总长度(即弧长,Arc Length)到底是多少?遗憾的是,贝塞尔曲线的优雅在此处遭遇了数学上的现实壁垒——三次贝塞尔曲线的弧长计算并不存在闭式解(closed-form solution)。Freya 直言这一积分属于“椭圆积分”(elliptic integral),在工程实践中往往意味着令人头疼的复杂性,用她幽默的话来说就是“悲伤与绝望”(sadness and despair)。 既然无法直接求得解析解,就只能退而求其次采用数值近似法。最直观的做法是将整条曲线细分为一系列微小的线段,然后计算每个线段的长度并累加求和。细分的采样点越多,测得的弧长就越精确;但代价显而易见,采样点越密集,计算开销也就越高。Freya 在屏幕上展示了形式化的积分与级数求和符号,并调侃自己甚至不确定为什么要把公式打出来,因为数学符号并不如动画直观,但权当是“送给数学符号爱好者的一份礼物”。 ```mermaid flowchart TD accTitle: 贝塞尔曲线弧长数值近似流程 accDescr: 展示将贝塞尔曲线细分为线段并累加求和以近似计算弧长的高层流程 subgraph Evaluation["曲线采样"] A["设定采样精度 N"] --> B["在 t 轴均匀采样 [t_0, t_1,... t_N]"] B --> C["求得曲线上各点坐标 P_i"] end subgraph Accumulation["累加求和"] C --> D["计算相邻点欧氏距离 |P_i - P_{i-1}|"] D --> E["累加所有线段长度得到近似弧长"] end ``` ### [15:07](https://www.youtube.com/watch?v=aVwxzDHniEw&t=907s) 匀速动画的陷阱:t 参数与实际距离的脱节 求出整条曲线的弧长之后,一个自然的需求接踵而至:如果希望获取距离起点特定物理长度处的点,该如何处理?最直观的直觉是将目标距离除以总弧长,以此算出百分比作为 $t$ 值来代入曲线方程。许多人因此以为可以直接在曲线上放置点,并按照恒定距离驱动它们做匀速运动。然而,Freya 指出这正是贝塞尔曲线露出“更丑陋一面”的开端:“If we change our control points, our dots are not equally spaced anymore.” 只要调整曲线的控制点,原本看似均匀分布的点就会立刻变得参差不齐,在曲线上不同位置的移动速度也会忽快忽慢。 出现这种现象的根源在于:在贝塞尔曲线中,均匀分布的 $t$ 值并不对应空间中等距分布的物理距离。借助一阶导数(即速度向量)可以直观剖析这一缺陷。导数向量的模长代表点在曲线上的运动速率;只有当导数随时间变化的轨迹恰好落在某个圆上时,全曲线的速率才会接近恒定。而在绝大多数常规曲线上,导数轨迹呈现极其不规则的形态,导致物体在某些曲率大或控制点紧凑的区域急剧减速,在其他区域则飞速掠过。在极端控制点排布下,这种速度不均的瑕疵会被无限放大。 - 物理直觉:$t$ 是曲线参数空间的抽象进度,并非真实物理空间的度量衡。 - 导数表象:一阶导数模长(速度大小)不恒定,是点沿曲线运动无法保持匀速的数学本质。 ### [17:09](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1029s) 弧长参数化:利用查找表恢复恒定速度 为了彻底解决匀速运动和等距分布的问题,必须引入“弧长参数化”(Arc Length Parameterization)。由于缺少解析解,工程上最高效的近似策略是构建查找表(Lookup Table, LUT)。算法首先在曲线上进行细分采样,将每个采样点的参数 $t$ 及其对应的累积物理弧长存入表中。采样越密集,映射精度越高,但内存和预计算开销也成倍上升。构建好表格后,给定任意目标距离值,只需在查找表中定位相邻的距离采样点,通过简单的线性插值就能反向解出所需的 $t$ 值。 这种查找与插值的机制,本质上是数值近似求解一个极度复杂的非线性多项式方程的根。Freya 展示了自己的实现源码:该工具维护一个物理距离列表,输入任意目标距离后,能迅速计算并返回一个在 0 到 1 之间的归一化位置参数。当把点分布的依据从“等距的 $t$ 步长”切换为“基于查找表换算出的真实等距物理步长”时,曲线上的采样点瞬间恢复了完美的视觉等距,沿路径运动的动画也变得平滑、匀速。Freya 坦言这种数值手段虽然看起来有些杂乱粗糙,但:“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.” ```mermaid flowchart LR accTitle: 弧长参数化查找表机制 accDescr: 展示输入物理距离并通过查找表近似反推 t 值的计算逻辑 D_in["输入目标物理距离 s"] --> Lookup["查找表定位相邻采样点"] Lookup --> Interp["相邻区间内线性插值"] Interp --> T_out["解出对应的参数 t 值"] T_out --> Curve["代入贝塞尔方程求值 B(t)"] Curve --> P_out["输出等距/匀速的空间坐标"] ``` ### [19:13](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1153s) 瑕不掩瑜的优美曲线与样条宇宙 尽管贝塞尔曲线在求弧长和匀速运动时暴露出不少数学上的局限性与工程妥协,Freya 依然给予了它极高的评价:“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~” 完美的解析解并非必需品,即便依赖近似算法,开发者依然能轻松驱动摄像机在华丽的场景中穿梭漫游,呈现出如优秀电子游戏一般的丝滑运镜。 贝塞尔曲线的维度还可以自由扩展。Freya 透露,在前面讲解伯恩斯坦多项式权重混合时,为了在三种颜色之间做平滑渐变,她实际上是在三维 RGB 颜色空间中构建了一条三维贝塞尔曲线来进行色彩插值。贝塞尔曲线仅仅是庞大几何学领域的冰山一角,在其之外还存在着更加深邃广阔的“样条电影宇宙”(cinematic universe of splines),比如 B 样条(B-splines)等高级样条曲线。 ### [20:05](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1205s) 致谢与幕后制作:从 Unity 工具链到清晨两点的猫咪 视频尾声,Freya 流露出由衷的激动与感激。这是她制作周期最长、投入精力最多的单体项目,她由衷感谢 Patreon 赞助者的支持。正因为有赞助者的后盾,当看到知名数学科普博主 Grant Sanderson(3Blue1Brown)提议“大家何不尝试做做数学视频”时,她才能毫不犹豫地抽出整整一个月的时间全力以赴开发这支视频。Freya 强调,自己长期以来一直想制作严谨而生动的数学视频,过去受限于精力大多只能在 Twitter 上发布零碎的技术动图,而 3Blue1Brown 的鼓励促成了她迈出这关键的一步。她还特别感谢了 Jazz Mickle(queenjazz)为视频专门创作的优秀配乐。 Freya 详细披露了整部视频的技术制作栈: - 渲染与动画引擎:全部程序化数学动画均在 Unity 游戏引擎中直接开发与运算。 - 时间轴工具:自制了一套轻量级的时间轴工具,用于串联代码驱动的程序化动画事件。 - 基础数学库:使用开源自研的 Mathfs 库处理贝塞尔曲线求值与数值范围重映射(range remapping)。 - 矢量渲染核心:所有几何视觉元素均依赖自己研发的 Unity 矢量图形插件 Shapes(支持实时和离线渲染)。 - 后期剪辑流程:通过自制工具逐帧导出高分辨率 PNG 图像序列,最后导入 DaVinci Resolve 进行剪辑和音画合成。许多开发与制作细节此前已在 Twitch 进行了直播。 视频在融洽温情的氛围中收尾。画面最后切入一段清晨两点录制音频时的即兴花絮:屏幕上弹出各种撒娇字幕(“mom pls”、“bed pls”),猫咪 Thor 正用头拼命蹭着麦克风催促主人睡觉。Freya 带着宠溺而疲惫的笑意对麦克风低语:“Thor wants me to go to bed”,为整部严密而优美的数学教程画上了一个极具人情味的句号。 - 音乐制作:Jazz Mickle(queenjazz) - 启发与推手:Grant Sanderson(3Blue1Brown) - 软件与插件:Unity、Shapes(矢量插件)、Mathfs(数学库)、DaVinci Resolve - 特别出镜:猫咪 Thor(于凌晨 2 点录音时强制抗议求休息) ## Notable quotes > [19:13](https://www.youtube.com/watch?v=aVwxzDHniEw&t=1153s) 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~ — Freya Holmér ## Mentioned Freya Holmér, Flowstorm, Photoshop, Grant Sanderson, 3Blue1Brown, Jazz Mickle, Pomax, Thor, Unity, Shapes, Mathfs, DaVinci Resolve, Twitter, Twitch, Patreon ## Video description Bézier curves - how do they do? They're used for animation, text rendering, and all sorts of curved shapes! But how do they actually work? well, like, that's what the video is about, so, watch it to find out etc!! • Lots of love to 💛 Jazz "queenjazz" Mickle for making the music ❱ https://queenjazz.bandcamp.com/ 💙 Grant "3Blue1Brown" Sanderson for pushing me to finally do this ❱ https://youtube.com/3blue1brown 🐦 Pomax for their wonderful writeup on Bézier curves ❱ https://pomax.github.io/bezierinfo 🐈 Thor the cat for.. hanging out.. when I was trying to record audio with no interruptions 🇫🇷 French subtitles by @damqui on Twitter • How was this video made? 🔨 Created in the Unity game engine ⭕ Using Shapes, my vector graphics plugin ❱ https://u3d.as/1W37 📈 Using Mathfs, my math library ❱ https://github.com/FreyaHolmer/Mathfs ...along with a bunch of hacky, partially broken, procedural animation tools I made specifically for this video • Did you know that "osculating" isn't pronounced that way? ✅ yes I do now in fact please stop commenting on it ;-; ❱ https://twitter.com/FreyaHolmer/status/1429472399389507591 • Links 💖 Patreon ❱ https://www.patreon.com/acegikmo 🐦 Twitter ❱ https://twitter.com/FreyaHolmer 📺 Twitch ❱ https://www.twitch.tv/acegikmo 💬 Discord ❱ https://discord.gg/v5VWuga 🌸 Instagram ❱ https://instagram.com/freya_holmer 00:00 Intro 01:06 Use Cases of Bézier Curves 01:56 Lerp 02:34 Quadratic Béziers 03:07 Cubic Béziers 03:57 De Casteljau's Algorithm 04:25 Bernstein Polynomial Form 06:18 1st Derivative (Velocity) 07:31 Tangents & Normals 08:03 2nd Derivative (Acceleration) 08:31 3rd Derivative (Jerk/Jolt) 09:07 Curvature 11:05 Bounding Box 14:14 Arc Length 15:07 Arc Length Parameterization & Uniform Animation 19:13 Outro 19:54 Credits 23:57 Thor helping me record this at 2am [Source](https://www.youtube.com/watch?v=aVwxzDHniEw)

Source quotes

[19:13] Freya Holmér: 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~

Source quotes

[6:18] Freya Holmér: The derivative of a bézier curve is always another bézier curve of one degree lower. [19:13] Freya Holmér: 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~

Original transcript

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