WebGL Fizica și detecția coliziunilor Utilizând Babylon.js și Oimo.js

Astăzi, aș dori să vă împărtășesc cu dvs. elementele de bază ale coliziunilor, fizicii și casetelor de margine, jucând cu motorul WebGL Babylon.js și cu un motor de computere numit Oimo.js.

Iată demo-ul pe care îl vom construi împreună: demo-ul Babylon.js Espilit Physics cu Oimo.js.

Puteți să-l lansați într-un browser compatibil WebGL, cum ar fi IE11, Firefox, Chrome, Opera, Safari 8 sau Microsoft Edge în previzualizarea tehnică Windows 10 și apoi să vă mutați în interiorul scenei ca într-un joc FPS. apasă pe s cheie pentru a lansa unele sfere / bile și b cheie pentru lansarea unor cutii. Folosind mouse-ul, poți de asemenea să dai clic pe una din sfere sau cutii pentru a aplica o forță de impuls asupra ei.

1. Înțelegerea coliziunilor

Privind definiția de detectare a coliziunii Wikipedia, putem citi: 

Detectarea coliziunii se referă în mod obișnuit la problema computațională de detectare a intersecției a două sau mai multe obiecte. În timp ce subiectul este cel mai adesea asociat cu utilizarea lui în jocuri video si altul simulări fizice, are, de asemenea, aplicații în robotică. În plus, pentru a determina dacă două obiecte s-au ciocnit, sistemele de detecție a coliziunii pot calcula și timpul de impact (TOI) și pot raporta o varietate de contacte (setul de puncte intersectate).Rezolvarea coliziunii se ocupă cu simularea a ceea ce se întâmplă atunci când se detectează o coliziune (a se vedea fizica motorului, ragdoll physics). Rezolvarea problemelor de detectare a coliziunilor necesită utilizarea pe scară largă a conceptelor algebră liniară și calcul geometrie.

Să dezarhivați această definiție într-o scenă 3D cool care va acționa ca bază de pornire pentru acest tutorial.

Puteți să vă mutați în acest mare muzeu așa cum ați face în lumea reală. Nu vei cădea prin podea, nu vei trece prin pereți sau nu vei zbura. Simulăm gravitatea. Toate acestea par destul de evidente, dar necesită o mulțime de calcul pentru a simula acest lucru într-o lume virtuală 3D. 

Prima întrebare pe care trebuie să o rezolvăm atunci când ne gândim la detectarea coliziunilor este cât de complexă ar trebui să fie. Într-adevăr, testarea faptului că două ochiuri complexe se ciocnesc ar putea costa o mulțime de CPU, chiar mai mult cu un motor JavaScript în cazul în care este complex pentru a descărca pe altceva decât firul UI.

Pentru a înțelege mai bine modul în care gestionăm această complexitate, navigați în muzeul Espilit lângă acest birou:

Ești blocat de masă, chiar dacă pare să existe un spațiu disponibil în partea dreaptă. Este un bug în algoritmul nostru de coliziune? Nu, nu este (Babylon.js este lipsit de bug-uri!). Este pentru că Michel Rousseau, artistul 3D care a construit această scenă, a făcut acest lucru prin alegere. Pentru a simplifica detectarea coliziunilor, a folosit un colizor specific.

Ce este un Collider?

În loc să testați coliziunile împotriva ochiurilor complete detaliate, le puteți pune în geometrii simple invizibile. Acești colizori vor acționa ca o reprezentare a ochiului de plasă și vor fi utilizați de motorul de coliziune. De cele mai multe ori, nu veți vedea diferențele, dar ne va permite să folosim mult mai puțin CPU, ca matematica din spatele căreia este mult mai simplu să calculați.

Fiecare motor suportă cel puțin două tipuri de colizoare: casetă de încadrare si sferă de legare. Veți înțelege mai bine uitandu-vă la această imagine:

Extracționat din: Vizualizarea computerului, Ray Tracing, Jocuri video, Înlocuirea cutiilor de legătură

