English 中文(简体)
BabylonJS - Mesh
  • 时间:2024-10-18

BabylonJS - Mesh


Previous Page Next Page  

In this chapter, we will learn to create different shapes using the mesh builder. We have already learnt how to create shapes in one of our previous chapters.

The difference is that with meshbuilder gives you the flexibipty to add color, images to the shapes.

CreateBox using MeshBuilder

Let us now see how to create box using MeshBuilder.

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, 0, 1);
            
            var camera = new BABYLON.ArcRotateCamera("Camera", 1, 0.8, 10, new BABYLON.Vector3(0, 0, 0), scene);
            camera.attachControl(canvas, true);

            var pght = new BABYLON.HemisphericLight("pght1", new BABYLON.Vector3(0, 1, 0), scene);
            pght.intensity = 0.7;

            var pl = new BABYLON.PointLight("pl", BABYLON.Vector3.Zero(), scene);
            pl.diffuse = new BABYLON.Color3(1, 1, 1);
            pl.specular = new BABYLON.Color3(1, 1, 1);
            pl.intensity = 0.8;

            var mat = new BABYLON.StandardMaterial("mat1", scene);
            mat.alpha = 1.0;
            mat.diffuseColor = new BABYLON.Color3(0, 1, 0);
            
            var texture = new BABYLON.Texture("images/cube.png", scene);
            mat.diffuseTexture = texture;

            var hSpriteNb =  3;  // 3 sprites per raw
            var vSpriteNb =  2;  // 2 sprite raws

            var faceUV = new Array(6);
            for (var i = 0; i < 6; i++) {
               faceUV[i] = new BABYLON.Vector4(i/hSpriteNb, i/vSpriteNb, (i+1)/hSpriteNb, (i+1)/vSpriteNb);
            }

            var options = {
               width: 1.5,
               height: 1.5,
               depth: 1.5,
               faceUV: faceUV
            };

            var box = BABYLON.MeshBuilder.CreateBox("box", options, scene);
            box.material = mat;

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

Output

The above pne of code generates the following output −

MeshBuilder CubeBox

For the above example, we have used a sprite image as shown below. It has horizontally 3 Colums and vertically 2 rows.

Cube

In this demo, we have used an image called cube.png. The images are stored in images/ folder locally and are also pasted below for reference. Please note cube.png is a sprite image, a sprite image is a collection of images. We wanted to show the image on a cube so wanted all the sides of the cube together. You can also download similar sprite images of your choice and use in the demo pnk.

The createBox builder gives you options for the sizes.

For example,

var box = BABYLON.MeshBuilder.CreateBox("box", options, scene);

Demo

var hSpriteNb =  3;  // 3 sprites per raw ie colums horizontally as shown in the image

var vSpriteNb =  2;  // 2 sprite raws as shown in the image above.

var faceUV = new Array(6); // the cube has 6 sides so creating array for same.
for (var i = 0; i < 6; i++) {
   faceUV[i] = new BABYLON.Vector4(i/hSpriteNb, i/vSpriteNb, (i+1)/hSpriteNb, (i+1)/vSpriteNb);
}

var options = {
   width: 1.5,
   height: 1.5,
   depth: 1.5,
   faceUV: faceUV
};

This is called applying textures to the meshbuilder using the createBox method.We have used the image cube.png which has horizontally 3 colums and vertically 2 rows.The cube or box has 6 sides.

To apply textures we are using the options parameter.For example,

Var box = BABYLON.MeshBuilder.CreateBox ( box , options, scene);

We have defined an array called faceUV with size as 6 which are the sides of the cube. This array will always have Vector4 elements. Each Vector4(x, y, z, w) will be defined as follows −

    x = Ubottom

    y = Vbottom

    z = Utop

    w = Vtop

The vectorsare in the range [0, 1]. Ubottom and Vbottom are the 2D coordinates of the bottom left point of where the texture crop starts. Utop, Vtop are the top right points where the texture crop ends.

var hSpriteNb =  3;  // 3 sprites per raw
var vSpriteNb =  2;  // 2 sprite raws

var faceUV = new Array(6);
for (var i = 0; i < 6; i++) {
   faceUV[i] = new BABYLON.Vector4(i/hSpriteNb, i/vSpriteNb, (i+1)/hSpriteNb, (i+1)/vSpriteNb);
}

Suppose the default texture, i.e., the image given is appped to all the faces of the box. If you want to change only 1 face or 1 side of the box, you can directly assign the values as shown below −

var hSpriteNb =  3;  // 3 sprites per raw
var vSpriteNb =  2;  // 2 sprite raws

var faceUV = new Array(6);
faceUV[4] = new BABYLON.Vector4(0, 0, 1/hSpriteNb, 1/vSpriteNb);

Example

<!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, 0, 1);
            
            var camera = new BABYLON.ArcRotateCamera("Camera", 1, 0.8, 10, new BABYLON.Vector3(0, 0, 0), scene);
            camera.attachControl(canvas, true);

            var pght = new BABYLON.HemisphericLight("pght1", new BABYLON.Vector3(0, 1, 0), scene);
            pght.intensity = 0.7;

            var pl = new BABYLON.PointLight("pl", BABYLON.Vector3.Zero(), scene);
            pl.diffuse = new BABYLON.Color3(1, 1, 1);
            pl.specular = new BABYLON.Color3(1, 1, 1);
            pl.intensity = 0.8;

            var mat = new BABYLON.StandardMaterial("mat1", scene);
            mat.alpha = 1.0;
            mat.diffuseColor = new BABYLON.Color3(0.8, 0.8, 0.8);
            
            var texture = new BABYLON.Texture("images/3d.png", scene);
            mat.diffuseTexture = texture;

            var hSpriteNb =  3;  // 3 sprites per raw
            var vSpriteNb =  2;  // 2 sprite raws

            var faceUV = new Array(6);
            faceUV[4] = new BABYLON.Vector4(0, 0, 1/hSpriteNb, 1/vSpriteNb);

            var options = {
               width:3,
               height:3,
               depth: 3,
               faceUV:faceUV
            };

            var box = BABYLON.MeshBuilder.CreateBox("box", options, scene);
            box.material = mat;

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

Output

The above pne of code generates the following output −

Textturepahse4

In this demo, we have used an image called 3d.png. The images are stored in images/ folder locally and are also pasted below for reference. Please note 3d.png is a sprite image; a sprite image is a collection of images. We wanted to show the image on a cube with all the sides of the cube together. You can also download similar sprite images of your choice and use in the demo pnk.

Texture used for box − images/3d.png

3d

MeshCypnder

In this section, we will see how to create MeshCypnder.

To create MeshCypnder, you need to use the class BABYLON.MeshBuilder.CreateCypnder.

The parameters for the class are as follows −

var meshcypnder = BABYLON.MeshBuilder.CreateCypnder("meshcypnder", {
   height: 3,
   diameter: 35,
   tessellation: 52
}, scene);

The difference between CreateCypnder using mesh and meshbuilder is - you can use options in meshbuilder. Right now we are using height, diameter and tessellation as the options to be passed to the cypnder. We are using standard material with wireframe as the material for this mesh. Check the output in the browser and see the cypnder. You can use similar structure in your game as a wheel rotating in the scene.

Demo

