# Drawing Curves

> Learn how to draw curves in Babylon.js.

Source: https://doc.babylonjs.com/features/featuresDeepDive/mesh/drawCurves

## How To Draw Curves

If you want to draw a circular path, it is easy enough to generate the points in the XY plane using:

```javascript
const path = [];
for(let theta = 0; theta < 2 * Math.PI; theta +=deltaTheta ) {
    path.push(new BABYLON.Vector3(radius * Math.cos(theta), radius * Math.sin(theta), 0));
```

If you want to, you can work out some quite complex paths by hand.

What follows is how to draw some mathematical curves by using the Babylon.js _Curve3_ object, from which you can extract the array of points you need to draw lines, ribbons, tubes and extruded shapes.

The general form is

```javascript
const curve = BABYLON.Curve3.Create.CURVETYPE(parameters);
```

## Arc Through Three Points

Available from version 5.0.0.
Given three points in space that are not in a straight line, it is always possible to join them with a circular arc or to draw a circle through all three points.

```javascript
const arc = BABYLON.Curve3.ArcThru3Points(first, second, third, steps, closed, fullCircle);
```

- **first** _Vector3_ the first point the arc must pass through.
- **second** _Vector3_ the second point the arc must pass through.
- **third** _Vector3_ the third point the arc must pass through.
- **steps** _number_ the larger the number of steps the more detailed the arc.
- **closed** _boolean_ optional with default false, when true forms the chord from the first and third point
- **fullCircle** _boolean_ optional with default false, when true forms the complete circle through the three points

This static method returns an instance of _Curve3_.  
Just use the Curve3 _getPoints()_ method to fill your array : _getPoints()_ returns an array of successive _Vector3_.  
The _length()_ method returns the curve length.

```javascript
const path = arc.getPoints();
const l = arc.length();
```

