Table of contents

Here you'll find almost everything to understand how the Ribbon object works and how to play with it.

*series of paths*
*paths with different lengths*

It's not mandatory that all paths have the same length.

In this example, *path2* and *path3* are longer than *path1* and *path4* : https://www.babylonjs-playground.com/#88AZQ -

As you can see, the final ribbon adjust to different lengths. The rule is they all start from first path points and each intermediate ribbon then stops at first of its both constituting paths end.

There is also no incidence on light reflection for ribbon with different length paths : https://www.babylonjs-playground.com/#88AZQ#1 -

Therefore you

This is due to the fact that the nested ribbon texturing algorithm only knows how to deal with a unique length for all paths. Indeed, as a ribbon is a parametric shape, so unpredictable, it's assumed that we could unwrap a volumic ribbon (so each one of its paths) onto a full rectangular image and this assumption keeps consistency only with the same length for all paths.

So it's not mandatory that all the ribbon paths have the same length, but it is hardly recommended.

The best way to emulate different lengths for some parts of your mesh is then to simply use many ribbons.

The ribbon mesh provides two ways to automatically close an unclosed shape.

*closeArray*parameter : this will add an extra unit ribbon between the last path and the first path of your*pathArray*.*closePath*parameter : this will join the last and first points of each*path*in your*pathArray*.

Here's an unclosed ribbon : https://www.babylonjs-playground.com/#3XMWZ#1 -

```
var ribbon = BABYLON.Mesh.CreateRibbon("ribbon", paths, false, false, 0, scene, false, BABYLON.Mesh.BACKSIDE);
```

Don't mind about how it is mathematically built. This is not the topic.

The same closed ribbon with *closeArray* set to *true* : https://www.babylonjs-playground.com/#3XMWZ#2 -

```
var ribbon = BABYLON.Mesh.CreateRibbon("ribbon", paths, true, false, 0, scene, false, BABYLON.Mesh.BACKSIDE);
```

As you can see, when rotating the camera, there is no edge on the ribbon surface. The light reflects continuously.

If we now apply a texture to this automatically closed ribbon : https://www.babylonjs-playground.com/#3XMWZ#3 -

You can notice that the texture isn't stretched on the surface added by the automatic closing.

The reason of this behavior is that, with ribbon *closeXXX* parameters, priority is given on normals (the tools that compute light reflection) over textures.

If you don't care about continuous light reflection but you do want your texture to be stretched along the whole surface, you just have to forget automatic closing (*closeArray* then set to *false*) and close the ribbon by yourself.

A simple way is just to re-push the first *path* at the end of the *pathArray*

```
paths.push(paths[0]);
var ribbon = BABYLON.Mesh.CreateRibbon("ribbon", paths, false, false, 0, scene, false, BABYLON.Mesh.BACKSIDE);
```

Example : https://www.babylonjs-playground.com/#3XMWZ#4 -

Obviously, the same rules and workarounds apply to the *closePath* parameter.

automatically *path* closed : https://www.babylonjs-playground.com/#3XMWZ#5 -

then textured : https://www.babylonjs-playground.com/#3XMWZ#6 -

The Ribbon is very adapted to elaborated maths computed meshes.

You can easily start from an equation to get a full volumic complex shape.

There are many ways to do it.

If you don't feel at ease with maths, here is a way to start :

We just set points in space. These points have got each a set of three coordinates : x, y and z.

We call here these points *Vector3*.

When we want to design a curve or a path in space, we need to get a collection of successive *Vector3*.

We can't have an infinity of points.

So we define a path with a certain number of *Vector3*. The more *Vector3*, the more smooth the curve and the more computations too.

So when you want your path to follow a mathematical curve, you need to compute each path *Vector3* coordinates.

