Advanced WebDev: comprensión de las colisiones y la física mediante la creación de una demostración genial de WebGL Babylon.js con Oimo.js

Advanced WebDev: comprensión de las colisiones y la física mediante la creación de una demostración genial de WebGL Babylon.js con Oimo.js

Hoy, me gustaría compartir con ustedes los conceptos básicos de colisiones, física y cuadros delimitadores jugando con WebGL babylon.js motor y un motor de física compañero llamado oimo.js. Aquí está la demostración que vamos a construir juntos: babylon.js Demostración de Espilit Physics con Oimo.js

Puedes lanzarlo en un Navegador compatible con WebGL—como IE11, Firefox, Chrome, Opera Safari 8 o Project Spartan en Windows 10 Technical Preview —luego, muévete dentro de la escena como en un juego FPS. Presione el «s» llave lanzar unas esferas/bolas y el b» llave para lanzar unas cajas. Con el mouse, puede hacer clic en una de las esferas o cuadros para aplicarle un poco de fuerza de impulso también.

Comprender las colisiones

Mirando la wikipedia Detección de colisiones definición, podemos leer que: “Detección de colisiones típicamente se refiere al problema computacional de detectar la intersección de dos o más objetos. Si bien el tema se asocia más a menudo con su uso en Juegos de vídeo y otra simulaciones físicastambién tiene aplicaciones en robótica. Además de determinar si dos objetos chocaron, los sistemas de detección de colisiones también pueden calcular el tiempo de impacto (TOI) e informar una variedad de contacto (el conjunto de puntos de intersección).[1]Respuesta de colisión trata de simular lo que sucede cuando se detecta una colisión (ver motor de física, física de muñeco de trapo). Resolver problemas de detección de colisiones requiere un uso extensivo de conceptos de álgebra lineal y geometría Computacional.“Descomprimamos ahora esa definición en un genial escena 3D que actuará como nuestra base de partida para este tutorial. Puedes moverte en este gran museo como lo harías en el mundo real. No se caerá por el suelo, atravesará las paredes ni volará. Estamos simulando la gravedad. Todo eso parece bastante obvio, pero requiere un montón de computación para simularlo en un mundo virtual 3D. La primera pregunta que debemos resolver cuando pensamos en la detección de colisiones es qué tan compleja debería ser. De hecho, probar si 2 mallas complejas están colisionando podría costar una gran cantidad de CPU, incluso más con un motor de JavaScript donde es complejo descargar eso en algo que no sea el subproceso de la interfaz de usuario. Para comprender mejor cómo gestionamos esta complejidad, navegue hasta el museo Espilit cerca de este escritorio:

Estás bloqueado por la mesa incluso si parece haber espacio disponible a la derecha. ¿Es un error en nuestro algoritmo de colisión? No, no lo es (¡babylon.js está libre de errores! ;-)). Es porque Michel Rousseau, el artista 3D que ha construido esta escena, lo ha hecho por elección. Para simplificar la detección de colisiones, ha utilizado un colisionador específico.

¿Qué es un colisionador?

En lugar de probar las colisiones contra las mallas detalladas completas, puede ponerlas en geometrías invisibles simples. Esos colisionadores actuarán como la representación de malla y serán utilizados por el motor de colisión en su lugar. La mayoría de las veces, no verá las diferencias, pero nos permitirá usar mucho menos CPU ya que las matemáticas detrás de eso son mucho más simples de calcular. Cada motor admite al menos 2 tipos de colisionadores: el cuadro delimitador y el esfera delimitadora. Lo entenderás mejor mirando esta imagen:


Extraído de: Visualización por computadora, Trazado de rayos, Videojuegos, Reemplazo de cajas delimitadoras

Esta hermosa baraja amarilla es la malla que se exhibirá. En lugar de probar las colisiones contra cada una de sus caras, podemos intentar insertarlo en la mejor geometría delimitadora. En este caso, una caja parece una mejor opción que una esfera para actuar como impostor de la malla. Pero la elección realmente depende de la propia malla. Volvamos a la escena de Espilit y mostremos el elemento delimitador invisible en un color rojo semitransparente:

Ahora puede comprender por qué no puede moverse por el lado derecho del escritorio. Es porque estás chocando (bueno, la cámara babylon.js está chocando) con esta caja. Si desea hacerlo, simplemente cambie su tamaño reduciendo el ancho para que se ajuste perfectamente al ancho del escritorio.