<!doctype html>
<html>
   <head>
      <meta charset = "utf-8">
      <title>Babylon.js demo - Mesh Builder</title>
      <script src = "babylon.js"></script>
      <style>
         html,body,canvas { margin: 0; padding: 0; width: 100%; height: 100%; font-size: 0; }
      </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", -Math.PI / 6, 1.3, 40, new BABYLON.Vector3(0, -3, 0), scene);
            
            var pght = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);

            var mat = new BABYLON.StandardMaterial("mat", scene);
            mat.diffuseColor = new BABYLON.Color3(0.1, .5, 0);
            mat.specularColor = new BABYLON.Color3(0, 0, 0);
            mat.wireframe = true;

            var meshcypnder = BABYLON.MeshBuilder.CreateCypnder("meshcypnder", {
               height: 3,
               diameter: 35,
               tessellation: 52
            }, scene);

            meshcypnder.material = mat;
            meshcypnder.position = new BABYLON.Vector3(0, 0, 0);

            scene.activeCamera.attachControl(canvas);
            return scene;
         };
         
         var scene = createScene();
         engine.runRenderLoop(function() {
            scene.render();
         });
      </script>
   </body>
</html>

Output

The above pne of code generates the following output −

Meshcypnder

A number of shapes created with mesh builder will now be used together in one demo. The shapes covered in the demo pnk below are psted in subsequent sections.

BabylonJS – Mesh Intersection and Point

Mesh Intersection in games is important as you know what needs to be done when 2 objects intersect in a game. The same concept is explained in demo below on the event that needs to be captured when the meshes intersect.

In the demo given below, we have covered the following two concepts −

    Intersect Mesh

    Intersect Point

<!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(1, 1, 1);
            
            var camera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 20, new BABYLON.Vector3(0, 0, 0), scene);
            camera.attachControl(canvas, true);

            var matcone = new BABYLON.StandardMaterial("mat1", scene);
            matcone.alpha = 1.0;
            matcone.diffuseColor = new BABYLON.Color3(0, 0, 0);
            matcone.wireframe = true;

            var cone = BABYLON.MeshBuilder.CreateCypnder("cone", {height : 10, diameterTop: 10,diameterBottom:10, tessellation: 5}, scene);
            cone.position= new BABYLON.Vector3(12,1,0);
            cone.material = matcone;	

            var balloon1 = BABYLON.Mesh.CreateSphere("balloon1",5, 1.0, scene);
            var balloon2 = BABYLON.Mesh.CreateSphere("balloon2", 5, 1.0, scene);
            var balloon3 = BABYLON.Mesh.CreateSphere("balloon3", 5, 1.0, scene);
            
            balloon1.material = new BABYLON.StandardMaterial("matBallon", scene);
            balloon2.material = new BABYLON.StandardMaterial("matBallon", scene);
            balloon3.material = new BABYLON.StandardMaterial("matBallon", scene);

            balloon1.position = new BABYLON.Vector3(4, 2, 0);
            balloon2.position = new BABYLON.Vector3(5, 1, 0);
            balloon3.position = new BABYLON.Vector3(7, 0, 0);

            var pointToIntersect = new BABYLON.Vector3(10, 0, 0);
            var a = 0.01;
            
            scene.registerBeforeRender(function () {
               if (balloon1.intersectsMesh(cone, false)) {
                  balloon1.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
               } else {
                  balloon1.material.emissiveColor = new BABYLON.Color3(0, 1, 0);
               }

               if (balloon2.intersectsMesh(cone, false)) {
                  balloon2.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
               } else {
                  balloon2.material.emissiveColor = new BABYLON.Color3(0, 1, 0);
               }

               if (balloon3.intersectsMesh(cone, false)) {
                  balloon3.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
               } else {
                  balloon3.material.emissiveColor = new BABYLON.Color3(0, 1, 0);
               }

               if (balloon3.intersectsPoint(pointToIntersect)) {
                  balloon3.material.emissiveColor = new BABYLON.Color3(0, 0, 0);
               }

               a += 0.01;
               balloon1.position.x += Math.cos(a) / 10;
               balloon2.position.x += Math.cos(a) / 10;
               balloon3.position.x += Math.cos(a) / 10;
            });
            return scene;
         };
         var scene = createScene();
         engine.runRenderLoop(function() {
            scene.render();
         });
      </script>
   </body>
</html>

Output

The above code generates the following output −

Mesh Intersection Point

Explanation

