WebGL Physics en Collision Detection met Babylon.js en Oimo.js

Vandaag wil ik de basisprincipes van botsingen, fysica en begrenzende vakken met je delen door te spelen met de WebGL Babylon.js-engine en een physics-motorgenoot genaamd Oimo.js.

Dit is de demo die we samen gaan bouwen: Babylon.js Espilit Physics-demo met Oimo.js.

Je kunt het starten in een WebGL-compatibele browser, zoals IE11, Firefox, Chrome, Opera, Safari 8 of Microsoft Edge in Windows 10 Technische Preview, en dan in de scène gaan zoals in een FPS-game. druk de s toets om een ​​paar bollen / ballen te lanceren en de b toets om een ​​aantal vakken te starten. Met uw muis kunt u ook op een van de bollen of vakken klikken om er wat impulskracht op uit te oefenen.

1. Botsingen begrijpen

Kijkend naar de definitie van de botsingdetectie van Wikipedia, kunnen we dat lezen: 

Botsingsdetectie verwijst meestal naar het computerprobleem van het detecteren van de kruising van twee of meer objecten. Hoewel het onderwerp meestal wordt geassocieerd met het gebruik ervan in videospellen en andere fysieke simulaties, het heeft ook toepassingen in robotica. Naast het bepalen of twee objecten zijn gebotst, kunnen botsingsdetectiesystemen ook de impacttijd (TOI) berekenen en een contactverdeelstuk rapporteren (de set kruisende punten)..Botsingsreactie gaat over het simuleren van wat er gebeurt als een botsing wordt gedetecteerd (zie fysica motor, ragdoll-fysica). Het oplossen van problemen met botsingsdetectie vereist uitgebreid gebruik van concepten uit lineaire algebra en computationele geometrie.

Laten we die definitie nu uitpakken in een coole 3D-scène die als uitgangspunt zal dienen voor deze zelfstudie.

Je kunt je verplaatsen in dit geweldige museum zoals je zou doen in de echte wereld. Je zult niet door de vloer vallen, door muren lopen of vliegen. We simuleren de zwaartekracht. Dat lijkt allemaal heel voor de hand liggend, maar het vereist een aantal berekeningen om dat te simuleren in een virtuele 3D-wereld. 

De eerste vraag die we moeten oplossen als we denken aan botsingsdetectie, is hoe complex het moet zijn. Inderdaad, testen of twee complexe meshes botsen, kan veel CPU kosten, nog meer met een JavaScript-engine, waar het complex is om dat uit te leveren aan iets anders dan de UI-thread.

Om beter te begrijpen hoe we deze complexiteit beheren, navigeert u naar het Espilit-museum in de buurt van dit bureau:

Je wordt geblokkeerd door de tabel, zelfs als er rechts wat ruimte beschikbaar lijkt te zijn. Is het een fout in ons botsingsalgoritme? Nee, dat is het niet (Babylon.js is vrij van bugs!). Het is omdat Michel Rousseau, de 3D-kunstenaar die deze scène heeft gebouwd, dit naar keuze heeft gedaan. Om de collision detection te vereenvoudigen, heeft hij een specifieke collider gebruikt.

Wat is een Collider?

In plaats van de botsingen te testen tegen de volledige gedetailleerde mazen, kunt u ze in eenvoudige onzichtbare geometrieën plaatsen. Deze colliders fungeren als mesh-weergave en worden in plaats daarvan gebruikt door de botsende motor. Meestal zul je de verschillen niet zien, maar het zal ons in staat stellen om veel minder CPU te gebruiken, omdat de wiskunde erachter veel eenvoudiger te berekenen is.

Elke motor ondersteunt ten minste twee soorten colliders: de begrenzende doos en de begrenzende bol. Je zult het beter begrijpen door naar deze foto te kijken:

Ontleend aan: computervisualisatie, Ray Tracing, videospellen, vervanging van grensdozen

Deze mooie gele eend is het te tonen net. In plaats van de botsingen tegen elk van zijn zijden te testen, kunnen we proberen deze in de beste begrenzingsgeometrie te plaatsen. In dit geval lijkt een box een betere keuze dan een bol om op te treden als de mesh impostor. Maar de keuze is echt afhankelijk van het gaas zelf.

Laten we teruggaan naar de scène van Espilit en het onzichtbare begrenzingselement weergeven in een semi-transparante rode kleur:

Je begrijpt nu waarom je niet aan de rechterkant van het bureau kunt bewegen. Het is omdat je botst (nou ja, de Babylon.js-camera botst) met deze doos. Als u dit wilt, hoeft u alleen de grootte ervan te wijzigen door de breedte te verlagen zodat deze perfect past op de breedte van het bureau.

Opmerking: als u Babylon.js wilt leren kennen, kunt u de gratis training bij Microsoft Virtual Academy (MVA) volgen. U kunt bijvoorbeeld direct naar Inleiding naar WebGL 3D springen met HTML5 en Babylon.js: Babylon.js gebruiken voor beginners waarbij we dit botsingsdeel van Babylon.js behandelen. Je kunt ook de code bekijken in onze interactieve speeltuin, Babylon.js-speelplaats: Collisions-voorbeeld.