Această rață frumoasă galbenă este plasa care trebuie afișată. În loc să testeze coliziunea împotriva fiecărei fețe, putem încerca să o inserăm în cea mai bună geometrie de legare. În acest caz, o cutie pare a fi o alegere mai bună decât o sferă care să acționeze ca un impostor de ochiuri. Dar alegerea într-adevăr depinde de plasa în sine.

Să ne întoarcem la scena Espilit și să afișăm elementul delimitat invizibil într-o culoare roșie semitransparentă:

Acum puteți înțelege de ce nu vă puteți mișca în partea dreaptă a biroului. Este pentru că vă ciocniți (bine, camera Babylon.js se ciocnește) cu această căsuță. Dacă doriți să faceți acest lucru, pur și simplu schimbați dimensiunea, scăzând lățimea pentru a se potrivi perfect lățimii biroului.

Notă: dacă doriți să începeți să învățați Babylon.js, puteți urma cursul gratuit de formare la Microsoft Virtual Academy (MVA). De exemplu, puteți sări direct la Introducere în WebGL 3D cu HTML5 și Babylon.js: Folosind Babylon.js pentru începători unde acoperim această parte a coliziunii a Babylon.js. Puteți, de asemenea, să aruncați o privire la codul din interiorul instrumentului nostru de joacă interactiv, pe terenul de joacă Babylon.js: Eșantion de coliziuni.

Pe baza complexității motorului de coliziune sau a fizicii, există și alte tipuri de agenți de coliziune disponibili: capsulă si plasă, de exemplu.

Extracționat de la: Noțiuni de bază cu Unitatea - Colliders & UnityScript

Capsulă este util pentru oameni sau umanoizi, deoarece se potrivește mai bine corpului nostru decât o cutie sau o sferă. Plasă este aproape niciodată plasa completă în sine - mai degrabă, este o versiune simplificată a rețelei originale pe care o vizați - dar este încă mult mai precisă decât o cutie, o sferă sau o capsulă.

2. Încărcarea scenei de pornire

Pentru a încărca scena noastră Espilit, aveți diferite opțiuni:

Opțiunea 1: Descărcați-l din depozitul nostru GitHub și apoi urmați modul Introducere în WebGL 3D cu ajutorul modulelor HTML5 și Babylon.js: Loading Assets al cursului nostru MVA pentru a afla cum să încărcați o scenă .babylon. Practic, trebuie să găzduiți activele și motorul Babylon.js într-un server web și setați tipurile de MIME adecvate pentru extensia .babylon.

Opțiunea 2: Descărcați această soluție premade Visual Studio (fișier .zip).  

Notă: Dacă nu sunteți familiarizați cu Visual Studio, aruncați o privire la acest articol: Dezvoltatorii Web, Visual Studio ar putea fi un instrument gratuit gratuit pentru dezvoltarea cu ... Vă rugăm să rețineți că versiunea Pro este acum gratuită pentru o mulțime de scenarii diferite. Este numit Visual Studio 2013 Community Edition.

Desigur, puteți continua acest tutorial dacă nu doriți să utilizați Visual Studio. Iată codul pentru a încărca scena noastră. Rețineți că majoritatea browserelor suportă WebGL acum - nu uitați să testați pentru Internet Explorer chiar și pe Mac.

///  motor var; vopsea var; var scenă; document.addEventListener ("DOMContentLoaded", startGame, false); funcția startGame () if (BABYLON.Engine.isSupported ()) canvas = document.getElementById ("renderCanvas"); motor = nou BABYLON.Engine (canvas, true); BABYLON.SceneLoader.Load ("Espilit /", "Espilit.babylon", motor, funcție (încărcatScene) scene = încărcateScene; // Așteptați ca texturile și shaderele să fie gata scene.executeWhenReady (funcția () pentru a intra în canvas scena.activeCamera.attachControl (canvas); // Odată ce scena este încărcată, trebuie doar să înregistrați o buclă de randare pentru ao reda motor.runRenderLoop (function () scene.render (););); funcția (progres) // Pentru a face: a oferi feedback utilizatorilor despre progres);  