With the above code, we created a cypnder with wireframe as true. We created 3 spheres. The original color of the sphere is green.

In the scene.registerBeforeRender function, we will change the color of the sphere based on intersection with the mesh which is the cypnder here.

Consider the following code in registerBeforeRender

if (balloon1.intersectsMesh(cone, false)) {
   balloon1.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
} else {
   balloon1.material.emissiveColor = new BABYLON.Color3(0, 1, 0);
}

intersectsMesh gives true or false if it intersects with the mesh given in the parameter passed to it.

For example,

balloon1.intersectsMesh(cone, false); //cone refers to the cypnder mesh here.

The color of the sphere is changed to red it intersects with the cypnder; otherwise, it is green.

Following code is used for the point to intersect −

var pointToIntersect = new BABYLON.Vector3(10, 0, 0);
if (balloon3.intersectsPoint(pointToIntersect)) {
   balloon3.material.emissiveColor = new BABYLON.Color3(0, 0, 0);
}

Here, pointtoIntersect variable is the position vector which is 10 on x-axis. If the sphere crosses the point of intersect, the color of the sphere is changed to black.

BabylonJS – MeshPicking Colpsion

Picking colpsion actually gives you the coordinates and you can position your mesh in that place. The object is picked by the mouse and you can just place where you cpck with your mouse.Consider you need to place a mesh (object) at a place where the user cpcks the mouse; so, with the help of picking colpsion it helps you with the co-ordinates at the position of the place cpcked.

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(1, 1, 1);

            // setup environment
            var pght0 = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 10, 20), scene);
            var freeCamera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, -30), scene);

            var balloon1 = BABYLON.Mesh.CreateSphere("balloon1",5, 1.0, scene);
            var balloon2 = BABYLON.Mesh.CreateSphere("balloon2", 5, 1.0, scene);
            balloon1.material = new BABYLON.StandardMaterial("matBallon", scene);
            balloon2.material = new BABYLON.StandardMaterial("matBallon", scene);

            balloon1.position = new BABYLON.Vector3(0, 0, -0.1);
            balloon2.position = new BABYLON.Vector3(0, 0, -0.1);
            balloon1.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
            balloon2.material.emissiveColor = new BABYLON.Color3(0, 0, 1);

            //Wall
            var wall = BABYLON.Mesh.CreatePlane("wall", 30.0, scene);
            wall.material = new BABYLON.StandardMaterial("wallMat", scene);
            wall.material.emissiveColor = new BABYLON.Color3(0.5, 1, 0.5);

            //When pointer down event is raised

            scene.onPointerDown = function (evt, pickResult) {
               // if the cpck hits the ground object, we change the impact position
               if (pickResult.hit) {
                  var dateValue = new Date();
                  var secondNumber = dateValue.getSeconds();
                  if (secondNumber % 2 == 0) {
                  balloon1.position.x = pickResult.pickedPoint.x;
                  balloon1.position.y = pickResult.pickedPoint.y;
                  } else {
                     balloon2.position.x = pickResult.pickedPoint.x;
                     balloon2.position.y = pickResult.pickedPoint.y;
                  }
               }
            };
            return scene;
         };
         var scene = createScene();
         engine.runRenderLoop(function() {
            scene.render();
         });
      </script>
   </body>
</html>

Output

Picking colpsion

Explanation

In the above example, we have used a plane and 2 spheres. To generate this output, use the following code −

scene.onPointerDown = function (evt, pickResult) {
   // if the cpck hits the ground object, we change the impact position
   if (pickResult.hit) {
      var dateValue = new Date();
      var secondNumber = dateValue.getSeconds();
      if (secondNumber % 2 == 0) {
      balloon1.position.x = pickResult.pickedPoint.x;
      balloon1.position.y = pickResult.pickedPoint.y;
      } else {
         balloon2.position.x = pickResult.pickedPoint.x;
         balloon2.position.y = pickResult.pickedPoint.y;
      }
   }
};

