The Bezier curve is the most common spline, and is used to design streamlined cars (that's why the algorithm was invented), in Photoshop, and to make roads in the game Cities: Skylines. The basic idea is that you have 2 end points and 2 control points. To form the final spline you need to interpolate linearly in different layers with De Casteljau's algorithm. But why is it called a Bezier curve if we are using De Casteljau's algorithm? The answer is that poor De Casteljau came up with the algorithm and Bezier stole it a few years later and renamed it to Bezier! Anyway, the algorithm is best explained with a picture:
A and D are the end points, and B and C are the control points. This will form a cubic curve. It is possible to add just one control point and you will end up with a quadratic curve, which is useful if you have limited processing power. For example, the game Quake 3 used quadratic Bezier curves. But a quadratic curve is less flexible than a cubic curve. You may also add more dimensions, so you can have as many control points as you want.
If A and D are fixed, you can move B and C to change the shape of the curve. But to make the curve itself, you first have to interpolate linearly between A and B, B and C, C and D. Now you have 3 new positions: Q, R, S. Now you are at a different "layer," so you have to interpolate linearly between Q and R, and R and S. To get the final point U you need on the Bezier curve, you interpolate linearly one final time between P and T. All these interpolations use the same t value. This is how it looks like in a script (To make it work you just need 4 spheres that make up the end points and control points):
using UnityEngine; using System.Collections; //Interpolation between 2 points with a Bezier Curve (cubic spline) public class BezierCurve : MonoBehaviour { //Has to be at least 4 so-called control points public Transform startPoint; public Transform endPoint; public Transform controlPointStart; public Transform controlPointEnd; //Easier to use ABCD for the positions of the points so they are the same as in the tutorial image Vector3 A, B, C, D; //Display without having to press play void OnDrawGizmos() { A = startPoint.position; B = controlPointStart.position; C = controlPointEnd.position; D = endPoint.position; //The Bezier curve's color Gizmos.color = Color.white; //The start position of the line Vector3 lastPos = A; //The resolution of the line //Make sure the resolution is adding up to 1, so 0.3 will give a gap at the end, but 0.2 will work float resolution = 0.02f; //How many loops? int loops = Mathf.FloorToInt(1f / resolution); for (int i = 1; i <= loops; i++) { //Which t position are we at? float t = i * resolution; //Find the coordinates between the control points with a Catmull-Rom spline Vector3 newPos = DeCasteljausAlgorithm(t); //Draw this line segment Gizmos.DrawLine(lastPos, newPos); //Save this pos so we can draw the next line segment lastPos = newPos; } //Also draw lines between the control points and endpoints Gizmos.color = Color.green; Gizmos.DrawLine(A, B); Gizmos.DrawLine(C, D); } //The De Casteljau's Algorithm Vector3 DeCasteljausAlgorithm(float t) { //Linear interpolation = lerp = (1 - t) * A + t * B //Could use Vector3.Lerp(A, B, t) //To make it faster float oneMinusT = 1f - t; //Layer 1 Vector3 Q = oneMinusT * A + t * B; Vector3 R = oneMinusT * B + t * C; Vector3 S = oneMinusT * C + t * D; //Layer 2 Vector3 P = oneMinusT * Q + t * R; Vector3 T = oneMinusT * R + t * S; //Final interpolated position Vector3 U = oneMinusT * P + t * T; return U; } }
That wasn't too difficult? If you go to the editor you should see this: