BabylonJS教程

BabylonJS 网格

在本章中,我们将学习使用网格生成器创建不同的形状。我们已经在之前的一章中学习了如何创建形状。
不同之处在于,使用 meshbuilder,您可以灵活地为形状添加颜色和图像。

使用 MeshBuilder 创建框

现在让我们看看如何使用 MeshBuilder 创建盒子。

演示

<!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>

输出

上面的代码行生成以下输出-
MeshBuilder CubeBox
对于上面的示例,我们使用了如下所示的精灵图像。它有水平 3 列和垂直 2 行。
Cube
在这个演示中,我们使用了一个名为 cube.png 的图像。图片保存在本地的images/文件夹中,也贴在下面供参考。请注意cube.png 是一个精灵图像,一个精灵图像是一组图像。我们想在一个立方体上显示图像,所以想把立方体的所有边都放在一起。您还可以下载您选择的类似精灵图像并在演示链接中使用。
createBox 构建器为您提供尺寸选项。
例如
var box = BABYLON.MeshBuilder.CreateBox("box", options, scene);

演示

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
};
这称为使用 createBox 方法将纹理应用到网格构建器。我们使用了图像 cube.png,它具有水平 3 列和垂直 2 行。立方体或盒子有 6 个边。
为了应用纹理,我们使用了 options 参数。例如,
var box = BABYLON.MeshBuilder.CreateBox ('box', options, scene);
我们定义了一个名为 faceUV 的数组,其大小为 6,即立方体的边。此数组将始终具有 Vector4 元素。每个 Vector4(x, y, z, w) 将定义如下-
x = Ubottom y = Vbottom z = Utop w = Vtop
向量在 [0, 1] 范围内。 Ubottom 和 Vbottom 是纹理裁剪开始处左下角点的 2D 坐标。 Utop、Vtop 是纹理裁剪结束的右上角点。
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);
}
假设默认纹理,即给定的图像应用于框的所有面。如果您只想更改框的 1 个面或 1 个侧面,您可以直接指定如下所示的值-
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);

示例

<!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>

输出

上面的代码行生成以下输出-
Textturepahse4
在这个演示中,我们使用了一个名为 3d.png 的图像。图片保存在本地的images/文件夹中,也贴在下面供参考。请注意 3d.png 是一个精灵图像;精灵图像是图像的集合。我们想在一个立方体上显示图像,立方体的所有边都放在一起。您还可以下载您选择的类似精灵图像并在演示链接中使用。
用于盒子的纹理- images/3d.png
3d

网格圆柱

在本节中,我们将看到如何创建 MeshCylinder。
要创建 MeshCylinder,您需要使用类 BABYLON.MeshBuilder.CreateCylinder。
类的参数如下-
var meshcylinder = BABYLON.MeshBuilder.CreateCylinder("meshcylinder", {
   height: 3,
   diameter: 35,
   tessellation: 52
}, scene);
使用mesh 和meshbuilder 的CreateCylinder 之间的区别在于——您可以使用meshbuilder 中的选项。现在我们使用高度、直径和镶嵌作为传递给圆柱体的选项。我们使用带有线框的标准材料作为此网格的材料。检查浏览器中的输出并查看圆柱体。您可以在游戏中使用类似的结构作为场景中旋转的轮子。

演示

<!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>

输出

上面的代码行生成以下输出-
网状圆柱体
使用网格生成器创建的许多形状现在将在一个演示中一起使用。下面的演示链接中涵盖的形状将在后续部分中列出。
Ground Cone Plane Disc Torus Polyhedron IcoSphere

BabylonJS – 网格交点和点

游戏中的网格交集很重要,因为您知道当 2 个对象在游戏中相交时需要做什么。相同的概念在下面的演示中解释了网格相交时需要捕获的事件。
在下面给出的演示中,我们涵盖了以下两个概念-
相交网格 交点
<!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>

输出

上面的代码生成以下输出-
网格交点

说明