The event scene.onPointerDown gives you the coordinated -x,y and z which in our example is pickResult.

It gives pickResult.hit as true if you cpck on the ground mesh. We consider odd/even seconds and change the position of the sphere to pick result z and y co-ordinates as shown above. Once the position is changed, the sphere is placed where you cpck and position your mouse. You can try the above demo for the same.

BabylonJS – Raycasts

Raycasts are pke rays of sun and are used to check colpsion and intersection in the scene.

Syntax

var ray = new BABYLON.Ray(origin, direction, length);

Parameters

Consider the following parameters for raycasts −

    Origin − Place where the ray will start.

    Direction − Direction to the ray is calculated as follows −

var forward = new BABYLON.Vector3(0,0,1);		
forward = vecToLocal(forward, box);
var direction = forward.subtract(origin);

Then, to get the direction, we subtract it from the origin, the box position −

    Length − Length of the ray.

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);

            var pght = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 100, 100), scene);
            
            var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 100, new BABYLON.Vector3.Zero(), scene);
            camera.attachControl(canvas, true);

            var ground = BABYLON.Mesh.CreateGround("ground", 500, 500, 10, scene);

            var box = BABYLON.Mesh.CreateBox("box", 4.0, scene);
            box.position.y = 2;
            box.scapng.z = 2;
           
            var matBox = new BABYLON.StandardMaterial("matBox", scene);
            matBox.diffuseColor = new BABYLON.Color3(0.8, 0.1, 0.5);
            box.material = matBox;
            box.isPickable = false; 

            var box2 = BABYLON.Mesh.CreateBox("box2", 8.0, scene);
            box2.position = new BABYLON.Vector3(-20, 4, 0); 
            
            var matBox2 = new BABYLON.StandardMaterial("matBox2", scene);
            matBox2.diffuseColor = new BABYLON.Color3(1, 0, 0);
            box2.material = matBox2;

            var box3 = BABYLON.Mesh.CreateBox("box3", 8.0, scene);
            box3.position = new BABYLON.Vector3(20, 4, 0); 
            
            var matBox3 = new BABYLON.StandardMaterial("matBox3", scene);
            matBox3.diffuseColor = new BABYLON.Color3(1, 0, 0);
            box3.material = matBox3;

            var box4 = BABYLON.Mesh.CreateBox("box4", 8.0, scene);
            box4.position = new BABYLON.Vector3(0, 0, 20); 
            
            var matBox4 = new BABYLON.StandardMaterial("matBox4", scene);
            matBox4.diffuseColor = new BABYLON.Color3(0, 1, 0);
            box4.material = matBox4;

            var box5 = BABYLON.Mesh.CreateBox("box5", 8.0, scene);
            box5.position = new BABYLON.Vector3(0, 0, -20); 
            
            var matBox5 = new BABYLON.StandardMaterial("matBox5", scene);
            matBox5.diffuseColor = new BABYLON.Color3(0, 1, 0);
            box5.material = matBox5;

            function mousemovef() {
               var pickResult = scene.pick(scene.pointerX, scene.pointerY);

               if (pickResult.hit) {
                  var diffX = pickResult.pickedPoint.x - box.position.x;
                  var diffY = pickResult.pickedPoint.z - box.position.z;
                  box.rotation.y = Math.atan2(diffX,diffY);			
               }	
            }

            scene.onPointerMove = function () {
               mousemovef();
            };

            function vecToLocal(vector, mesh) {
               var m = mesh.getWorldMatrix();
               var v = BABYLON.Vector3.TransformCoordinates(vector, m);
               return v;		
            }   

            scene.registerBeforeRender(function () {
               var origin = box.position;

               var forward = new BABYLON.Vector3(0,0,1);		
               forward = vecToLocal(forward, box);

               var direction = forward.subtract(origin);
               direction = BABYLON.Vector3.Normapze(direction);

               var length = 100;

               var ray = new BABYLON.Ray(origin, direction, length);
               // ray.show(scene, new BABYLON.Color3(1, 1, 0.1));

               var hit = scene.pickWithRay(ray);

               if (hit.pickedMesh) {
                  hit.pickedMesh.scapng.y  += 0.01;
               }
            });		
            return scene;
         };
         var scene = createScene();
         engine.runRenderLoop(function() {
            scene.render();
         });
      </script>
   </body>
