BabylonJS - Сетка

В этой главе мы научимся создавать различные формы с помощью построителя сетки. Мы уже узнали, как создавать формы в одной из наших предыдущих глав.

Разница в том, что с MeshBuilder вы можете добавлять цвета и изображения к фигурам.

CreateBox с помощью 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>

Выход

Приведенная выше строка кода генерирует следующий вывод -

В приведенном выше примере мы использовали изображение спрайта, как показано ниже. Он имеет 3 столбца по горизонтали и 2 ряда по вертикали.

В этой демонстрации мы использовали изображение под названием 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 = V снизу
  • z = Utop
  • w = Vtop

Векторы находятся в диапазоне [0, 1]. Ubottom и Vbottom - это двухмерные координаты левой нижней точки начала обрезки текстуры. 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>

Выход

Приведенная выше строка кода генерирует следующий вывод -

В этой демонстрации мы использовали изображение под названием 3d.png. Изображения хранятся в папке images / локально, а также вставлены ниже для справки. Обратите внимание: 3d.png - это изображение спрайта; изображение-спрайт - это набор изображений. Мы хотели показать изображение на кубе со всеми сторонами куба вместе. Вы также можете загрузить похожие изображения спрайтов на ваш выбор и использовать их в демонстрационной ссылке.

Текстура, используемая для коробки - images/3d.png

СеткаЦилиндр

В этом разделе мы увидим, как создать MeshCylinder.

Чтобы создать MeshCylinder, вам нужно использовать класс BABYLON.MeshBuilder.CreateCylinder.

Параметры для класса следующие:

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

Разница между CreateCylinder, использующим сетку, и meshbuilder заключается в том, что вы можете использовать параметры в 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 дает истину или ложь, если он пересекается с сеткой, указанной в переданном ему параметре.

Например,

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переменная - это вектор положения, равный 10 по оси x. Если сфера пересекает точку пересечения, цвет сферы меняется на черный.

BabylonJS - Столкновение при выборе сетки

Выбор столкновения фактически дает вам координаты, и вы можете разместить свою сетку в этом месте. Объект выбирается мышью, и вы можете просто разместить там, где вы щелкаете мышью. Считайте, что вам нужно разместить сетку (объект) в том месте, где пользователь щелкает мышью; Итак, с помощью выбора столкновения он помогает вам с координатами в позиции места, на которое щелкнули.

Демо

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

Raycast похожи на солнечные лучи и используются для проверки столкновения и пересечения в сцене.

Синтаксис

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

Параметры

Рассмотрим следующие параметры для raycast -

  • 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 с функцией предиката

Давайте теперь посмотрим, как работает 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 с функцией предиката помогает выбрать, какой меш мы хотим. Если мы не хотим, чтобы меш выбирался, мы можем проигнорировать то же самое.

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

Вышеупомянутая функция дает сетку, выбранную лучом. Если выбранная сетка box2, box или box5, она вернет false; в противном случае верно.

Вы можете попробовать приведенный выше пример для того же.

BabylonJS - сетка теней

Тени визуализируются в зависимости от того, как свет падает на созданную сетку. Они играют важную роль в обеспечении реалистичности изображения в трехмерном мире.

Давайте теперь узнаем, как создавать тени с помощью 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>

Выход

Приведенная выше строка кода генерирует следующий вывод -

Объяснение

Чтобы создать тени, вам нужно создать генератор теней. Рассмотрим пример, показанный ниже.

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. Изображения хранятся в папке images / локально. Вы можете скачать любое изображение на ваш выбор и использовать в демо-ссылке.

BabylonJS - Расширенные текстуры на сетках

В этом разделе мы узнаем о расширенных текстурах на сетках. Различные текстуры показаны ниже -

  • Текстура куба

  • Зеркальная и рельефная текстура

  • Видео Текстура

Применим к сетке сложную текстуру - зеркало, рельеф, видео и преломление.

Sr. No. Сетка и описание
1 Слой MeshHightlight

Слой Highlight используется для выделения сетки в сцене. Вы можете придать ему цвет, и цвет будет применен к границам сетки. В случае, если в игре вы хотите выделить подсветку, для этого можно использовать слой подсветки сетки.

2 Преобразовать сетку

Морфинг изменяет форму одного объекта на другой посредством некоторого перехода. Мы видели обновляемый параметр для фигур; в противном случае для параметра установлено значение false. Для морфинга устанавливается значение true, и сетка обновляется для изменения формы.

3 Действия с сеткой

Действия используются для добавления взаимодействия к сетке. События активируются, когда вы нажимаете на сетку или когда сетка пересекается или сталкивается.

4 Mesh AssetsManager

С помощью класса Assestsmanager вы можете загружать в сцену сетки, изображения и двоичные файлы.

5 Импортировать сетку

Мы научимся использовать Import Mesh.

6 Цели морфинга сетки

Мы уже видели морфинг линий, ленты, многоугольника и т. Д. Теперь мы увидим морфинг сферы и прямоугольника в этой демонстрации. С морфингом целей форма сферы изменяется, как показано в демонстрации ниже.

7 Экземпляры сетки

Если вы хотите рисовать идентичные сетки в своей сцене, используйте экземпляры.

8 Уровень детализации сети и экземпляры

LOD означает линию расстояния. Эта функция позволяет вам определять сетки в зависимости от расстояния до зрителя. По мере того как расстояние от зрителя до объекта увеличивается, уровень детализации сетки четко отображается с помощью LOD.

9 Сетка VolumemetricLightScatteringПост-процесс

Этот процесс рассеивает свет, как показано на выходе, приведенном ниже. Проверьте то же самое в браузере, и вы увидите, как свет рассеивается через сетку.

10 Mesh EdgesRenderer

EdgesRendering используется для рисования краев вокруг сетки, как показано в выходных данных выше.

11 Mesh BlendModes

Вы можете создать режим наложения, изменив альфа-режим материалов.

12 Сетка SolidParticles

Система SolidParticle обновляется на сетке. Все свойства, которые мы видели на сетке, можно использовать на твердой частице.

13 Сетка FacetData

Данные фасета занимают много памяти, и эта функция по умолчанию отключена. Чтобы включить его, нам нужно создать сетку по мере необходимости и обновить в нее данные фасетов.