Drawing Curves
How To Draw Curves
If you want to draw a circular path then it is easy enough to generate the points, in the XY plane, for this using
var path = [];for(var theta = 0; theta < 2 * Math.PI; theta +=deltaTheta ) {path.push(new BABYLON.Vector3(radius * Math.cos(theta), radius * Math.sin(theta), 0));
When you are of a mind to do it 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
var curve = BABYLON.Curve3.Create.CURVETYPE(parameters);
Quadratic Bezier Curve
http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Quadratic_curves
var 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.
var path = bezier2.getPoints();var l = bezier2.length();
Cubic Bezier curve
http://en.wikipedia.org/wiki/B%C3%A9zier_curve# Higher-order_curves
var 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 wanted final curve number of points in the 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.
var path = bezier3.getPoints();var l = bezier3.length();
Hermite Spline
http://en.wikipedia.org/wiki/Cubic_Hermite_spline
var 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 wanted final curve number of points in the 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.
var path = hermite.getPoints();var l = hermite.length();
Catmull-Rom Spline
https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline
var nbPoints = 20; // the number of points between each Vector3 control pointsvar points = [vec1, vec2, ..., vecN]; // an array of Vector3 the curve must pass through : the control pointsvar closed = true; // closes the curve when truevar 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.
var path = catmullRom.getPoints();var l = catmullRom.length();
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, the continue() method, that allows you place the start of one Curve3 onto 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.
var mySinus = [];for (var i = 0; i < 30; i++) {mySinus.push( new BABYLON.Vector3(i, Math.sin(i / 10), 0) );}var mySinusCurve = new BABYLON.Curve3(mySinus);
You would like to continue your mySinus curve with a bezier3 curve and then join on a bezier2.
var 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 whatever you want you just get the array of points with the getPoints() method. This method simply returns an array of successive Vector3.
var path = myFullCurve.getPoints();var extruded = BABYLON.Mesh.ExtrudeShape("extrudedShape", shape, path, 1, 0, scene);
If you need then to know the curve length, just use the length() method.
var l = myFullCurve.length();
Example 2
Here is an example where a Hermite Spline is used to close smoothly a concatenation of two Bezier curves. As the spline is closing 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 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.
// two concatened cubic Beziervar cubicA = BABYLON.Curve3.CreateCubicBezier(vA0, vA1, vA2, vA3, 50);var cubicB = BABYLON.Curve3.CreateCubicBezier(vB0, vB1, vB2, vB3, 50);var continued = cubicA.continue(cubicB);// initial Hermite values from continued first and last segmentsvar t = continued.length() / 2; // tangent scale factorvar points = continued.getPoints();var p1 = points[points.length - 1]; // last continued point = first hermite pointvar t1 = (p1.subtract(points[points.length - 2])).scale(t); // last segment scaled = hermite tangent t1var p2 = points[0]; // first continued point = last hermite pointvar t2 = (points[1].subtract(p2)).scale(t); // first segment scaled = hermite tangent t2var hermite = BABYLON.Curve3.CreateHermiteSpline(p1, t1, p2, t2, 50);continued = continued.continue(hermite);// finally drawing a smooth closed curvevar closedCurve = BABYLON.Mesh.CreateLines("closed", continued.getPoints(), scene);
The orange and yellow curves are the original Bezier curves.
In light blue, these two curves are continued by each other and a hermite curve is also added in continuation to close the path.