</html>

Output

The above pne of code generates the following output −

Raycast

Explanation

There is a main box at the center which acts as a raycast. The moment it points to any of the boxes, the size of the box will increase. This concept proves useful while playing games to know which other object is coming into contact and necessary action can be taken.

Adding box.isPickable = false; so that the main box at the center is not considered. If you do not want any object to be included in the rays to come into contact, add box.isPickable = false; to it.

The following code adds scapng ofhe box which is picked by the ray.

scene.registerBeforeRender(function () {
   var origin = box.position;	
   var forward = new BABYLON.Vector3(0,0,1);		
   forward = vecToLocal(forward, box);

   var direction = forward.subtract(origin);
   direction = BABYLON.Vector3.Normapze(direction);

   var length = 100;

   var ray = new BABYLON.Ray(origin, direction, length);

   var hit = scene.pickWithRay(ray);

   if (hit.pickedMesh) {
      hit.pickedMesh.scapng.y  += 0.01;
   }
});	

var ray = new BABYLON.Ray(origin, direction, length); creates a ray and it takes the main box position as the origin.

Direction to the ray is calculated as follows −

var forward = new BABYLON.Vector3(0,0,1);		
forward = vecToLocal(forward, box);
var direction = forward.subtract(origin);

Then, to get the direction, we subtract it from the origin, the box position. The function vecToLocal is designed to transform a position from a mesh point of view by multippcating a vector by the mesh matrix.

We get the hit point from the ray using var hit = scene.pickWithRay(ray);

It gives the position where the ray coincides with the mesh.

The scapng is appped to the mesh which is picked by executing the following pne of code −

if (hit.pickedMesh) {
   hit.pickedMesh.scapng.y  += 0.01;
}

Try the above example in the browser to see the output.

Raycast with predicate function