使用上面的代码,我们创建了一个线框为真的圆柱体。我们创建了 3 个球体。球体的原始颜色是绿色。
scene.registerBeforeRender 函数中,我们将根据与此处为圆柱体的网格的交集来更改球体的颜色。
考虑 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 如果它与传递给它的参数中给定的网格相交,则给出 true 或 false。
例如
balloon1.intersectsMesh(cone, false); //cone refers to the cylinder mesh here.
球体的颜色变为红色,它与圆柱体相交;否则为绿色。
以下代码用于相交点-
var pointToIntersect = new BABYLON.Vector3(10, 0, 0);
if (balloon3.intersectsPoint(pointToIntersect)) {
   balloon3.material.emissiveColor = new BABYLON.Color3(0, 0, 0);
}
这里, pointtoIntersect 变量是在 x 轴上为 10 的位置向量。如果球体穿过相交点,球体的颜色将变为黑色。

BabylonJS – MeshPicking 碰撞

拾取碰撞实际上为您提供坐标,您可以将网格放置在该位置。该对象是由鼠标拾取的,您可以将其放置在您用鼠标单击的位置。考虑您需要在用户单击鼠标的位置放置一个网格(对象);因此,在拾取碰撞的帮助下,它可以帮助您确定点击位置的坐标。

演示

<!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>

输出

拾取碰撞

说明

在上面的例子中,我们使用了一个平面和 2 个球体。要生成此输出,请使用以下代码-
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;
      }
   }
};
事件 scene.onPointerDown 为您提供协调的-x、y 和 z,在我们的示例中为 pickResult
如果您单击地面网格,它会将 pickResult.hit 设为 true。我们考虑奇数/偶数秒并改变球体的位置以选择结果 z 和 y 坐标,如上所示。更改位置后,球体将放置在您单击并放置鼠标的位置。你可以试试上面的演示。

BabylonJS – 光线投射

光线投射就像太阳光线,用于检查场景中的碰撞和交叉。

语法

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

参数

考虑光线投射的以下参数-
Origin-光线开始的地方。 Direction-射线的方向计算如下-
var forward = new BABYLON.Vector3(0,0,1);    
forward = vecToLocal(forward, box);
var direction = forward.subtract(origin);
然后,为了得到方向,我们从原点,盒子位置减去它-
Length-射线的长度。

演示

<!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>

输出

上面的代码行生成以下输出-
Raycast

说明

中心有一个主框,用作光线投射。当它指向任何一个盒子时,盒子的大小就会增加。这个概念在玩游戏时被证明是有用的,可以了解哪个其他物体正在接触并采取必要的行动。
添加 box.isPickable = false; 以便不考虑中心的主框。如果您不希望任何包含在光线中的物体接触,请将 box.isPickable = false; 添加到其中。
下面的代码添加了被光线拾取的盒子的缩放。
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); 创建一条射线,并以主框位置为原点。
射线的方向计算如下-
var forward = new BABYLON.Vector3(0,0,1);    
forward = vecToLocal(forward, box);
var direction = forward.subtract(origin);
然后,为了得到方向,我们从原点,盒子位置减去它。函数 vecToLocal 旨在通过将向量乘以网格矩阵来从网格的角度变换位置。
我们使用 var hit = scene.pickWithRay(ray);
从光线中获取命中点
它给出了射线与网格重合的位置。
缩放应用于通过执行以下代码行选取的网格-
if (hit.pickedMesh) {
   hit.pickedMesh.scaling.y  += 0.01;
}
在浏览器中尝试上述示例以查看输出。

带谓词函数的Raycast

现在让我们看看带有谓词函数的光线投射是如何工作的,以及使用 rayhelper 显示的方向。

演示

<!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>

输出

上面的代码行生成以下输出-
Raycast Predicate

说明

带有谓词函数的Raycast有助于选择我们想要的网格。如果我们不想选择一个网格,我们可以忽略它。
function predicate(mesh) {
   if (mesh == box2 || mesh == box || mesh == box5) {
      return false;
   }
   return true;
}
上面的函数给出了射线选择的网格。如果选择的mesh为box2、box、box5,则返回false;否则为真。
你可以试试上面的例子。

