BabylonJS - Lưới

Trong chương này, chúng ta sẽ học cách tạo các hình dạng khác nhau bằng trình tạo lưới. Chúng ta đã học cách tạo hình dạng trong một trong các chương trước của chúng ta.

Sự khác biệt là với meshbuilder cho phép bạn linh hoạt thêm màu sắc, hình ảnh vào các hình dạng.

CreateBox bằng MeshBuilder

Bây giờ chúng ta hãy xem cách tạo hộp bằng MeshBuilder.

Bản giới thiệu

<!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 light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
            light.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>

Đầu ra

Dòng mã trên tạo ra kết quả sau:

Đối với ví dụ trên, chúng tôi đã sử dụng một hình ảnh sprite như hình dưới đây. Nó có 3 ô theo chiều ngang và 2 hàng theo chiều dọc.

Trong bản demo này, chúng tôi đã sử dụng một hình ảnh có tên là cube.png. Các hình ảnh được lưu trữ trong thư mục image / local và cũng được dán bên dưới để tham khảo. Xin lưu ý rằng cube.png là một hình ảnh sprite, một hình ảnh sprite là một tập hợp các hình ảnh. Chúng tôi muốn hiển thị hình ảnh trên một khối lập phương vì vậy muốn tất cả các cạnh của khối lập phương lại với nhau. Bạn cũng có thể tải xuống các hình ảnh sprite tương tự mà bạn chọn và sử dụng trong liên kết demo.

Trình tạo createBox cung cấp cho bạn các tùy chọn về kích thước.

Ví dụ,

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

Bản giới thiệu

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

Điều này được gọi là áp dụng kết cấu cho trình tạo lưới bằng phương thức createBox. Chúng tôi đã sử dụng hình ảnh cube.png có chiều ngang là 3 cột và chiều dọc là 2 hàng. hình lập phương hoặc hình hộp có 6 cạnh.

Để áp dụng kết cấu, chúng tôi sử dụng tham số tùy chọn. Ví dụ:

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

Chúng tôi đã xác định một mảng được gọi là faceUV với kích thước là 6 là các cạnh của khối lập phương. Mảng này sẽ luôn có các phần tử Vector4. Mỗi Vector4 (x, y, z, w) sẽ được định nghĩa như sau:

  • x = Ubottom
  • y = Vbottom
  • z = Dừng lại
  • w = Vtop

Các vectơ nằm trong phạm vi [0, 1]. Ubottom và Vbottom là tọa độ 2D của điểm dưới cùng bên trái nơi bắt đầu cắt họa tiết. Dừng, Vtop là các điểm trên cùng bên phải nơi kết thúc cắt họa tiết.

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

Giả sử kết cấu mặc định, tức là, hình ảnh đã cho được áp dụng cho tất cả các mặt của hộp. Nếu bạn chỉ muốn thay đổi 1 mặt hoặc 1 mặt của hộp, bạn có thể gán trực tiếp các giá trị như hình dưới đây -

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

Thí dụ

<!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 light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
            light.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>

Đầu ra

Dòng mã trên tạo ra kết quả sau:

Trong bản demo này, chúng tôi đã sử dụng một hình ảnh có tên là 3d.png. Các hình ảnh được lưu trữ trong thư mục image / local và cũng được dán bên dưới để tham khảo. Xin lưu ý 3d.png là một hình ảnh sprite; một hình ảnh sprite là một tập hợp các hình ảnh. Chúng tôi muốn hiển thị hình ảnh trên một khối lập phương với tất cả các cạnh của khối lập phương cùng nhau. Bạn cũng có thể tải xuống các hình ảnh sprite tương tự mà bạn chọn và sử dụng trong liên kết demo.

Kết cấu được sử dụng cho hộp - images/3d.png

MeshCylinder

Trong phần này, chúng ta sẽ xem cách tạo MeshCylinder.

Để tạo MeshCylinder, bạn cần sử dụng lớp BABYLON.MeshBuilder.CreateCylinder.

Các tham số cho lớp như sau:

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

Sự khác biệt giữa CreateCylinder sử dụng mesh và meshbuilder là - bạn có thể sử dụng các tùy chọn trong meshbuilder. Ngay bây giờ chúng tôi đang sử dụng chiều cao, đường kính và kích thước làm các tùy chọn được chuyển đến hình trụ. Chúng tôi đang sử dụng vật liệu tiêu chuẩn với khung dây làm vật liệu cho lưới này. Kiểm tra đầu ra trong trình duyệt và xem hình trụ. Bạn có thể sử dụng cấu trúc tương tự trong trò chơi của mình như một bánh xe quay trong cảnh.