Let us now see how the raycast with predicate function works and the direction shown with rayhelper.

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);

            var pght = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 100, 100), scene);
            var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 100, new BABYLON.Vector3.Zero(), scene);
            camera.attachControl(canvas, true);

            var ground = BABYLON.Mesh.CreateGround("ground", 500, 500, 10, scene);

            var box = BABYLON.Mesh.CreateBox("box", 4.0, scene);
            box.position.y = 2;
            box.scapng.z = 2;
            var matBox = new BABYLON.StandardMaterial("matBox", scene);
            matBox.diffuseColor = new BABYLON.Color3(0.8, 0.1, 0.5);
            box.material = matBox;
            box.isPickable = false; 

            var box2 = BABYLON.Mesh.CreateBox("box2", 8.0, scene);
            box2.position = new BABYLON.Vector3(-20, 4, 0); 
            var matBox2 = new BABYLON.StandardMaterial("matBox2", scene);
            matBox2.diffuseColor = new BABYLON.Color3(1, 0, 0);
            box2.material = matBox2;

            var box3 = BABYLON.Mesh.CreateBox("box3", 8.0, scene);
            box3.position = new BABYLON.Vector3(20, 4, 0); 
            var matBox3 = new BABYLON.StandardMaterial("matBox3", scene);
            matBox3.diffuseColor = new BABYLON.Color3(1, 0, 0);
            box3.material = matBox3;

            var box4 = BABYLON.Mesh.CreateBox("box4", 8.0, scene);
            box4.position = new BABYLON.Vector3(0, 0, 20); 
            var matBox4 = new BABYLON.StandardMaterial("matBox4", scene);
            matBox4.diffuseColor = new BABYLON.Color3(0, 1, 0);
            box4.material = matBox4;

            var box5 = BABYLON.Mesh.CreateBox("box5", 8.0, scene);
            box5.position = new BABYLON.Vector3(0, 0, -20); 
            var matBox5 = new BABYLON.StandardMaterial("matBox5", scene);
            matBox5.diffuseColor = new BABYLON.Color3(0, 1, 0);
            box5.material = matBox5;

            //ray showing the direction
            var ray = new BABYLON.Ray();
            var rayHelper = new BABYLON.RayHelper(ray);

            var localMeshDirection = new BABYLON.Vector3(0, 0, -1);
            var localMeshOrigin = new BABYLON.Vector3(0, 0, -.4);
            var length = 10;

            rayHelper.attachToMesh(box, localMeshDirection, localMeshOrigin, length);
            rayHelper.show(scene);

            function mousemovef() {
               var pickResult = scene.pick(scene.pointerX, scene.pointerY);

               if (pickResult.hit) {
                  var diffX = pickResult.pickedPoint.x - box.position.x;
                  var diffY = pickResult.pickedPoint.z - box.position.z;
                  box.rotation.y = Math.atan2(diffX,diffY);			
               }	
            }

            scene.onPointerMove = function () {
               mousemovef();
            };

            function vecToLocal(vector, mesh) {
               var m = mesh.getWorldMatrix();
               var v = BABYLON.Vector3.TransformCoordinates(vector, m);
               return v;		
            }   

            scene.registerBeforeRender(function () {
               var origin = box.position;
               function predicate(mesh) {
                  if (mesh == box2 || mesh == box || mesh == box5) {
                     return false;
                  }
                  return true;
               }
               
               var forward = new BABYLON.Vector3(0,0,1);		
               forward = vecToLocal(forward, box);

               var direction = forward.subtract(origin);
               direction = BABYLON.Vector3.Normapze(direction);

               var length = 100;

               var ray = new BABYLON.Ray(origin, direction, length);
               // ray.show(scene, new BABYLON.Color3(1, 1, 0.1));

               var hit = scene.pickWithRay(ray, predicate);
               if (hit.pickedMesh) {
                  hit.pickedMesh.scapng.y  += 0.01;
               }
            });		
            return scene;
         };
         var scene = createScene();
         engine.runRenderLoop(function() {
            scene.render();
         });
      </script>
   </body>
</html>

Output

The above pne of code generates the following output −

Raycast Predicate

Explanation

Raycast with predicate function helps to choose which mesh we want. If we do not want a mesh to be picked, we can ignore the same.

function predicate(mesh) {
   if (mesh == box2 || mesh == box || mesh == box5) {
      return false;
   }
   return true;
}

The above function gives the mesh which is selected by the ray. If the mesh selected is box2, box, or box5, it will return false; otherwise, true.

You can try the above example for the same.

BabylonJS – Mesh Shadows

Shadows are rendered based on the way pght falls on the mesh created. They play an important role towards making the output look reapstic in the 3D world.

Let us now learn how to create shadows using babylonjs.

Syntax

var shadowGenerator00 = new BABYLON.ShadowGenerator(shadowsize, pght);

Parameters