Utilizând acest material, veți beneficia numai de motorul de coliziune încorporat al Babylon.js. Într-adevăr, facem o diferență între motorul nostru de coliziune și un motor de fizică. 

Motorul de coliziune este dedicat în principal camerei care interacționează cu scena. Puteți activa gravitatea sau nu pe cameră și puteți activa funcția checkCollision opțiune de pe camera foto și de pe diferite ochiuri. 

Motorul de coliziune vă poate ajuta să aflați dacă două ochiuri se ciocnesc. Dar asta e tot (acest lucru este deja mult, de fapt!). Motorul de coliziune nu va genera acțiuni, forță sau impuls după ce două obiecte Babylon.js se ciocnesc. Aveți nevoie de un motor de fizică pentru a aduce viață obiectelor.

Felul în care am integrat fizica în Babylon.js este printr-un mecanism de plugin. Puteți citi mai multe despre asta aici: Adăugarea propriului plugin pentru motorul fizicii la Babylon.js. Susținem două motoare de fizică open-source: Cannon.js și Oimo.js. Oimo este acum motorul fizic implicit preferat.

Dacă ați ales opțiunea 1 pentru a încărca scena, trebuie să descărcați Oimo.js din GitHub. Este o versiune ușor actualizată pe care am făcut-o pentru a susține mai bine Babylon.js. Dacă ați ales opțiunea 2, aceasta este deja menționată și disponibilă în soluția VS sub script-uri pliant.

3. Permiterea suportului fizic în scenă și transformarea coliziunilor în impostori de fizică

Primul lucru pe care trebuie să-l faceți este să activați fizica pe scenă. Pentru aceasta, adăugați următoarele rânduri de cod:

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

Stabiliți nivelul gravitației (-10 pe axa Y din acest cod de probă, care este mai mult sau mai puțin asemănător cu ceea ce avem pe Pământ) și motorul de fizică pe care doriți să îl utilizați. Vom folosi Oimo.js, dar linia comentată arată cum se utilizează Cannon.js.

Acum, trebuie să repetăm ​​toate coliziunile non-vizibile utilizate de motorul de coliziune și să acționăm proprietățile fizice pe acesta. Pentru asta, pur și simplu trebuie să găsești toate rețelele unde checkCollisions este setat sa Adevărat dar nu este vizibil în scenă:

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

Vă rugăm să declarați meshesColliderList de asemenea:

var meshesColliderList = [];

Și am terminat! Suntem gata să aruncăm niște obiecte în scena noastră și să punem mizerie în acest muzeu frumos, dar prea calm.

4. Crearea de sfere și cutii cu state fizice

Vom adăuga acum niște sfere (cu textura Amiga) și câteva cutii (cu textura lemnului) la fața locului. 

Aceste ochiuri vor fi setate de statul fizic. De exemplu, aceasta înseamnă că vor sări pe podea dacă le lansați în aer, săriți între ele după ce o coliziune a fost detectată și așa mai departe. Motorul fizic trebuie să știe ce tip de impostor doriți să utilizați pentru plasă (plan, sferă sau cutie astăzi), precum și proprietățile de masă și frecare.

Dacă ați ales opțiunea 1, puteți descărca cele două texturi aici.

Adăugați acest cod în proiectul dvs.:

funcția CreateMaterials () materialAmiga = nou BABYLON.StandardMaterial ("amiga", scenă); materialAmiga.diffuseTexture = nou BABYLON.Texture ("assets / amiga.jpg", scenă); materialAmiga.emissiveColor = nou BABYLON.Color3 (0,5, 0,5, 0,5); materialAmiga.diffuseTexture.uScale = 5; materialAmiga.diffuseTexture.vScale = 5; materialWood = nou BABYLON.StandardMaterial ("lemn", scenă); materialWood.diffuseTexture = nou BABYLON.Texture ("assets / wood.jpg", scenă); materialWood.emissiveColor = nou BABYLON.Color3 (0,5, 0,5, 0,5);  funcția addListeners () window.addEventListener ("keydown", funcția (evt) // s pentru sferă if (evt.keyCode == 83) pentru (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 );   ); 

Puteți vedea că cutiile sunt mai grele decât sferele cu un factor de 4.

Notă: Dacă trebuie să înțelegeți cum funcționează materialul în Babylon.js, vizionați modulul Introducere în WebGL 3D cu HTML5 și Babylon.js: Înțelegerea materialelor și intrărilor sau jucați cu eșantionul nostru dedicat Teren de joacă, Babylon.js Teren de joc: Eșantion de materiale.

Adăugați aceste două linii de cod după scene.enablePhysics linia:

CreateMaterials (); addListeners ();

Și lansați proiectul web. Navigați în centrul muzeului și apăsați pe s sau b chei. Veți obține acest rezultat amuzant:

5. Adăugarea suportului de selectare pentru a face clic pe ochiuri

Să adăugăm o altă caracteristică interesantă: abilitatea de a face clic pe unul dintre obiecte pentru al arunca. Pentru aceasta, trebuie să trimiteți o rază din coordonatele 2D ale mouse-ului în interiorul scenei 3D, să verificați dacă acest rază atinge una dintre ochiurile interesante și, dacă este așa, aplicați o forță impulsivă pe ea pentru a încerca să o mutați.

Notă: pentru a înțelege modul de funcționare a prelucrării, consultați modulul MVA Introducere în WebGL 3D cu HTML5 și Babylon.js: Caracteristici avansate. Sau jucați cu eșantionul nostru online, Babylon.js Playground: Picking sample.

Adăugați acest cod în addListeners () funcţie:

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

Lansați codul în browserul dvs. preferat. Acum puteți să faceți clic pe ochiurile fizice pentru a juca cu ei.

6. Afișarea cutiilor de legătură pentru a înțelege mai bine întreaga poveste

În cele din urmă, vom crea o scenă de depanare pentru a vă permite să afișați / ascundeți coliziunea și să activați / dezactivați proprietățile fizice pe ele.

Vom injecta UI în acest div:

Și vom folosi această funcție pentru a manipula interfața utilizator:

funcția CreateCollidersHTMLList () var listColliders = document.getElementById ("listColliders"); pentru (var j = 0; < 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);   

Știu, generează un UI foarte urât, dar eram prea leneș să-și petreacă mai mult timp pe el. Simțiți-vă liber să-l îmbunătățiți!

Sunați această nouă funcție și lansați proiectul web. Acum, de exemplu, afișați colizoarele 12 și 17:

Puteți, de asemenea, cu a doua casetă de selectare să activați / dezactivați proprietățile fizicii. De exemplu, dacă dezactivați proprietățile fizicii pe colizorul 12 și lansați sferele, acestea vor trece acum prin acest perete! Acest lucru este arătat în următoarea imagine de ecran ca sfera înconjurată de pătrat roșu:

Puteți juca cu acest eșantion de depanare direct în browserul dvs. aici: Babylon.js Espilit Physicsdebug demo.

Vă rugăm, de asemenea, să aruncați o privire la acest demo minunat construit de Samuel Girardin care utilizează, de asemenea, Oimo.js pe unele personaje amuzante:

Sper că v-ați bucurat de acest tutorial! Simțiți-vă liber să vă ping pe Twitter pentru a comenta acest lucru sau să utilizați câmpul de comentarii de mai jos.

Acest articol face parte din seriile de tehnologie web dev din Microsoft. Suntem încântați să împărtășim Microsoft Edge și noul EdgeHTML motor de randare cu tine. Obțineți mașini virtuale gratuite sau testați de la distanță pe dispozitivele Mac, iOS, Android sau Windows @ http://dev.modern.ie/.