Bản giới thiệu

<!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 light = 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 meshcylinder = BABYLON.MeshBuilder.CreateCylinder("meshcylinder", {
               height: 3,
               diameter: 35,
               tessellation: 52
            }, scene);

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

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

Đầu ra

Dòng mã trên tạo ra kết quả sau:

Một số hình dạng được tạo bằng trình tạo lưới bây giờ sẽ được sử dụng cùng nhau trong một bản trình diễn. Các hình dạng có trong liên kết demo bên dưới được liệt kê trong các phần tiếp theo.

  • Ground

  • Cone

  • Plane

  • Disc

  • Torus

  • Polyhedron

  • IcoSphere

BabylonJS - Giao điểm và điểm lưới

Giao điểm lưới trong trò chơi rất quan trọng vì bạn biết những gì cần phải làm khi 2 đối tượng giao nhau trong trò chơi. Khái niệm tương tự được giải thích trong bản demo bên dưới về sự kiện cần được nắm bắt khi các mắt lưới giao nhau.

Trong bản trình diễn dưới đây, chúng tôi đã đề cập đến hai khái niệm sau:

  • Lưới giao nhau
  • Điểm giao nhau
<!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.CreateCylinder("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>

Đầu ra

Đoạn mã trên tạo ra kết quả sau:

Giải trình

Với đoạn mã trên, chúng tôi đã tạo một hình trụ với wireframe như đúng. Chúng tôi đã tạo ra 3 quả cầu. Màu ban đầu của quả cầu là xanh lục.

bên trong scene.registerBeforeRender chức năng, chúng tôi sẽ thay đổi màu sắc của hình cầu dựa trên giao điểm với lưới là hình trụ ở đây.

Hãy xem xét đoạn mã sau trong 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 cho đúng hoặc sai nếu nó giao nhau với lưới đã cho trong tham số được truyền cho nó.

Ví dụ,

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

Màu sắc của hình cầu được thay đổi thành màu đỏ nó giao với hình trụ; ngược lại, nó có màu xanh lá cây.

Mã sau được sử dụng cho điểm giao nhau:

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

Đây, pointtoIntersectbiến là vectơ vị trí là 10 trên trục x. Nếu quả cầu đi qua giao điểm thì màu của quả cầu đổi thành màu đen.

BabylonJS - Va chạm MeshPicking

Chọn va chạm thực sự cung cấp cho bạn tọa độ và bạn có thể định vị lưới của mình ở vị trí đó. Đối tượng được chọn bằng chuột và bạn có thể chỉ cần đặt ở nơi bạn nhấp chuột, hãy cân nhắc bạn cần đặt lưới (đối tượng) tại nơi người dùng nhấp chuột; vì vậy, với sự trợ giúp của việc chọn va chạm, nó sẽ giúp bạn có các tọa độ tại vị trí của nơi được nhấp.

Bản giới thiệu

<!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 light0 = 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 click 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>

Đầu ra

Giải trình

Trong ví dụ trên, chúng ta đã sử dụng một mặt phẳng và 2 hình cầu. Để tạo đầu ra này, hãy sử dụng mã sau:

scene.onPointerDown = function (evt, pickResult) {
   // if the click 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;
      }
   }
};

Sự kiện scene.onPointerDown cung cấp cho bạn -x, y và z phối hợp mà trong ví dụ của chúng tôi là pickResult.

Nó cung cấp cho pickResult.hit như đúng nếu bạn nhấp vào lưới mặt đất. Chúng ta xem xét các giây lẻ / chẵn và thay đổi vị trí của quả cầu để chọn kết quả z và y tọa độ như hình trên. Khi vị trí được thay đổi, hình cầu sẽ được đặt ở nơi bạn nhấp và định vị chuột. Bạn có thể thử các bản demo trên cho giống nhau.

BabylonJS - Raycast

Raycast giống như tia nắng mặt trời và được sử dụng để kiểm tra va chạm và giao cắt trong hiện trường.

Cú pháp

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

Thông số

Hãy xem xét các thông số sau cho những người ăn chay:

  • Origin - Đặt nơi tia sẽ bắt đầu.

  • Direction - Hướng tới tia được tính như sau -

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

Sau đó, để có được hướng, chúng tôi trừ nó khỏi điểm gốc, vị trí hộp -

  • Length - Chiều dài của tia.

Bản giới thiệu