You could choose a known math curve in wikipedia or dedicated sites (http://en.wikipedia.org/wiki/List_of_curves , http://www.mathcurve.com/courbes2d/courbes2d.shtml , http://www.uiowa.edu/~examserv/mathmatters/tutorial_quiz/geometry/commoncurves.html, etc) or, when you feel more comfortable, create you own.

As you can see, curve equations are often like this : *f(x, y) = 0* or like this : *y = f(x)*.

This means *y* is expressed in function of *x*.

This kind of equation is called a *cartesian equation*. It is probably the most used among mathematicians, but it won't help us a lot because we need to compute *x* and *y* (and *z*) simultaneously to set each *Vector3*.

So we will prefer the *parametric equations*.

In a *parametric equation* each different coordinate is defined in function of a parameter *k* :

*x = fct1(k)*

*y = fct2(k)*

*z = fct3(k)*

So if you are given a *cartesian equation*, it is quite almost possible to translate it in a *parametric equation*.

example with a parabola : y = x²*the cartesian equation y = x * x* will give the *parametric equation :*

*x = k*

*y = k * k*

You then give *k* values from -20 to 20 for example and you get your 40 successive *Vector3* on the parabola. Easy, isn't it ?

You now know the way to fill a path with successive *Vector3* along a math curve.

Well, we just learnt how to fill a path but a Ribbon needs many paths (okay, we can still construct a ribbon with a single path too, but it's more complex), so how do we add different paths as there is no real interest to add many times the same path ?

It's quite easy once you've got your parametric equation.

Let's get into javascript now.

Your former parametric equation could be this way :

```
var path = [];
for (var k = -20; k <= 20; k++) {
var x = k;
var y = k * k;
var z = 0;
path.push(new BABYLON.Vector3(x, y, z));
}
```

Right ?

https://www.babylonjs-playground.com/#1HSC2O -

Let's now imagine, you create the same path array 10 times on the z-axis with *z = t* :

```
var paths = [];
for (var t = 0; t < 10; t++) {
var path = [];
for (var k = -20; k <= 20; k++) {
var x = k;
var y = k * k;
var z = t;
path.push(new BABYLON.Vector3(x, y, z));
}
paths.push(path);
}
```

What do we get now ?

https://www.babylonjs-playground.com/#1HSC2O#1 -

An array

Just what is needed to create a ribbon : https://www.babylonjs-playground.com/#1HSC2O#2 -

If you now change slightly each path equation so they aren't all similar, say, by dividing

```
var paths = [];
for (var t = 1; t < 10; t++) {
var path = [];
for (var k = -20; k <= 20; k++) {
var x = k;
var y = k * k / t;
var z = t;
path.push(new BABYLON.Vector3(x, y, z));
}
paths.push(path);
}
```

You immediatly get a set of different paths along the z-axis : https://www.babylonjs-playground.com/#1HSC2O#8 -

So a more complex ribbon : https://www.babylonjs-playground.com/#1HSC2O#9 -

At last, if we change a bit *x* and *z* variation to scale the curve, we can get a nice parabolic shape :

```
var paths = [];
for (var t = 1; t < 10; t++) {
var path = [];
for (var k = -20; k <= 20; k++) {
var x = k * 8;
var y = k * k / t;
var z = t * 50;
path.push(new BABYLON.Vector3(x, y, z));
}
paths.push(path);
}
```

https://www.babylonjs-playground.com/#1HSC2O#10 -

Quick fun ?

multiply

or funnier : https://www.babylonjs-playground.com/#1HSC2O#12 -

I couldn't stop playing ...

An easy way to create math computed shapes is so :

- to choose a 2D math curve,
- to get its parametric equation,
- to fill an array with
*Vector3*computed with a simple*for*loop iterating on the number of points wanted (set them in a 2D plane to start, with z = 0 for instance), - to check your curve with
*BABYLON.Mesh.CreateLines("name", yourArray, scene)*, - to derivate your first curve by varying
*x*or*y*and iterating on*z*since adding each derivated path into a*paths*array, - to check again with
*BABYLON.Mesh.CreateLines("name", yourArray, scene)*on each*z*iteration, - to finally build your ribbon with the
*paths*array.

The Ribbon is very versatile. So you can redo every BabylonJS basic shapes.

Why would you want to do this ?

Well, you probably don't. There is no need to re-invent the wheel. But you could need to model your own shape which derivates from one of the basic shapes.

The main rule should be :

- if you need a basic shape as it stands, then use the provided BJS basic shapes.
- if you need a shape made up of many basic shapes, then use Constructive Solid Geometry or merge provided BJS basic shapes.
- if you need a computed shape having a symetry axis, then use the Tube mesh or the extrusion, which don't require many maths.
- if you need something else, then use the Ribbon itself... and your maths skills.

Let's try here to redo a sphere and then to modify it into something different.

As you've seen in the former part, you need to create many paths to build a ribbon. For a sphere, you can imagine that you stack many circles, each circle being a path.

To create a circle, you just set points at *x = sin(angle)* and *z = cos(angle)* and give *angle* some values between 0 and 2 x PI.

```
var pi2 = Math.PI * 2;
var step = pi2 / 60; // we want 60 points
for (var i = 0; i < pi2; i += step ) {
var x = radius * Math.sin(i);
var z = radius * Math.cos(i);
var y = 0;
path.push( new BABYLON.Vector3(x, y, z) );
}
path.push(path[0]); // to close the circle
```

demo : https://www.babylonjs-playground.com/#E6IX1#1 -

Now, you add circles along the y-axis, making the radius evolving with another angle *p* varying from the sphere south pole -PI / 2 to its north pole +PI /2. These circles (path) are stored in an array called *paths* :

```
var radius = 10;
var tes = 60;
var pi2 = Math.PI * 2;
var step = pi2 / tes;
var paths = [];
for (var p = -Math.PI / 2; p < Math.PI / 2; p += step / 2) {
var path = [];
for (var i = 0; i < pi2; i += step ) {
var x = radius * Math.sin(i) * Math.cos(p);
var z = radius * Math.cos(i) * Math.cos(p);
var y = radius * Math.sin(p);
path.push( new BABYLON.Vector3(x, y, z) );
}
path.push(path[0]);
paths.push(path);
}
```

demo : https://www.babylonjs-playground.com/#E6IX1 -

Let's apply a ribbon to these paths : https://www.babylonjs-playground.com/#E6IX1#2 -

You get (almost) a sphere.

To get a nice full sphere, you need to complete the missing point at north pole and set the ribbon

```
var lastPath = [];
for (var j = 0; j < pi2; j += step ) {
lastPath.push( new BABYLON.Vector3(0, radius, 0) );
}
paths.push(lastPath);
var sphere = BABYLON.Mesh.CreateRibbon("sph", paths, false, true , 0, scene);
```

demo : https://www.babylonjs-playground.com/#E6IX1#3 -

Pretty much maths and iterations o far to get a simple sphere, isn't it ?

This is why you should really use the BJS provided sphere if you only want a sphere !

But don't worry, all those efforts so far aren't vain. From now, let's the magic happens with only little changes ...

Remember : the *for* loop iterating on *p* is for the south to north pole angle. What if you don't increment *p* until PI / 2 but stop before, say at PI /2 - 1.5 :

```
for (var p = -Math.PI / 2; p < Math.PI / 2 - 1.5; p += step / 2) {
```

demo : https://www.babylonjs-playground.com/#E6IX1#4 -

Quite easy. You just derivated the initial sphere into another shape you wouldn't have got another way.

Now, you can keep the original pole angle limit PI / 2 but add a new behavior : if a certain angle limit is reached, then inverse the y radius around this limit.

```
var yRadius;
var limit = Math.PI / 2 - 1;
for (var p = -Math.PI / 2; p < Math.PI / 2; p += step / 2) {
var path = [];
yRadius = p < limit ? Math.sin(p) : 2 * Math.sin(limit) - Math.sin(p) ;
for (var i = 0; i < pi2; i += step ) {
var x = radius * Math.sin(i) * Math.cos(p);
var z = radius * Math.cos(i) * Math.cos(p);
var y = radius * yRadius;
path.push( new BABYLON.Vector3(x, y, z) );
}
paths.push(path);
}
```

demo : https://www.babylonjs-playground.com/#E6IX1#5 -

Let's change the initial *for* loop limits now :

```
for (var p = -Math.PI / 2 + 0.5; p < Math.PI / 2 - 0.5; p += step / 2) {
```

demo : https://www.babylonjs-playground.com/#E6IX1#6 -

Well, is this still a sphere ?

Let's close the ribbon :

```
var sphere = BABYLON.Mesh.CreateRibbon("sph", paths, true, true , 0, scene);
```

demo : https://www.babylonjs-playground.com/#E6IX1#7 -

Well, it's no longer a sphere, but a symetric shape you could probably have got in a simpler way with a Tube mesh or with CSG ... or not.

Since you wrote the initial sphere maths code, you've added until now very few changes to get this derivated shape. Too symetric, not enough, ok ? let's morph it once more so you get out the CSG or Tube way : let's moderate

```
for (var i = 0; i < pi2; i += step ) {
var x = radius * Math.sin(i) * Math.cos(p) * Math.cos(i / 6);
var z = radius * Math.cos(i) * Math.cos(p);
var y = radius * yRadius;
path.push( new BABYLON.Vector3(x, y, z) );
}
```

demo : https://www.babylonjs-playground.com/#E6IX1#8 -

You are now in the real Ribbon world ! Want more ? let's moderate

```
for (var i = 0; i < pi2; i += step ) {
var x = radius * Math.sin(i) * Math.cos(p) * Math.cos(i / 6);
var z = radius * Math.cos(i) * Math.cos(p) * 2;
var y = radius * yRadius * Math.cos(i * 2);
path.push( new BABYLON.Vector3(x, y, z) );
}
```

demo : https://www.babylonjs-playground.com/#E6IX1#9 -

*make many different computed or manual pathArrays, then concatenate them*

*edition in progress*