Nota: si desea comenzar a aprender babylon.js, puede seguir nuestro curso de formación gratuito en Microsoft Virtual Academy (MVA). Por ejemplo, puede saltar directamente al «Introducción a WebGL 3D con HTML5 y Babylon.js – Uso de Babylon.js para principiantes” donde cubrimos esta parte de colisión de Babylon.js. También puede echar un vistazo al código dentro de nuestra herramienta de juegos interactivos: Área de juegos de Babylon.js: muestra de colisiones. En función de la complejidad del motor de colisión o física, existen otros tipos de colisionadores disponibles: el cápsula y el malla por ejemplo.

Extraído de: Primeros pasos con Unity – Colliders y UnityScript

La cápsula es útil para humanos o humanoides ya que se adapta mejor a nuestro cuerpo que una caja o una esfera. La malla casi nunca es la malla completa en sí misma, sino que es una versión simplificada de la malla original a la que se dirige, pero sigue siendo mucho más precisa que una caja, una esfera o una cápsula.

Cargando la escena inicial

Para cargar nuestra escena Espilit, tienes varias opciones:

Opción 1: Descárguelo de nuestro repositorio GitHub, y luego siga el módulo Introducción a WebGL 3D con HTML5 y Babylon.js – Carga de activos de nuestro curso MVA para aprender a cargar una escena .babylon. Básicamente, debe alojar los activos y el motor Babylon.js en un servidor web y configurar los tipos MIME adecuados para la extensión .babylon.

opcion 2: Descargar esta solución de Visual Studio prefabricada (.archivo zip).

Nota: si no está familiarizado con Visual Studio, eche un vistazo a este artículo: Desarrolladores web, Visual Studio podría ser una gran herramienta gratuita para desarrollar con… Tenga en cuenta también que la versión Pro ahora es gratuita para muchos escenarios diferentes. se llama Edición de la comunidad de Visual Studio 2013. Por supuesto, aún puede seguir este tutorial si no desea usar Visual Studio. Aquí está el código para cargar nuestra escena. Recuerde que la mayoría de los navegadores son compatibles con WebGL ahora; recuerde prueba para Internet Explorer incluso en tu Mac.

/// 
var engine;
var canvas;
var scene;
document.addEventListener("DOMContentLoaded", startGame, false);
function startGame() {
    if (BABYLON.Engine.isSupported()) {
        canvas = document.getElementById("renderCanvas");
        engine = new BABYLON.Engine(canvas, true);
        BABYLON.SceneLoader.Load("Espilit/", "Espilit.babylon", engine, function (loadedScene) {
            scene = loadedScene;
   
            // Wait for textures and shaders to be ready
            scene.executeWhenReady(function () {
                // Attach camera to canvas inputs
                scene.activeCamera.attachControl(canvas);
                
                // Once the scene is loaded, just register a render loop to render it
                engine.runRenderLoop(function () {
                    scene.render();
                });
            });
        }, function (progress) {
            // To do: give progress feedback to user
        });
    }
}

Con este material, solo se beneficiará del motor de colisión integrado de Babylon.js. De hecho, estamos marcando una diferencia entre nuestro motor de colisión y un motor de física. El motor de colisión se dedica principalmente a que la cámara interactúe con la escena. Puede habilitar la gravedad o no en la cámara, puede habilitar el «comprobar colisión” en la cámara y en las distintas mallas. El motor de colisión también puede ayudarte a saber si dos mallas están colisionando. Pero eso es todo (¡esto ya es mucho!). El motor de colisión no generará acciones, fuerza o impulso después de que dos objetos de Babylon.js colisionen. Necesitas un motor de física para que le dé vida a los objetos. La forma en que hemos estado integrando la física en Babylon.js es a través de un mecanismo de complemento. Puedes leer mas al respecto aquí: Agregar su propio complemento de motor de física a babylon.js. Admitimos dos motores de física de código abierto: cañón.js y oimo.js. Oimo es ahora el motor de física predeterminado preferido. Si ha elegido “Opción 1” para cargar la escena, entonces necesitas para descargar Oimo.js de nuestro GitHub. Es una versión ligeramente actualizada que hemos creado para brindar una mejor compatibilidad con Babylon.js. Si ha elegido “opcion 2”, ya está referenciado y disponible en la solución VS bajo el “guiones” carpeta.

Habilitación del soporte de física en la escena y transformación de los colisionadores en impostores de física

Lo primero que debe hacer es habilitar la física en la escena. Para eso, agregue esta línea de código:

scene.enablePhysics(new BABYLON.Vector3(0, -10, 0), new BABYLON.OimoJSPlugin());
//scene.enablePhysics(new BABYLON.Vector3(0, -10, 0), new BABYLON.CannonJSPlugin());