<!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 light = 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.scaling.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.Normalize(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.scaling.y  += 0.01;
               }
            });		
            return scene;
         };
         var scene = createScene();
         engine.runRenderLoop(function() {
            scene.render();
         });
      </script>
   </body>
</html>

Đầu ra

Dòng mã trên tạo ra kết quả sau:

Giải trình

Có một hộp chính ở trung tâm hoạt động như một hộp đựng đồ ăn chay. Thời điểm nó trỏ đến bất kỳ hộp nào, kích thước của hộp sẽ tăng lên. Khái niệm này tỏ ra hữu ích trong khi chơi trò chơi để biết đối tượng nào khác đang tiếp xúc và hành động cần thiết có thể được thực hiện.

Thêm box.isPickable = false;sao cho hộp chính ở tâm không được xét. Nếu bạn không muốn bất kỳ vật thể nào trong tia tiếp xúc, hãy thêmbox.isPickable = false; với nó.

Đoạn mã sau đây bổ sung thêm tỷ lệ của hộp được chọn bởi tia.

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.Normalize(direction);

   var length = 100;

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

   var hit = scene.pickWithRay(ray);

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

var ray = new BABYLON.Ray(origin, direction, length); tạo ra một tia và nó lấy vị trí hộp chính làm điểm gốc.

Hướng tới tia được tính như sau:

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

Sau đó, để có được hướng, chúng tôi trừ nó từ điểm gốc, vị trí hộp. Chức năngvecToLocal được thiết kế để biến đổi một vị trí từ quan điểm lưới bằng cách nhân một vectơ với ma trận lưới.

Chúng tôi nhận được điểm nhấn từ tia bằng cách sử dụng var hit = scene.pickWithRay(ray);

Nó cho biết vị trí mà tia trùng với lưới.

Việc chia tỷ lệ được áp dụng cho lưới được chọn bằng cách thực thi dòng mã sau:

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

Hãy thử ví dụ trên trong trình duyệt để xem kết quả.

Raycast với chức năng vị ngữ

Bây giờ chúng ta hãy xem cách hoạt động của raycast với chức năng vị từ và hướng được hiển thị với rayhelper.

Bản giới thiệu

<!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 light = 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.scaling.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.Normalize(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.scaling.y  += 0.01;
               }
            });		
            return scene;
         };
         var scene = createScene();
         engine.runRenderLoop(function() {
            scene.render();
         });
      </script>
   </body>
</html>

Đầu ra

Dòng mã trên tạo ra kết quả sau:

Giải trình

Raycast với chức năng vị từ giúp chọn lưới nào chúng ta muốn. Nếu chúng ta không muốn lưới được chọn, chúng ta có thể bỏ qua tương tự.

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

Hàm trên cho lưới được chọn bởi tia. Nếu lưới được chọn là box2, box hoặc box5, nó sẽ trả về false; ngược lại, đúng.

Bạn có thể thử ví dụ trên cho tương tự.

BabylonJS - Bóng râm lưới

Bóng được hiển thị dựa trên cách ánh sáng rơi vào lưới được tạo ra. Chúng đóng một vai trò quan trọng trong việc làm cho đầu ra trông thực tế trong thế giới 3D.

Bây giờ chúng ta hãy học cách tạo bóng đổ bằng cách sử dụng babylonjs.

Cú pháp

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

Thông số

Hãy xem xét các thông số sau liên quan đến bóng lưới -

  • Shadowsize - Kích thước của bóng.

  • Light - Ánh sáng được sử dụng trong cảnh.

Bản giới thiệu