Op basis van de complexiteit van de collision of physics engine zijn er andere soorten colliders beschikbaar: de capsule en de maas, bijvoorbeeld.

Afgenomen van: Aan de slag met Unity - Colliders & UnityScript

Capsule is nuttig voor mensen of mensachtigen omdat het beter bij ons lichaam past dan een doos of een bol. maas is bijna nooit het volledige gaas zelf, maar eerder een vereenvoudigde versie van het originele gaas dat u target, maar het is nog steeds veel preciezer dan een doos, een bol of een capsule.

2. De startscene laden

Om onze Espilit-scène te laden, hebt u verschillende opties:

Optie 1: Download het vanuit onze GitHub-repository en volg dan de Introduction to WebGL 3D met HTML5 en Babylon.js: Loading Assets-module van onze MVA-cursus om te leren hoe je een .babylon-scène kunt laden. Kortom, je moet de assets en de Babylon.js-engine hosten in een webserver en de juiste MIME-typen instellen voor de .babylon-extensie.

Optie 2: Download deze premade Visual Studio-oplossing (ZIP-bestand).  

Opmerking: als u onbekend bent met Visual Studio, bekijk dan dit artikel: Webontwikkelaars, Visual Studio kan een geweldige gratis tool zijn om te ontwikkelen met ... Let op: de Pro-versie is nu gratis voor veel verschillende scenario's. Het heet Visual Studio 2013 Community Edition.

Natuurlijk kunt u deze zelfstudie nog steeds volgen als u Visual Studio niet wilt gebruiken. Hier is de code om onze scène te laden. Houd er rekening mee dat de meeste browsers nu WebGL ondersteunen. Vergeet niet om te testen op Internet Explorer, zelfs op uw Mac.

///  var motor; var canvas; var scène; 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; // Wacht tot texturen en shaders gereed zijn scene.executeWhenReady (function () // Camera bijvoegen naar canvas-ingangen scene.activeCamera.attachControl (canvas); // Zodra de scène is geladen, registreert u gewoon een render-lus om deze te renderen engine.runRenderLoop (function () scene.render ();););, function (progress) // Te doen: feedback geven aan gebruiker);  

Met dit materiaal profiteert u alleen van de ingesloten botsingsmotor van Babylon.js. Inderdaad, we maken een verschil tussen onze botsingsmotor en een physics-engine. 

De botsingsmotor is meestal gericht op de camera die met de scène in wisselwerking staat. U kunt de zwaartekracht al dan niet inschakelen op de camera en u kunt de checkCollision optie op de camera en op de verschillende mazen. 

De botsingsmotor kan u ook helpen te weten of twee mazen botsen. Maar dat is alles (dit is eigenlijk al een heleboel!). De botsingsmotor zal geen acties, kracht of impuls genereren nadat twee Babylon.js-objecten in botsing komen. Daarvoor heb je een physics-engine nodig om het leven tot leven te brengen.

De manier waarop we de natuurkunde in Babylon.js hebben geïntegreerd, is via een plugin-mechanisme. Je kunt hier meer over lezen: Voeg je eigen physics engine-plugin toe aan Babylon.js. We ondersteunen twee open source physics-engines: Cannon.js en Oimo.js. Oimo is nu de standaardfysica-engine die de voorkeur geniet.

Als je optie 1 hebt gekozen om de scène te laden, moet je Oimo.js downloaden van onze GitHub. Het is een licht bijgewerkte versie die we hebben gemaakt om Babylon.js beter te ondersteunen. Als u Optie 2 hebt gekozen, wordt er al naar verwezen en is deze beschikbaar in de VS-oplossing onder de scripts map.

3. Fysieke ondersteuning in de scène mogelijk maken en medebewoners transformeren in natuurkunde-bedriegers

Het eerste wat je moet doen is om natuurkunde ter plekke in te schakelen. Voeg daarvoor deze regels toe:

scene.enableFysics (nieuwe BABYLON.Vector3 (0, -10, 0), nieuwe BABYLON.OimoJSPlugin ()); //scene.enableFysica (nieuwe BABYLON.Vector3 (0, -10, 0), nieuwe BABYLON.CannonJSPlugin ());

Je stelt het zwaartekrachtniveau in (-10 op de Y-as in deze voorbeeldcode, die min of meer lijkt op wat we op Aarde hebben) en de physics-engine die je wilt gebruiken. We gebruiken Oimo.js, maar de regel met commentaar laat zien hoe Cannon.js moet worden gebruikt.

Nu moeten we alle niet-zichtbare botsers die door de botsingsmotor worden gebruikt, doorlopen en fysische eigenschappen erop activeren. Daarvoor moet je gewoon alle mazen vinden waar checkCollisions ingesteld op waar maar niet zichtbaar in de scène:

voor (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]);  

Verklaar alstublieft de meshesColliderList ook:

var meshesColliderList = [];