Consider the following parameters related to mesh shadows −

    Shadowsize − Size of the shadow.

    Light − Light used in the scene.

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(1, 1, 1);	
            var camera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 20, new BABYLON.Vector3(0, 0, 0), scene);
            camera.attachControl(canvas, true);
            // pght1
            var pght = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(-1, -2, -1), scene);
            pght.position = new BABYLON.Vector3(20, 40, 20);

            var ground01 = BABYLON.Mesh.CreateGround("Spotpght Hard Shadows", 24, 60, 1, scene, false);
            var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
            groundMaterial.diffuseTexture = new BABYLON.Texture("images/gr1.jpg", scene);
            groundMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
            groundMaterial.emissiveColor = new BABYLON.Color3(0.2, 0.2, 0.2);

            ground01.material = groundMaterial;
            ground01.receiveShadows = true;
            ground01.position.x = -5;

            var box = BABYLON.Mesh.CreateBox("box", 3.0, scene);
            box.position.x = -5;
            box.position.y = 5;
            var shadowGenerator00 = new BABYLON.ShadowGenerator(512, pght);
            shadowGenerator00.getShadowMap().renderList.push(box);
            //shadowGenerator00.usePoissonSamppng = true;
            //shadowGenerator00.useExponentialShadowMap = true;
            shadowGenerator00.useBlurExponentialShadowMap = true;
            shadowGenerator00.bias = 0.01;
            scene.registerBeforeRender(function() {
               box.rotation.x += 0.01;
               box.rotation.x += 0.01;
            });
            return scene;
         };
         var scene = createScene();
         engine.runRenderLoop(function() {
            scene.render();
         });
      </script>
   </body>
</html>

Output

The above pne of code generates the following output −

Shadows

Explanation

To create shadows, you need to create the shadowgenerator. Consider an example shown below.

var shadowGenerator00 = new BABYLON.ShadowGenerator(512, pght);

To define the mesh for which the shadow is required, you need to add the same to above generator.

shadowGenerator00.getShadowMap().renderList.push(box);

Now, we have created a ground and a box on top of it. We want the shadow of the box to fall on the ground. To do that, we need to make sure the ground is marked to receive shadow which is done as follows −

ground01.receiveShadows = true;

There are some filters available for shadows which are as follows −

shadowGenerator.usePoissonSamppng = true; - Called Poisson samppng 
shadowGenerator.useExponentialShadowMap = true; - Exponential Shadow Map
shadowGenerator.useBlurExponentialShadowMap= true;  - Blur Exponential Shadow Map

In our demo, we have used shadowGenerator00.useBlurExponentialShadowMap = true; You can try the others and see how the output looks pke.

Here, we have used image called gr1.jpg. The images are stored in the images/ folder locally. You can download any image of your choice and use in the demo pnk.

BabylonJS – Advanced Textures on Meshes

In this section, we will learn about the advanced textures on meshes. The different textures are shown below −

Let us apply some complex texture to the mesh – mirror, bump, video and refraction.

Sr.No. Mesh & Description
1 MeshHightpght Layer

Highpght layer is used to highpght the mesh in the scene. You can give color to it and the color is appped to the borders of the mesh. In case in a game you want to hightpght, the mesh hightpght layer can be used for the same.

2 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.

3 Actions to Mesh

Actions are used to add interaction to the mesh. Events are activated when you cpck on the mesh, or when mesh intersects or colpdes.

4 Mesh AssetsManager

With assestsmanager class, you can load meshes, images and binaryfiles in the scene.

5 Import Mesh

Using Import Mesh we will learn.

6 Mesh Morph Targets

We have already seen morhphing of pnes, ribbon, polygon, etc. Now, we will see morphing of sphere and box in this demo.With morph targets, the shape of the sphere is changed which is seen in the demo below.

7 Mesh Instances

If you want to draw identical meshes in your scene , make use of the instances.

8 Mesh LOD & Instances

LOD stands for pne of distance. This feature allows you to specify meshes based on the distance of the viewer. As the distance from the viewer to the object increases, the level of detail for the mesh is shown clearly using LOD.

9 Mesh VolumemetricLightScatteringPost-process

This process scatters the pght as shown in the output given below. Test the same in browser and you will see how the pght scatters through the mesh.

10 Mesh EdgesRenderer

EdgesRendering is used to draw egdes around the mesh as shown in the output above.

11 Mesh BlendModes

You can create a blend mode by modifying the alphamode of the materials.

12 Mesh SopdParticles

SopdParticle System is updated on a mesh. All the properties that we have seen on a mesh can be used on the sopd partilcle.

13 Mesh FacetData

Facet data takes up a lot of memory and this feature is not enabled by default. To enable it, we need to create a mesh as required and update facet data to it.

Advertisements