BabylonJS - Malha
Neste capítulo, aprenderemos a criar diferentes formas usando o construtor de malha. Já aprendemos como criar formas em um de nossos capítulos anteriores.
A diferença é que com meshbuilder você tem a flexibilidade de adicionar cores e imagens às formas.
CreateBox usando MeshBuilder
Vamos agora ver como criar uma caixa usando o MeshBuilder.
Demo
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(0, 0, 1);
var camera = new BABYLON.ArcRotateCamera("Camera", 1, 0.8, 10, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
var 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>
Resultado
A linha de código acima gera a seguinte saída -
Para o exemplo acima, usamos uma imagem de sprite conforme mostrado abaixo. Possui 3 colunas na horizontal e 2 linhas na vertical.
Nesta demonstração, usamos uma imagem chamada cube.png. As imagens são armazenadas em imagens / pasta localmente e também são coladas abaixo para referência. Observe que o cube.png é uma imagem de sprite, uma imagem de sprite é uma coleção de imagens. Queríamos mostrar a imagem em um cubo, por isso queríamos todos os lados do cubo juntos. Você também pode baixar imagens de sprites semelhantes de sua escolha e usar no link de demonstração.
O construtor createBox oferece opções para os tamanhos.
Por exemplo,
var box = BABYLON.MeshBuilder.CreateBox("box", options, scene);
Demo
var hSpriteNb = 3; // 3 sprites per raw ie colums horizontally as shown in the image
var vSpriteNb = 2; // 2 sprite raws as shown in the image above.
var faceUV = new Array(6); // the cube has 6 sides so creating array for same.
for (var i = 0; i < 6; i++) {
faceUV[i] = new BABYLON.Vector4(i/hSpriteNb, i/vSpriteNb, (i+1)/hSpriteNb, (i+1)/vSpriteNb);
}
var options = {
width: 1.5,
height: 1.5,
depth: 1.5,
faceUV: faceUV
};
Isso é chamado de aplicação de texturas ao construtor de malha usando o método createBox. Nós usamos a imagem cube.png que tem 3 colunas na horizontal e 2 linhas na vertical. O cubo ou caixa tem 6 lados.
Para aplicar texturas, estamos usando o parâmetro de opções. Por exemplo,
Var box = BABYLON.MeshBuilder.CreateBox ('box', options, scene);
Definimos uma matriz chamada faceUV com tamanho 6, que são os lados do cubo. Este array sempre terá elementos Vector4. Cada Vector4 (x, y, z, w) será definido da seguinte forma -
- x = Ubottom
- y = Vbottom
- z = Utop
- w = Vtop
Os vetores estão no intervalo [0, 1]. Ubottom e Vbottom são as coordenadas 2D do ponto inferior esquerdo de onde o corte de textura começa. Utop, Vtop são os pontos superiores direitos onde termina o corte de textura.
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);
}
Suponha que a textura padrão, ou seja, a imagem dada é aplicada a todas as faces da caixa. Se você quiser alterar apenas 1 face ou 1 lado da caixa, pode atribuir diretamente os valores conforme mostrado abaixo -
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);
Exemplo
<!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>
Resultado
A linha de código acima gera a seguinte saída -
Nesta demonstração, usamos uma imagem chamada 3d.png. As imagens são armazenadas em imagens / pasta localmente e também são coladas abaixo para referência. Observe que 3d.png é uma imagem de sprite; uma imagem sprite é uma coleção de imagens. Queríamos mostrar a imagem em um cubo com todos os lados do cubo juntos. Você também pode baixar imagens de sprites semelhantes de sua escolha e usar no link de demonstração.
Textura usada para caixa - images/3d.png
MeshCylinder
Nesta seção, veremos como criar MeshCylinder.
Para criar MeshCylinder, você precisa usar a classe BABYLON.MeshBuilder.CreateCylinder.
Os parâmetros da classe são os seguintes -
var meshcylinder = BABYLON.MeshBuilder.CreateCylinder("meshcylinder", {
height: 3,
diameter: 35,
tessellation: 52
}, scene);
A diferença entre CreateCylinder usando mesh e meshbuilder é - você pode usar opções no meshbuilder. No momento, estamos usando altura, diâmetro e mosaico como opções a serem passadas para o cilindro. Estamos usando material padrão com wireframe como material para esta malha. Verifique a saída no navegador e veja o cilindro. Você pode usar uma estrutura semelhante em seu jogo como uma roda girando na cena.
Demo
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>Babylon.js demo - Mesh Builder</title>
<script src = "babylon.js"></script>
<style>
html,body,canvas { margin: 0; padding: 0; width: 100%; height: 100%; font-size: 0; }
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(0.8, 0.8, 0.8);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 6, 1.3, 40, new BABYLON.Vector3(0, -3, 0), scene);
var 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>
Resultado
A linha de código acima gera a seguinte saída -
Uma série de formas criadas com o construtor de malha agora serão usadas juntas em uma demonstração. As formas cobertas no link de demonstração abaixo estão listadas nas seções subsequentes.
Ground
Cone
Plane
Disc
Torus
Polyhedron
IcoSphere
BabylonJS - Ponto e Intersecção de Malha
A interseção de malha em jogos é importante porque você sabe o que precisa ser feito quando dois objetos se cruzam em um jogo. O mesmo conceito é explicado na demonstração abaixo sobre o evento que precisa ser capturado quando as malhas se cruzam.
Na demonstração abaixo, cobrimos os dois conceitos a seguir -
- Intersect Mesh
- Ponto de intersecção
<!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>
Resultado
O código acima gera a seguinte saída -
Explicação
Com o código acima, criamos um cilindro com wireframe como verdadeiro. Criamos 3 esferas. A cor original da esfera é verde.
No scene.registerBeforeRender função, vamos mudar a cor da esfera com base na interseção com a malha que é o cilindro aqui.
Considere o seguinte código em 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 fornece verdadeiro ou falso se houver interseção com a malha fornecida no parâmetro passado a ele.
Por exemplo,
balloon1.intersectsMesh(cone, false); //cone refers to the cylinder mesh here.
A cor da esfera é alterada para vermelho e se cruza com o cilindro; caso contrário, é verde.
O código a seguir é usado para o ponto de intersecção -
var pointToIntersect = new BABYLON.Vector3(10, 0, 0);
if (balloon3.intersectsPoint(pointToIntersect)) {
balloon3.material.emissiveColor = new BABYLON.Color3(0, 0, 0);
}
Aqui, pointtoIntersectvariável é o vetor de posição que é 10 no eixo x. Se a esfera cruzar o ponto de intersecção, a cor da esfera será alterada para preto.
BabylonJS - Colisão MeshPicking
A colisão de seleção na verdade fornece as coordenadas e você pode posicionar sua malha nesse lugar. O objeto é escolhido pelo mouse e você pode apenas colocá-lo onde clicar com o mouse. Considere que você precisa colocar uma malha (objeto) em um local onde o usuário clica com o mouse; então, com a ajuda de colisão de seleção, ele ajuda você com as coordenadas na posição do local clicado.
Demo
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(1, 1, 1);
// setup environment
var 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>
Resultado
Explicação
No exemplo acima, usamos um plano e 2 esferas. Para gerar essa saída, use o seguinte código -
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;
}
}
};
O evento scene.onPointerDown dá a você o -x, y e z coordenado que em nosso exemplo é pickResult.
Ele dá pickResult.hit como verdadeiro se você clicar na malha de solo. Consideramos segundos ímpares / pares e alteramos a posição da esfera para escolher as coordenadas zey do resultado, conforme mostrado acima. Assim que a posição for alterada, a esfera é colocada onde você clica e posiciona o mouse. Você pode tentar a demonstração acima para o mesmo.
BabylonJS - Raycasts
Raycasts são como raios de sol e são usados para verificar colisões e interseções na cena.
Sintaxe
var ray = new BABYLON.Ray(origin, direction, length);
Parâmetros
Considere os seguintes parâmetros para raycasts -
Origin - Local onde o raio começará.
Direction - A direção para o raio é calculada da seguinte forma -
var forward = new BABYLON.Vector3(0,0,1);
forward = vecToLocal(forward, box);
var direction = forward.subtract(origin);
Então, para obter a direção, subtraímos da origem, a posição da caixa -
Length - Comprimento do raio.
Demo
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
var 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>
Resultado
A linha de código acima gera a seguinte saída -
Explicação
Há uma caixa principal no centro que atua como um raycast. No momento em que aponta para qualquer uma das caixas, o tamanho da caixa aumentará. Este conceito se mostra útil durante os jogos para saber qual outro objeto está entrando em contato e as ações necessárias podem ser tomadas.
Adicionando box.isPickable = false;de modo que a caixa principal no centro não é considerada. Se você não quiser que nenhum objeto seja incluído nos raios para entrar em contato, adicionebox.isPickable = false; para isso.
O código a seguir adiciona a escala da caixa que é selecionada pelo raio.
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); cria um raio e assume a posição da caixa principal como origem.
A direção do raio é calculada da seguinte forma -
var forward = new BABYLON.Vector3(0,0,1);
forward = vecToLocal(forward, box);
var direction = forward.subtract(origin);
Então, para obter a direção, subtraímos da origem, a posição da caixa. A funçãovecToLocal é projetado para transformar uma posição do ponto de vista da malha multiplicando um vetor pela matriz da malha.
Conseguimos o ponto de vida do raio usando var hit = scene.pickWithRay(ray);
Ele fornece a posição onde o raio coincide com a malha.
A escala é aplicada à malha que é escolhida executando a seguinte linha de código -
if (hit.pickedMesh) {
hit.pickedMesh.scaling.y += 0.01;
}
Experimente o exemplo acima no navegador para ver o resultado.
Raycast com função de predicado
Vamos agora ver como funciona o raycast com função de predicado e a direção mostrada com rayhelper.
Demo
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
var 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>
Resultado
A linha de código acima gera a seguinte saída -
Explicação
Raycast com função de predicado ajuda a escolher qual malha queremos. Se não quisermos que uma malha seja escolhida, podemos ignorar a mesma.
function predicate(mesh) {
if (mesh == box2 || mesh == box || mesh == box5) {
return false;
}
return true;
}
A função acima fornece a malha que é selecionada pelo raio. Se a malha selecionada for box2, box ou box5, ela retornará false; caso contrário, é verdade.
Você pode tentar o exemplo acima para o mesmo.
BabylonJS - sombras em malha
As sombras são renderizadas com base na forma como a luz incide na malha criada. Eles desempenham um papel importante para fazer com que a saída pareça realista no mundo 3D.
Vamos agora aprender como criar sombras usando babylonjs.
Sintaxe
var shadowGenerator00 = new BABYLON.ShadowGenerator(shadowsize, light);
Parâmetros
Considere os seguintes parâmetros relacionados às sombras da malha -
Shadowsize - Tamanho da sombra.
Light - Luz usada na cena.
Demo
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(1, 1, 1);
var camera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 20, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
// 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>
Resultado
A linha de código acima gera a seguinte saída -
Explicação
Para criar sombras, você precisa criar o shadowgenerator. Considere um exemplo mostrado abaixo.
var shadowGenerator00 = new BABYLON.ShadowGenerator(512, light);
Para definir a malha para a qual a sombra é necessária, você precisa adicionar a mesma ao gerador acima.
shadowGenerator00.getShadowMap().renderList.push(box);
Agora, criamos um chão e uma caixa em cima dele. Queremos que a sombra da caixa caia no chão. Para fazer isso, precisamos ter certeza de que o solo está marcado para receber sombra, o que é feito da seguinte maneira -
ground01.receiveShadows = true;
Existem alguns filtros disponíveis para sombras, que são os seguintes -
shadowGenerator.usePoissonSampling = true; - Called Poisson sampling
shadowGenerator.useExponentialShadowMap = true; - Exponential Shadow Map
shadowGenerator.useBlurExponentialShadowMap= true; - Blur Exponential Shadow Map
Em nossa demonstração, usamos shadowGenerator00.useBlurExponentialShadowMap = true; Você pode experimentar os outros e ver como fica a saída.
Aqui, usamos uma imagem chamada gr1.jpg. As imagens são armazenadas nas imagens / pasta localmente. Você pode baixar qualquer imagem de sua escolha e usar no link de demonstração.
BabylonJS - Texturas Avançadas em Malhas
Nesta seção, aprenderemos sobre as texturas avançadas em malhas. As diferentes texturas são mostradas abaixo -
Textura Cube
Mirror and Bump Texture
Textura de Vídeo
Vamos aplicar algumas texturas complexas à malha - espelho, relevo, vídeo e refração.
Sr. Não. | Malha e descrição |
---|---|
1 | Camada MeshHightlight A camada de realce é usada para realçar a malha na cena. Você pode dar cor a ele e a cor é aplicada às bordas da malha. No caso de um jogo que você deseja realçar, a camada mesh hightlight pode ser usada para o mesmo. |
2 | Morph a Mesh Morphing muda a forma de um objeto para outro por algum meio de transição. Vimos o parâmetro atualizável para as formas; o parâmetro é definido como falso caso contrário. Para transformação, é definido como verdadeiro e a malha é atualizada para alterar a forma. |
3 | Ações para malha Ações são usadas para adicionar interação à malha. Os eventos são ativados quando você clica na malha ou quando a malha se cruza ou colide. |
4 | Mesh AssetsManager Com a classe assestsmanager, você pode carregar malhas, imagens e arquivos binários na cena. |
5 | Importar malha Usando Import Mesh vamos aprender. |
6 | Mesh Morph Targets Já vimos morfação de linhas, fita, polígono, etc. Agora, veremos metamorfose de esfera e caixa neste demo. Com os alvos de metamorfose, a forma da esfera é alterada, o que é visto na demonstração abaixo. |
7 | Instâncias de malha Se você quiser desenhar malhas idênticas em sua cena, use as instâncias. |
8 | Mesh LOD e instâncias LOD significa linha de distância. Este recurso permite que você especifique malhas com base na distância do visualizador. Conforme a distância do visualizador ao objeto aumenta, o nível de detalhe da malha é mostrado claramente usando LOD. |
9 | Malha VolumemetricLightScatteringPost-process Este processo espalha a luz conforme mostrado na saída fornecida abaixo. Teste o mesmo no navegador e você verá como a luz se espalha pela malha. |
10 | Mesh EdgesRenderer EdgesRendering é usado para desenhar egdes ao redor da malha, como mostrado na saída acima. |
11 | Mesh BlendModes Você pode criar um modo de mesclagem modificando o alphamode dos materiais. |
12 | Mesh SolidParticles SolidParticle System é atualizado em uma malha. Todas as propriedades que vimos em uma malha podem ser usadas na partilcle sólida. |
13 | Mesh FacetData Os dados da faceta ocupam muita memória e esse recurso não é habilitado por padrão. Para habilitá-lo, precisamos criar uma malha conforme necessário e atualizar os dados da faceta para ela. |