BabylonJS - Morph a Mesh



Morphing changes the shape of an object to another by some means of transition. We have seen the updatable parameter for the shapes; the parameter is set to false otherwise. For morphing, it is set to true and the mesh is updated to change the shape.

The demo given below shows lines, ribbon morphed.

Demo with Lines

<!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( .5, .5, .5);
            
            var camera = new BABYLON.ArcRotateCamera("camera1",  0, 0, 0, new BABYLON.Vector3(0, 0, -0), scene);
            camera.setPosition(new BABYLON.Vector3(0, 0, -100));
            camera.attachControl(canvas, true);
            
            var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 0.5, 0), scene);
            light.intensity = 0.7;
            
            var pl = new BABYLON.PointLight("pl", new BABYLON.Vector3(0, 0, 0), scene);
            pl.diffuse = new BABYLON.Color3(1, 1, 1);
            pl.specular = new BABYLON.Color3(1, 0, 0);
            pl.intensity = 0.95;

            // lines creation
            var sinpath = [];
            for(var i = -20; i < 20; i++) {
               var x = i;
               var y = 0;
               var z = 0;
               sinpath.push(new BABYLON.Vector3(x, y, z));
            }
            var sinmesh = BABYLON.Mesh.CreateLines("lines", sinpath, scene, true);

            // lines creation
            var cospath = [];
            for(var i = 20; i > -20; i--) {
               var x = i;
               var y = 0;
               var z = 0;
               cospath.push(new BABYLON.Vector3(x, y, z));
            }
            console.log(cospath);
            var cosmesh = BABYLON.Mesh.CreateLines("lines", cospath, scene, true);

            var updatePath = function(sinpath, k) {
               for (var i = 0; i < sinpath.length; i++) {
                  var x = sinpath[i].x;
                  var z = sinpath[i].z;
                  var y = 10 * Math.sin(i / 3 + k); // using sin on y-axis
                  sinpath[i].x = x;
                  sinpath[i].y = y;
                  sinpath[i].z = z;
               }
            };

            var updatePath1 = function(cospath, k) {
               for (var i = 0; i < cospath.length; i++) {
                  var x = cospath[i].x;
                  var z = cospath[i].z;
                  var y = 10 * Math.cos(i / 3 + k); //using cos on y -axis
                  cospath[i].x = x;
                  cospath[i].y = y;
                  cospath[i].z = z;
               }
            };

            // morphing
            var k = 0;
            scene.registerBeforeRender(function() {
               updatePath(sinpath, k);
               updatePath1(cospath, k);
               //updateLines(mesh, path);
               sinmesh = BABYLON.Mesh.CreateLines(null, sinpath, null, null, sinmesh);
               cosmesh = BABYLON.Mesh.CreateLines(null, cospath, null, null, cosmesh);
               k += 0.10;			
               pl.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 −

Morph Mesh

Explanation

The lines are updated and morphed using sin and cos angles.

2 lines are created from path -20 to 20. Later the lines are updated using the sin and cos on the y axis.

The mesh using the updatable option is set to true so that it can be updated later. Consider the following example to understand this −

var sinmesh = BABYLON.Mesh.CreateLines("lines", sinpath, scene, true);

Later all the values are set to null and only the path is updated. Consider the following example to understand this.

sinmesh = BABYLON.Mesh.CreateLines(null, sinpath, null, null, sinmesh);

The last param is the name of the mesh used.

Morph Ribbon

Let us now see how a morph ribbon is created.

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( .5, .5, .5);
            var camera = new BABYLON.ArcRotateCamera("camera1",  0, 0, 0, new BABYLON.Vector3(0, 0, -0), scene);
            camera.setPosition(new BABYLON.Vector3(0, 0, -100));
            camera.attachControl(canvas, true);
            
            var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 0.5, 0), scene);
            light.intensity = 0.7;
            
            var pl = new BABYLON.PointLight("pl", new BABYLON.Vector3(0, 0, 0), scene);
            pl.diffuse = new BABYLON.Color3(1, 1, 1);
            pl.specular = new BABYLON.Color3(1, 0, 0);
            pl.intensity = 0.95;
            
            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;

            // path function
            var pathFunction = function(k) {
               var path = []; 
               for (var i = 60; i > 0; i--) {
                  var x =  i - 30;
                  var y = 0;
                  var z = k;
                  path.push(new BABYLON.Vector3(x, y, z));
               }
               return path;
            };

            // ribbon creation
            var sideO = BABYLON.Mesh.BACKSIDE;
            var pathArray = [];
            for (var i = -20; i < 20; i++) {
               pathArray.push(pathFunction(i * 2));
            }
            
            console.log(pathArray);
            var mesh = BABYLON.Mesh.CreateRibbon("ribbon", pathArray, false, false, 0, scene, true, sideO);
            mesh.material = mat;

            var updatePath = function(path) {
               for (var i = 0; i < path.length; i++) {
                  var x = path[i].x;
                  var z = path[i].z;
                  var y = -20 * Math.sin(i/ 10);
                  path[i].x = x;
                  path[i].y = y;
                  path[i].z = z;
               }
            };
            
            // animation
            scene.registerBeforeRender(function() {		
               for(var p = 0; p < pathArray.length; p++) {
                  updatePath(pathArray[p]);
               }
               mesh = BABYLON.Mesh.CreateRibbon(null, pathArray, null, null, null, null, null, null, mesh);
               pl.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 −

Morph Ribbon

Explanation

For Ribbon, first the path is created using the following command −

var mesh = BABYLON.Mesh.CreateRibbon("ribbon", pathArray, false, false, 0, scene, true, sideO);

The orientation is changed to var sideO = BABYLON.Mesh.BACKSIDE; from defaulside.

The mesh is kept updatable. The pathArray is changed and updated to ribbon mesh again using the following command −

mesh = BABYLON.Mesh.CreateRibbon(null, pathArray, null, null, null, null, null, null, mesh);

All the values passed to the ribbon are null, only the updated pathArray is changed and sent.

babylonjs_mesh.htm
Advertisements