En we zijn klaar! We zijn klaar om een ​​aantal objecten in onze scène te gooien en veel rotzooi in dit prachtige, maar veel te rustige museum te stoppen.

4. Spheres & Boxes maken met Physics States

We gaan nu enkele bollen (met een Amiga-textuur) en enkele kaders (met een houtstructuur) aan de scène toevoegen. 

Deze mazen hebben een fysische toestand ingesteld. Dit betekent bijvoorbeeld dat ze op de vloer stuiteren als je ze in de lucht laat vliegen, tussen hen door kaatst nadat een botsing is gedetecteerd, enzovoort. De physics engine moet weten welk type bedrieger je wilt gebruiken voor het gaas (vlak, bol of doos van vandaag), evenals de massa en wrijvingseigenschappen..

Als u Optie 1 hebt gekozen, kunt u de twee texturen hier downloaden.

Voeg deze code toe aan uw project:

function CreateMaterials () materialAmiga = new BABYLON.StandardMaterial ("amiga", scène); materialAmiga.diffuseTexture = new BABYLON.Texture ("assets / amiga.jpg", scène); materialAmiga.emissiveColor = nieuwe BABYLON.Color3 (0.5, 0.5, 0.5); materialAmiga.diffuseTexture.uScale = 5; materialAmiga.diffuseTexture.vScale = 5; materialWood = new BABYLON.StandardMaterial ("wood", scène); materialWood.diffuseTexture = new BABYLON.Texture ("assets / wood.jpg", scène); materialWood.emissiveColor = nieuwe BABYLON.Color3 (0.5, 0.5, 0.5);  function addListeners () window.addEventListener ("keydown", function (evt) // s voor 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 );   ); 

Je kunt zien dat vakken een factor zwaarder zijn dan de bollen 4.

Opmerking: als je wilt begrijpen hoe materiaal werkt in Babylon.js, bekijk dan de module Introduction to WebGL 3D met HTML5 en Babylon.js: Materialen en ingangen begrijpen, of speel met ons speciale Playground-voorbeeld, Babylon.js Playground: Materials-voorbeeld.

Voeg deze twee regels code toe na de scene.enablePhysics lijn:

CreateMaterials (); addListeners ();

En start het webproject. Navigeer naar het centrum van het museum en druk op de s of b sleutels. Je krijgt dit leuke resultaat:

5. Ondersteuning voor picken toevoegen aan klikken op mazen

Laten we nog een leuke functie toevoegen: de mogelijkheid om op een van de objecten te klikken om deze weg te gooien. Daarvoor moet je een straal sturen vanuit de 2D-coördinaten van de muis in de 3D-scène, controleren of deze straal een van de interessante mazen raakt, en in dat geval een impulskracht erop toepassen om te proberen deze te verplaatsen.

Opmerking: om te begrijpen hoe picking werkt, raadpleegt u de MVA-module Inleiding tot WebGL 3D met HTML5 en Babylon.js: geavanceerde functies. Of speel met onze online sample, Babylon.js Playground: Picking sample.

Voeg deze code toe aan de addListeners () functie:

canvas.addEventListener ("mousedown", functie (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););

Start uw code in uw favoriete browser. U kunt nu klikken op uw fysieke meshes om ermee te spelen.

6. De begrenzingsboxen weergeven om het hele verhaal beter te begrijpen

Ten slotte gaan we een foutopsporingsscenario maken om de botsers te laten zien / verbergen en de fysica-eigenschappen op hen te activeren / deactiveren..

We gaan de gebruikersinterface in deze div injecteren:

En we zullen deze functie gebruiken om de gebruikersinterface te verwerken:

function CreateCollidersHTMLList () var listColliders = document.getElementById ("listColliders"); voor (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);   

Ik weet het, het genereert een erg lelijke gebruikersinterface, maar ik was te lui om er meer tijd aan te besteden. Voel je vrij om het te verbeteren!

Noem deze nieuwe functie en start het webproject. Toon nu bijvoorbeeld de colliders 12 en 17:

U kunt ook met het tweede selectievakje de fysische eigenschappen inschakelen / uitschakelen. Als je bijvoorbeeld de physics-eigenschappen op collider 12 uitschakelt en de bollen start, gaan ze nu door deze muur! Dit wordt in de volgende schermafbeelding getoond als de bol omgeven door het rode vierkant:

Je kunt met dit foutopsporingsvoorbeeld direct in je browser spelen: Babylon.js Espilit Physicsdebug-demo.

Bekijk ook deze geweldige demo gebouwd door Samuel Girardin die Oimo.js ook op een aantal grappige karakters gebruikt:

Ik hoop dat je deze tutorial leuk vond! Je kunt me op Twitter pingen om commentaar te geven of gebruik het onderstaande opmerkingenveld.

Dit artikel maakt deel uit van de web dev tech-serie van Microsoft. We zijn verheugd om te delen Microsoft Edge en het nieuwe EdgeHTML-renderingengine met jou. Download gratis virtuele machines of test op afstand op uw Mac, iOS, Android of Windows-apparaat @ http://dev.modern.ie/.