Está configurando el nivel de gravedad (-10 en el eje Y en este código de muestra, que es más o menos como lo que tenemos en la Tierra) y el motor de física que le gustaría usar. Usaremos Oimo.js pero la línea comentada muestra cómo usar cannon.js. Ahora, necesitamos iterar a través de todos los colisionadores no visibles utilizados por el motor de colisión y activar las propiedades físicas en él. Para eso, simplemente necesita encontrar todas las mallas donde «checkCollisiones” se establece en verdadero pero no es visible en la escena:

for (var i = 1; i < scene.meshes.length; i++) {
    if (scene.meshes[i].checkCollisions && scene.meshes[i].isVisible === false) {
        scene.meshes[i].setPhysicsState(BABYLON.PhysicsEngine.BoxImpostor, { mass: 0, 
                                        friction: 0.5, restitution: 0.7 });
        meshesColliderList.push(scene.meshes[i]);
    }
}

Por favor declare el mallasColliderList además:

var meshesColliderList = [];

¡Y hemos terminado! Estamos listos para arrojar algunos objetos en nuestra escena y poner mucho desorden en este hermoso pero tranquilo museo.

Creación de esferas y cajas con estados físicos

Ahora vamos a agregar algunas esferas (con textura Amiga) y algunas cajas (con textura de madera) a la escena. Estas mallas tendrán un estado físico establecido. Por ejemplo, esto significa que rebotarán en el suelo si los lanzas al aire, rebotan entre ellos después de que se detecte una colisión, etc. El motor de física necesita saber qué tipo de impostor le gustaría usar para la malla (plano, esfera o caja hoy), la masa y las propiedades de fricción. Si ha elegido “Opción 1”, puedes descargar las 2 texturas aquí: fisicaassets.zip

Agregue este código a su proyecto:

function CreateMaterials() {
    materialAmiga = new BABYLON.StandardMaterial("amiga", scene);
    materialAmiga.diffuseTexture = new BABYLON.Texture("assets/amiga.jpg", scene);
    materialAmiga.emissiveColor = new BABYLON.Color3(0.5, 0.5, 0.5);
    materialAmiga.diffuseTexture.uScale = 5;
    materialAmiga.diffuseTexture.vScale = 5;
    materialWood = new BABYLON.StandardMaterial("wood", scene);
    materialWood.diffuseTexture = new BABYLON.Texture("assets/wood.jpg", scene);
    materialWood.emissiveColor = new BABYLON.Color3(0.5, 0.5, 0.5);
}
function addListeners() {
    window.addEventListener("keydown", function (evt) {
        // s for sphere
        if (evt.keyCode == 83) {
            for (var index = 0; index < 25; index++) {
                var sphere = BABYLON.Mesh.CreateSphere("Sphere0", 10, 0.5, scene);
                sphere.material = materialAmiga;
                sphere.position = new BABYLON.Vector3(0 + index / 10, 3, 5 + index / 10);
                sphere.setPhysicsState(BABYLON.PhysicsEngine.SphereImpostor, { mass: 1 });
            }
        }
        // b for box
        if (evt.keyCode == 66) {
            for (var index = 0; index < 10; index++) {
                var box0 = BABYLON.Mesh.CreateBox("Box0", 0.5, scene);
                box0.position = new BABYLON.Vector3(0 + index / 5, 3, 5 + index / 5);
                box0.material = materialWood;
                box0.setPhysicsState(BABYLON.PhysicsEngine.BoxImpostor, { mass: 4 });
            }
        }
    });
}

Puedes ver que las cajas son 4 más pesadas que las esferas.

Nota: si necesita comprender cómo funciona el material en babylon.js, observe este módulo: Introducción a WebGL 3D con HTML5 y Babylon.js: comprensión de los materiales y las entradas o juega con nuestra muestra específica de Playground: Babylon.js Playground – Muestra de materiales

Agregue estas 2 líneas de código después de la scene.enablePhysics línea:

CreateMaterials();
addListeners();

Y lanzar el proyecto web. Navega hasta el centro del museo y presiona más bien las teclas “s” o “b”. Obtendrás este divertido resultado:

Agregar soporte de selección para hacer clic en mallas

Agreguemos otra característica interesante: la capacidad de hacer clic en uno de los objetos para tirarlos. Para eso, necesitas enviar un rayo desde las coordenadas 2D del mouse dentro de la escena 3D, verifica si este rayo toca una de las mallas interesantes y, de ser así, aplica una fuerza de impulso sobre él para intentar moverlo.

Nota: para comprender cómo funciona la selección, consulte este módulo de MVA: Introducción a WebGL 3D con HTML5 y Babylon.js – Funciones avanzadas o juega con nuestra muestra en línea: Babylon.js Playground: muestra de recolección.