- [Playground: Arc](https://playground.babylonjs.com/#KENEJP#3) - Open arc.

- [Playground: Segment](https://playground.babylonjs.com/#KENEJP#4) - Segment.

- [Playground: Full Circle](https://playground.babylonjs.com/#KENEJP#5) - Full Circle.

## Quadratic Bezier Curve

http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Quadratic_curves

![Wikipedia Quadratic Bezier Curve](https://upload.wikimedia.org/wikipedia/commons/3/3d/B%C3%A9zier_2_big.gif)

```javascript
const bezier2 = BABYLON.Curve3.CreateQuadraticBezier(origin, control, destination, nb_of_points);
```

- **origin** : _Vector3_ the origin point,
- **control** : _Vector3_ the control point,
- **destination** : _Vector3_ the destination point,
- **nb_of_points** : _number_ number of points wanted in the path array.

This static method returns an instance of _Curve3_.  
Just use the Curve3 _getPoints()_ method to fill your array : _getPoints()_ returns an array of successive _Vector3_.  
The _length()_ method returns the curve length.

```javascript
const path = bezier2.getPoints();
const l = bezier2.length();
```

- [Playground: Drawing A Bezier Quadratic Curve](https://playground.babylonjs.com/#W0XSPA) - Simple example of drawing a bezier quadratic curve.

## Cubic Bezier curve

http://en.wikipedia.org/wiki/B%C3%A9zier_curve# Higher-order_curves

![Wikipedia Cubic Bezier Curve](https://upload.wikimedia.org/wikipedia/commons/d/db/B%C3%A9zier_3_big.gif)

```javascript
const bezier3 = BABYLON.Curve3.CreateCubicBezier(origin, control1, control2, destination, nb_of_points);
```

- **origin** : _Vector3_ the origin point,
- **control1** : _Vector3_ the first control point,
- **control2** : _Vector3_ the second control point,
- **destination** : _Vector3_ the destination point,
- **nb_of_points** : _number_ the desired number of points in the final curve array.

This static method returns an instance of _Curve3_.  
Just use the Curve3 _getPoints()_ method to fill your array : _getPoints()_ returns an array of successive _Vector3_.  
The _length()_ method returns the curve length.

```javascript
const path = bezier3.getPoints();
const l = bezier3.length();
```

- [Playground: Drawing A Bezier Cubic Curve](https://playground.babylonjs.com/#EY3EW4) - Simple example of drawing a bezier cubic curve.

## Hermite Spline

http://en.wikipedia.org/wiki/Cubic_Hermite_spline

![Hermite Spline](https://doc.babylonjs.com/img/how_to/Mesh/hermite.webp)

```javascript
const hermite = BABYLON.Curve3.CreateHermiteSpline(p1, t1, p2, t2, nbPoints);
```

- **p1** : _Vector3_ the origin point,
- **t1** : _Vector3_ the origin tangent vector,
- **p2** : _Vector3_ the destination point,
- **t2** : _Vector3_ the destination tangent vector,
- **nbPoints** : _number_ the desired number of points in the final curve array.

This static method returns an instance of _Curve3_.  
Just use the Curve3 _getPoints()_ method to fill your array : _getPoints()_ returns an array of successive _Vector3_.  
The _length()_ method returns the curve length.

```javascript
const path = hermite.getPoints();
const l = hermite.length();
```

- [Playground: Drawing A Hermite Spline](https://playground.babylonjs.com/#P94GHL) - Simple example of drawing a Hermite Spline curve.

## Catmull-Rom Spline

https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline

![Wikibooks Cubic Hermite spline](https://upload.wikimedia.org/wikipedia/commons/1/1c/Finite_difference_spline_example.png)

```javascript
const nbPoints = 20;                     // the number of points between each Vector3 control points
const points = [vec1, vec2, ..., vecN];  // an array of Vector3 the curve must pass through : the control points
const closed = true;                     // closes the curve when true
const catmullRom = BABYLON.Curve3.CreateCatmullRomSpline(points, nbPoints, closed);
```

- **points** : _Vector3_ an array of Vector3 (the control points) the curve will pass through,
- **nbPoints** : _number_ the wanted curve number of points between each control point,
- **closed** : _boolean_ optional with default _false_; available from BJS V3.3; when true forms a closed curve.

This static method returns an instance of _Curve3_.  
Just use the Curve3 _getPoints()_ method to fill your array : _getPoints()_ returns an array of successive _Vector3_.  
The _length()_ method returns the curve length.

```javascript
const path = catmullRom.getPoints();
const l = catmullRom.length();
```

- [Playground: Drawing A Catmull-Rom Spline Open Curve](https://playground.babylonjs.com/#1AU0M4) - Simple example of drawing a Catmull-Rom Spline Open Curve.
- [Playground: Drawing A Catmull-Rom Spline Closed Curve](https://playground.babylonjs.com/#1AU0M4#18) - Simple example of drawing a Catmull-Rom Spline Closed Curve.

## Hermite Quaternion Spline

```javascript
BABYLON.Quaternion.Hermite(point0, tangent0, point1, tangent1, amount);
```

This allows the interpolation of quaternions for use in animation. As a quaternion is a 4D object, how can you visualize the Hermite quaternion spline used by the interpolation? By representing the hyperspline in 3D space.

This is achieved by mapping a rotation quaternion onto a 3D vector.

### The Math

What is needed is a function $f$ from rotation quaternions to 3D vectors of the form

$f(x, y, z, w) = (x_{v}, y_{v}, z_{v})$

For a rotation quaternion there are two things to note:

1. &nbsp; $x^2 + y^2 + z^2 + w^2 = 1$
2. &nbsp; $(x, y, z, w)$ and $(-x, -y, -z, -w)$ are equivalent.

The equivalence of $(x, y, z, w)$ and $(-x, -y, -z, -w)$ can be seen in the following

- [Playground: Equivalent Rotation Quaternions](https://playground.babylonjs.com/#9S6YUQ#3) - Scale by -1 produces equivalent rotation quaternions.

It follows that the set of rotation quaternions $(x, y, z, w)$ where $x^2 + y^2 + z^2 + w^2 = 1$ and $-1 \leq x, y, z, \leq 1$ and $0 \leq w \leq 1$ covers all possible rotations.

$x^2 + y^2 + z^2 + w^2 = 1$ and so  
$x^2 + y^2 + z^2 = 1 - w^2$ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Eq 1

Since $0 \leq w \leq 1$ then $0 < 1 \leq (1 + w) \leq 2$

Dividing Eq 1 by $(1 + w)^2$, which can never be $0$

$x^2 + y^2 + z^2 \over (1 + w)^2$ = $(1 - w^2) \over (1 + w)^2$ = $(1 - w) \over (1 + w)$

This gives the mapping

$f(x, y, z, w)$ = ($x \over (1 + w)$, $y\over (1 + w)$, $z\over (1 + w)$ )

Each rotation quaternion where $0 \leq w \leq 1$ is mapped onto one of a series of concentric spherical shells of radius, $r$,

$0 \leq r^2$ = $(1 - w) \over (1 + w)$ $\leq 1$.

![Hermite Quaternion Spline](https://doc.babylonjs.com/img/how_to/Mesh/quatshells.webp)

The center of the shells represents the rotation quaternion $(0, 0, 0, 1)$; the outer white shell is a unit sphere where $w = 0$.

The process can be reversed: the inverse function $f^{-1}$ returns the rotation quaternion from a point $(x, y, z)$ on the shells.

Since the radius, r, of the sphere at $(x, y, z)$ is such that $r^2 = x^2 + y^2 + z^2$ and

$r^2$ = $(1 - w) \over (1 + w)$ then

$w$ = $(1 - r^2) \over (1 + r^2)$ and

$1 + w$ = $2 \over (1 + r^2)$ and

$f^{-1}(x, y, z)$ = ($2x \over (1 + r^2)$, $2y \over (1 + r^2)$, $2z \over (1 + r^2)$, $(1 - r^2) \over (1 + r^2)$)

### Drawing

The following function will return a Curve3 within a unit sphere representing a Hermite quaternion spline in 3D space using the math above.

```javascript
const hermiteQuarternionSpline = (p1, t1, p2, t2, nbPoints) => {
  const hermite = new Array();
  const step = 1.0 / nbPoints;
  for (let i = 0; i <= nbPoints; i++) {
    const q = BABYLON.Quaternion.Hermite(p1, t1, p2, t2, i * step);
    q.normalize();
    if (q.w < 0) {
      q.scaleInPlace(-1);
    }
    const v = new BABYLON.Vector3(q.x / (1 + q.w), q.y / (1 + q.w), q.z / (1 + q.w));
    hermite.push(v);
  }
  return new BABYLON.Curve3(hermite);
};
```

- **p1** : _Quaternion_ the origin point,
- **t1** : _Quaternion_ the origin tangent vector,
- **p2** : _Quaternion_ the destination point,
- **t2** : _Quaternion_ the destination tangent vector,
- **nbPoints** : _number_ the wanted final curve number of points in the array.

**Warning**  
Using BABYLON.Quaternion.RotationAxis(axis, angle) to create any of p1, t1, p2, or t2 does not produce the expected results. Other ways of producing rotation quaternions, apart from creating them directly, should also be checked to ensure the resulting quaternion is in the range required for the mapping to work.

To produce a vector on the outer shell, you need a rotation quaternion with $w = 0$.

Take the rotation quaternion from

```javascript
new BABYLON.Quaternion(1, 1, 1, 0).normalize(); //giving (0.5774, 0.5774, 0.5774, 0) to 4 dp
```

However using

```javascript
BABYLON.Quaternion.RotationAxis(new BABYLON.Vector3(1, 1, 1), 0); // gives (0, 0, 0, 1)
```

and while this may be an equivalent quaternion, it places the vector at the center of the shells, not on the outer shell.  
**End Warning**

- [Playground: Hermite Quaternion Spline](https://playground.babylonjs.com/#4B0VBG) - Hermite quaternion spline represented in 3D space.

As it is difficult to visualize the spline from pure quaternions it would be useful if there was an editor to draw the representation of the spline in 3D space.

### A (Very) Basic Editor

- [Playground: Hermite Quaternion Editor](https://playground.babylonjs.com/#4B0VBG#1) - Hermite quaternion spline Editor 3D space.

This playground allows you to drag representations of the start (green) and end (red) quaternions within the unit sphere in 3D space. The representations of the start and end quaternion tangents (purple) are attached to the respective start and end controls. The tangents can also be dragged around the invisible sphere shells centered on the start and end controls. The shells, and hence the radius, can be adjusted using the up and down arrow keys (or w and x) for the selected control. While dragging or adjusting the radius, the camera is detached. The camera is reattached whenever dragging ends, and when using keys you can reattach it by pressing the spacebar.

The representation of the spline in 3D space is drawn as you adjust the controls. To apply the created Hermite quaternion spline to the box, click the animate button.

## Custom Curve3 Object

You can also make your own Curve3 object from a simple array of successive Vector3.  
Why would you do this and not just use the points to draw a line?  
Because the _Curve3_ object has a useful method, _continue()_, that allows you to place the start of one _Curve3_ at the end of another _Curve3_ without any calculations to match the start and end points of the curves.

### Example 1

Create an array of Vector3 along a simple sinus curve.

```javascript
const mySinus = [];
for (let i = 0; i < 30; i++) {
  mySinus.push(new BABYLON.Vector3(i, Math.sin(i / 10), 0));
}
const mySinusCurve = new BABYLON.Curve3(mySinus);
```

You would like to continue your _mySinus_ curve with a _bezier3_ curve and then join on a _bezier2_.

```javascript
const myFullCurve = mySinusCurve.continue(bezier3).continue(bezier2);
```

The _continue()_ method returns a new _Curve3_ object and leaves _mySinusCurve3_, _bezier3_ and _bezier2_ unchanged.

If you then need to draw the curve or use it for anything else, just get the array of points with the _getPoints()_ method. This method simply returns an array of successive _Vector3_.

```javascript
const path = myFullCurve.getPoints();
const extruded = BABYLON.MeshBuilder.ExtrudeShape("extrudedShape", { shape: shape, path: path, scale: 1, rotation: 0 }, scene);
```

If you need then to know the curve length, just use the _**length()**_ method.

```javascript
const l = myFullCurve.length();
```

- [Playground: Joining Curves](https://playground.babylonjs.com/#00JR7Z) - Simple example of joining curves.

### Example 2

Here is an example where a Hermite spline is used to smoothly close a concatenation of two Bezier curves. As the spline closes the curves, the first and last points of the open continued curve need to be read from the array.

- The first and last points of the concatenation are used as last and first point of the Hermite spline.
- The first and last segments of the concatenation are used as the last and first tangent vectors of the Hermite. Since these segments are quite small, they are scaled according to the concatenation _length_, so the longer the concatenation, the more curved the spline.

```javascript
// two concatened cubic Bezier
const cubicA = BABYLON.Curve3.CreateCubicBezier(vA0, vA1, vA2, vA3, 50);
const cubicB = BABYLON.Curve3.CreateCubicBezier(vB0, vB1, vB2, vB3, 50);
const continued = cubicA.continue(cubicB);

// initial Hermite values from continued first and last segments
const t = continued.length() / 2; // tangent scale factor
const points = continued.getPoints();
const p1 = points[points.length - 1]; // last continued point = first hermite point
const t1 = p1.subtract(points[points.length - 2]).scale(t); // last segment scaled = hermite tangent t1
const p2 = points[0]; // first continued point = last hermite point
const t2 = points[1].subtract(p2).scale(t); // first segment scaled = hermite tangent t2

const hermite = BABYLON.Curve3.CreateHermiteSpline(p1, t1, p2, t2, 50);
continued = continued.continue(hermite);

// finally drawing a smooth closed curve
const closedCurve = BABYLON.MeshBuilder.CreateLines("closed", { points: continued.getPoints() }, scene);
```

- [Playground: Closed Joined Curves](https://playground.babylonjs.com/#2GCEVH) - Simple example of closed joined curves.

The orange and yellow curves are the original Bezier curves.  
In light blue, these two curves are connected to each other, and a Hermite curve is also added to close the path.

## Further reading

- [How To Create Parametric Shapes](https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/param)
- [How To Use Path3D](https://doc.babylonjs.com/features/featuresDeepDive/mesh/path3D)