BabylonJS – 网格阴影

根据光线落在创建的网格上的方式渲染阴影。它们在使输出在 3D 世界中看起来逼真方面发挥着重要作用。
现在让我们学习如何使用 babylonjs 创建阴影。

语法

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

参数

考虑以下与网格阴影相关的参数-
Shadowsize-阴影的大小。 Light-场景中使用的灯光。

演示

<!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>

输出

上面的代码行生成以下输出-
Shadows

说明

要创建阴影,您需要创建阴影生成器。考虑下面显示的示例。
var shadowGenerator00 = new BABYLON.ShadowGenerator(512, light);
要定义需要阴影的网格,您需要将相同的内容添加到上面的生成器中。
shadowGenerator00.getShadowMap().renderList.push(box);
现在,我们已经创建了一个地面和一个在它上面的盒子。我们希望盒子的阴影落在地上。为此,我们需要确保地面被标记为接收阴影,具体操作如下-
ground01.receiveShadows = true;
有一些可用于阴影的过滤器,如下所示-
shadowGenerator.usePoissonSampling = true;-Called Poisson sampling 
shadowGenerator.useExponentialShadowMap = true;-Exponential Shadow Map
shadowGenerator.useBlurExponentialShadowMap= true; -Blur Exponential Shadow Map
在我们的演示中,我们使用了 shadowGenerator00.useBlurExponentialShadowMap = true;你可以试试其他的,看看输出是什么样的。
这里,我们使用了名为 gr1.jpg 的图像。图像存储在本地的图像/文件夹中。您可以下载任何您选择的图片并在演示链接中使用。

BabylonJS – 网格上的高级纹理

在本节中,我们将了解网格上的高级纹理。不同的纹理如下所示-
立方体纹理 镜像和凹凸纹理 视频纹理
让我们对网格应用一些复杂的纹理——镜像、凹凸、视频和折射。
网格和描述
MeshHightlight Layer
Highlight 层用于突出场景中的网格。您可以为其赋予颜色,并将颜色应用于网格的边界。如果在游戏中要突出显示,可以使用网格突出显示层。
Morph a Mesh
变形通过某种过渡方式将对象的形状更改为另一个。我们已经看到了形状的可更新参数;否则,该参数设置为 false。对于变形,它设置为 true 并更新网格以更改形状。
Actions to Mesh
操作用于向网格添加交互。当您单击网格时,或者当网格相交或碰撞时会激活事件。
Mesh AssetsManager
使用assestsmanager 类,您可以在场景中加载网格、图像和二进制文件。
Import Mesh
我们将学习使用导入网格。
Mesh Morph Targets
我们已经看到了线条、带状、多边形等的变形。现在,我们将看到球体和框的变形在这个演示中。使用变形目标,球体的形状发生了变化,如下面的演示所示。
Mesh Instances
如果您想在场景中绘制相同的网格,请使用实例。
Mesh LOD & Instances
LOD 代表距离线。此功能允许您根据观察者的距离指定网格。随着从观察者到对象的距离增加,使用 LOD 可以清楚地显示网格的细节级别。
Mesh VolumemetricLightScatteringPost-process
这个过程散射光,如下面给出的输出所示。在浏览器中进行测试,您将看到光线如何通过网格散射。
Mesh EdgesRenderer
EdgesRendering 用于在网格周围绘制 egdes,如上面的输出所示。
Mesh BlendModes
您可以通过修改材质的 alphamode 来创建混合模式。
Mesh SolidParticles
实体粒子系统在网格上更新。我们在网格上看到的所有属性都可以用在固体粒子上。
Mesh FacetData
Facet 数据占用大量内存,默认不启用此功能。要启用它,我们需要根据需要创建一个网格并更新它的分面数据。
昵称: 邮箱:
Copyright © 2022 立地货 All Rights Reserved.
备案号:京ICP备14037608号-4