<!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);
            // light1
            var light = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(-1, -2, -1), scene);
            light.position = new BABYLON.Vector3(20, 40, 20);

            var ground01 = BABYLON.Mesh.CreateGround("Spotlight 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, light);
            shadowGenerator00.getShadowMap().renderList.push(box);
            //shadowGenerator00.usePoissonSampling = 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>

Đầu ra

Dòng mã trên tạo ra kết quả sau:

Giải trình

Để tạo bóng đổ, bạn cần tạo trình tạo bóng. Hãy xem xét một ví dụ được hiển thị bên dưới.

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

Để xác định lưới cần có bóng, bạn cần phải thêm lưới tương tự vào trình tạo ở trên.

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

Bây giờ, chúng tôi đã tạo ra một mặt đất và một cái hộp trên đó. Chúng tôi muốn bóng của chiếc hộp rơi trên mặt đất. Để làm điều đó, chúng ta cần đảm bảo mặt đất được đánh dấu để nhận bóng, thực hiện như sau:

ground01.receiveShadows = true;

Có một số bộ lọc có sẵn cho bóng đổ như sau:

shadowGenerator.usePoissonSampling = true; - Called Poisson sampling 
shadowGenerator.useExponentialShadowMap = true; - Exponential Shadow Map
shadowGenerator.useBlurExponentialShadowMap= true;  - Blur Exponential Shadow Map

Trong bản demo của chúng tôi, chúng tôi đã sử dụng shadowGenerator00.useBlurExponentialShadowMap = true; Bạn có thể thử những cái khác và xem đầu ra trông như thế nào.

Ở đây, chúng tôi đã sử dụng hình ảnh có tên là gr1.jpg. Hình ảnh được lưu trữ trong thư mục / hình ảnh cục bộ. Bạn có thể tải xuống bất kỳ hình ảnh nào bạn chọn và sử dụng trong liên kết demo.

BabylonJS - Họa tiết nâng cao trên lưới

Trong phần này, chúng ta sẽ tìm hiểu về các kết cấu nâng cao trên mắt lưới. Các kết cấu khác nhau được hiển thị bên dưới -

  • Kết cấu hình khối

  • Gương và Kết cấu Bump

  • Kết cấu video

Hãy để chúng tôi áp dụng một số kết cấu phức tạp cho lưới - gương, vết sưng, video và khúc xạ.

Sr.No. Lưới & Mô tả
1 Lớp MeshHightlight

Lớp nổi bật được sử dụng để làm nổi bật lưới trong cảnh. Bạn có thể tạo màu cho nó và màu được áp dụng cho các đường viền của lưới. Trong trường hợp trong một trò chơi bạn muốn làm nổi bật, lớp hightlight dạng lưới có thể được sử dụng cho tương tự.

2 Morph a Mesh

Morphing thay đổi hình dạng của một đối tượng thành một đối tượng khác bằng một số phương tiện chuyển đổi. Chúng tôi đã thấy tham số có thể cập nhật cho các hình dạng; nếu không thì tham số được đặt thành false. Đối với biến hình, nó được đặt thành true và lưới được cập nhật để thay đổi hình dạng.

3 Hành động đối với Mesh

Các hành động được sử dụng để thêm tương tác vào lưới. Sự kiện được kích hoạt khi bạn nhấp vào lưới hoặc khi lưới giao nhau hoặc va chạm.

4 Mesh AssetsManager

Với lớp Assestsmanager, bạn có thể tải lưới, hình ảnh và tệp nhị phân trong cảnh.

5 Nhập lưới

Sử dụng lưới nhập khẩu chúng ta sẽ tìm hiểu.

6 Mục tiêu Mesh Morph

Chúng ta đã thấy sự biến đổi của các đường, dải băng, đa giác, v.v. Bây giờ, chúng ta sẽ thấy sự biến đổi của khối cầu và khối hộp trong bản trình diễn này. Với các mục tiêu biến hình, hình dạng của khối cầu được thay đổi như được thấy trong bản trình diễn bên dưới.

7 Phiên bản lưới

Nếu bạn muốn vẽ các mắt lưới giống hệt nhau trong cảnh của mình, hãy sử dụng các phiên bản.

số 8 Mesh LOD & Phiên bản

LOD là viết tắt của khoảng cách. Tính năng này cho phép bạn chỉ định các mắt lưới dựa trên khoảng cách của người xem. Khi khoảng cách từ người xem đến đối tượng tăng lên, mức độ chi tiết của lưới được hiển thị rõ ràng bằng cách sử dụng LOD.

9 Mesh VolumemetricLightScatteringPost-process

Quá trình này phân tán ánh sáng như thể hiện trong đầu ra dưới đây. Thử nghiệm tương tự trong trình duyệt và bạn sẽ thấy ánh sáng tán xạ qua lưới như thế nào.

10 Mesh EdgesRenderer

EdgesRendering được sử dụng để vẽ các ví dụ xung quanh lưới như được hiển thị trong đầu ra ở trên.

11 Mesh BlendModes

Bạn có thể tạo chế độ hòa trộn bằng cách sửa đổi alphamode của vật liệu.

12 Mesh SolidParticles

Hệ thống SolidParticle được cập nhật trên một lưới. Tất cả các thuộc tính mà chúng ta đã thấy trên một lưới có thể được sử dụng trên sàn đặc.

13 Mesh FacetData

Dữ liệu khía cạnh chiếm nhiều bộ nhớ và tính năng này không được bật theo mặc định. Để kích hoạt nó, chúng ta cần tạo một lưới theo yêu cầu và cập nhật dữ liệu khía cạnh cho nó.