Agregue este código en el añadirOyentes() función:

canvas.addEventListener("mousedown", function (evt) {
    var pickResult = scene.pick(evt.clientX, evt.clientY, function (mesh) {
        if (mesh.name.indexOf("Sphere0") !== -1 || mesh.name.indexOf("Box0") !== -1) {
            return true;
        }
        return false;
    });
    if (pickResult.hit) {
        var dir = pickResult.pickedPoint.subtract(scene.activeCamera.position);
        dir.normalize();
        pickResult.pickedMesh.applyImpulse(dir.scale(1), pickResult.pickedPoint);
    }
});

Inicie su código en su navegador favorito. Ahora puedes hacer clic en tus mallas físicas para jugar con ellas.

Mostrar los cuadros delimitadores para comprender mejor toda la historia

Finalmente, vamos a crear una escena de depuración para permitirle mostrar/ocultar los colisionadores y activar/desactivar las propiedades físicas en ellos. Vamos a inyectar la interfaz de usuario en este div:

Y usaremos esta función para manejar la interfaz de usuario:

function CreateCollidersHTMLList() {
    var listColliders = document.getElementById("listColliders");
    for (var j = 0; j < meshesColliderList.length; j++) {
        var newLi = document.createElement("li");
        var chkVisibility = document.createElement('input');
        chkVisibility.type = "checkbox";
        chkVisibility.name = meshesColliderList[j].name;
        chkVisibility.id = "colvis" + j;
        var chkPhysics = document.createElement('input');
        chkPhysics.type = "checkbox";
        chkPhysics.name = meshesColliderList[j].name;
        chkPhysics.id = "colphysx" + j;
        (function (j) {
            chkVisibility.addEventListener(
             "click",
             function (event) {
                 onChangeVisibility(j, event);
             },
             false
           );
            chkPhysics.addEventListener(
            "click",
            function (event) {
                onChangePhysics(j, event);
            },
            false
            );
        })(j)
        newLi.textContent = meshesColliderList[j].name + " visibility/physx ";
        newLi.appendChild(chkVisibility);
        newLi.appendChild(chkPhysics);
        listColliders.appendChild(newLi);
    }
    function onChangeVisibility(id, event) {
        if (!meshesColliderList[id].isVisible) {
            meshesColliderList[id].isVisible = true;
            meshesColliderList[id].material.alpha = 0.75;
            meshesColliderList[id].material.ambientColor.r = 1;
        }
        else {
            meshesColliderList[id].isVisible = false;
        }
    }
    function onChangePhysics(id, event) {
        if (!meshesColliderList[id].checkCollisions) {
            meshesColliderList[id].checkCollisions = true;
            meshesColliderList[id].setPhysicsState(BABYLON.PhysicsEngine.BoxImpostor, { mass: 0, 
                                                   friction: 0.5, restitution: 0.7 });
        }
        else {
            meshesColliderList[id].checkCollisions = false;
            meshesColliderList[id].setPhysicsState(BABYLON.PhysicsEngine.NoImpostor);
        }
    }
}

Lo sé, genera una interfaz de usuario muy fea, pero era demasiado perezoso para dedicarle más tiempo. ¡Anímate a mejorarlo! 😛 Llame a esta nueva función y ejecute el proyecto web. Ahora, por ejemplo, mostrar los colisionadores 12 y 17:

También puede, con la segunda casilla de verificación, habilitar/deshabilitar las propiedades físicas. Por ejemplo, si desactivas las propiedades físicas en el colisionador 12 y lanzas las esferas, ¡ahora atravesarán esta pared! Esto se muestra en la siguiente captura de pantalla como la esfera rodeada por el cuadrado rojo:

Puede jugar con esta muestra de depuración directamente en su navegador aquí: Demostración de depuración de babylon.js Espilit Physics. Por favor, eche un vistazo a esta increíble demostración creada por Samuel Girardin que también usa Oimo.js en algunos personajes divertidos:

¡Espero que hayas disfrutado este tutorial! Siéntete libre de hacerme ping en Twitter en http://twitter.com/davrous para comentarlo. Este artículo es parte de la serie de tecnología de desarrollo web de Microsoft. Estamos emocionados de compartir proyecto espartano y es nuevo motor de renderizado contigo. Obtenga máquinas virtuales gratuitas o realice pruebas de forma remota en su dispositivo Mac, iOS, Android o Windows @ http:// moderno.ES.

(dpe)


#Advanced #WebDev #comprensión #las #colisiones #física #mediante #creación #una #demostración #genial #WebGL #Babylonjs #con #Oimojs

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada.