BabylonJS - Ribbon


Advertisements

Ribbon takes an array of paths as input and draws lines along those paths. It uses complex logic to get the co-ordinates. In the example given below, we have used Bezier curve equation to draw the ribbon. Bezier curves are mostly used in 3D games to model the smooth curves. The curve needs control points and the curve is drawn along the control points.

Demo

<!doctype html>
<html>
   <head>
      <meta charset = "utf-8">
      <title>BabylonJs - Basic Element-Creating Scene</title>
      <script src = "babylon.js"></script>
      <style>
         canvas {width: 100%; height: 100%;}
      </style>
   </head>

   <body>
      <canvas id = "renderCanvas"></canvas>
      <script type = "text/javascript">
         var canvas = document.getElementById("renderCanvas");
         var engine = new BABYLON.Engine(canvas, true);
         
         var createScene  = function() {

            var scene = new BABYLON.Scene(engine);
            scene.clearColor = new BABYLON.Color3(0.8, 0.8, 0.8);
            
            var camera = new BABYLON.ArcRotateCamera("Camera", 3 *Math.PI / 2, Math.PI / 2, 50, BABYLON.Vector3.Zero(), scene);
            camera.attachControl(canvas, false);

            // lights
            var light = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);
            light.groundColor = new BABYLON.Color3(0.2, 0.2, 0.5);
            light.intensity = 0.6;


            var light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(-20, 0, -20), scene);
            light2.diffuse = BABYLON.Color3.White();
            light2.specular = BABYLON.Color3.Green();
            light2.intensity = 0.6;

            // material
            var mat = new BABYLON.StandardMaterial("mat1", scene);
            mat.alpha = 1.0;
            mat.diffuseColor = new BABYLON.Color3(0.5, 0.5, 1.0);
            //mat.backFaceCulling = false;
            mat.wireframe = true;

            // cubic B├ęzier function
            // cubicBezier(vector3Origin, vector3Control1, vector3Control2, vector3Destination, segmentNumber)
            var cubicBezier = function(v0, v1, v2, v3, nb) {
               var bez = [];
               var step = 1 / nb;
               var equation = function(t, val0, val1, val2, val3) {
                  var res = (1 -t)*(1-t)*(1-t) * val0 + 3 * t * (1-t)*(1-t) * val1 + 3 * t*t *(1-t) * val2 + t*t*t * val3;
                  return res;
               };

               for(var i = 0; i <= 1; i += step) {
                  bez.push( new BABYLON.Vector3(equation(i, v0.x, v1.x, v2.x, v3.x), equation(i, v0.y, v1.y, v2.y, v3.y), equation(i, v0.z, v1.z, v2.z, v3.z)) );
               }
               bez.push(v3);
               return bez;
            };

            var populatePath = function(p) {
               var pi2 = Math.PI * 2;
               var i = p / 25 ;
               var path = cubicBezier( new BABYLON.Vector3(3 * Math.cos(pi2 * i),-10, 3 * Math.sin(pi2 *i)),
               new BABYLON.Vector3(12 * Math.cos(pi2 * i), p/5 ,10 * Math.sin(pi2 * i)),
               new BABYLON.Vector3(15 * Math.cos(pi2 * i), p/2 ,8 * Math.sin(pi2 * i)),
               new BABYLON.Vector3(3 * Math.cos(pi2 * i), 10, 3 * Math.sin(pi2 * i)), 50);
               return path;
            };

            // path visualizer helper
            var showPath = function(path, scene) {
               var line = BABYLON.Mesh.CreateLines("line", path, scene )
            };

            var paths = [];
            for (var p = 0; p < 20; p++) {
               paths[p] = populatePath(p); 
               showPath(paths[p], scene);
            }

            var ribbon = new BABYLON.Mesh.CreateRibbon("ribbon", paths, false, false, null, scene);
            ribbon.material = mat;

            scene.registerBeforeRender(function() {
               light2.position = camera.position;
            });
            return scene;
         };
         var scene = createScene();
         engine.runRenderLoop(function() {
            scene.render();
         });
      </script>
   </body>
</html>

Output

The above line of code generates the following output −

Ribbon

Syntax

var ribbon = new BABYLON.Mesh.CreateRibbon("ribbon", paths, false, false, null, scene);

The ribbon uses an array of path in x,y and z direction.TheBezeir curve equation used above is calculated here −

var cubicBezier = function(v0, v1, v2, v3, nb) {
   var bez = [];
   var step = 1 / nb;
   var equation = function(t, val0, val1, val2, val3) {
      var res = (1 -t)*(1-t)*(1-t) * val0 + 3 * t * (1-t)*(1-t) * val1 + 3 * t*t *(1-t) * val2 + t*t*t * val3;
      return res;
   };
   
   for(var i = 0; i <= 1; i += step) {
      bez.push( new BABYLON.Vector3(equation(i, v0.x, v1.x, v2.x, v3.x), equation(i, v0.y, v1.y, v2.y, v3.y), equation(i, v0.z, v1.z, v2.z, v3.z)) );
   }
   
   bez.push(v3);
   return bez;
};

Bezier Curve Equation

var res = (1 -t)*(1-t)*(1-t) * val0 + 3 * t * (1-t)*(1-t) * val1 + 3 * t*t *(1-t) * val2 + t*t*t * val3;
babylonjs_parametric_shapes.htm
Advertisements