WebGL-Physik und Kollisionserkennung mit Babylon.js und Oimo.js

Heute möchte ich Ihnen die Grundlagen von Kollisionen, Physik und Bounding-Boxen mitteilen, indem Sie mit der WebGL-Babylon.js-Engine und einem Physik-Engine-Begleiter namens Oimo.js spielen.

Hier ist die Demo, die wir zusammen bauen werden: Babylon.js Espilit Physics-Demo mit Oimo.js.

Sie können es in einem WebGL-kompatiblen Browser wie IE11, Firefox, Chrome, Opera 8, Safari 8 oder Microsoft Edge in der technischen Vorschau von Windows 10 starten und sich dann wie in einem FPS-Spiel innerhalb der Szene bewegen. Drücken Sie die s Taste zum Starten einiger Kugeln / Kugeln und der b Taste zum Starten einiger Boxen. Mit der Maus können Sie auch auf eine der Kugeln oder Kästchen klicken, um eine Impulskraft aufzubringen.

1. Kollisionen verstehen

Wenn wir die Definition der Wikipedia-Kollisionserkennung betrachten, können wir Folgendes lesen: 

Kollisionserkennung bezieht sich typischerweise auf das Rechenproblem des Erfassens der Schnittmenge von zwei oder mehr Objekten. Während das Thema am häufigsten mit seiner Verwendung in verbunden ist Videospiele und andere physikalische Simulationen, Es hat auch Anwendungen in Robotik. Zusätzlich zur Bestimmung, ob zwei Objekte kollidiert sind, können Kollisionserkennungssysteme auch die Aufprallzeit (TOI) berechnen und einen Kontaktverteiler (die Menge der Schnittpunkte) melden..Kollisionsreaktion befasst sich mit der Simulation, was passiert, wenn eine Kollision erkannt wird (siehe Physik-Engine, Ragdoll-Physik). Das Lösen von Kollisionserkennungsproblemen erfordert einen umfassenden Einsatz der Konzepte von Lineare Algebra und Berechnungsgeometrie.

Entpacken wir diese Definition nun in eine coole 3D-Szene, die als Ausgangspunkt für dieses Tutorial dient.

Sie können sich in diesem großartigen Museum wie in der realen Welt bewegen. Sie fallen nicht durch den Boden, gehen durch Wände oder fliegen nicht. Wir simulieren die Schwerkraft. All dies scheint ziemlich offensichtlich, aber es erfordert einige Berechnungen, um dies in einer virtuellen 3D-Welt zu simulieren. 

Die erste Frage, die wir beantworten müssen, wenn wir über die Kollisionserkennung nachdenken, ist, wie komplex sie sein sollte. Das Testen, ob zwei komplexe Netze kollidieren, könnte in der Tat sehr viel CPU-Kosten verursachen, insbesondere bei einer JavaScript-Engine, bei der es komplex ist, diese auf etwas anderem als dem UI-Thread abzulagern.

Um besser zu verstehen, wie wir mit dieser Komplexität umgehen, navigieren Sie in das Espilit Museum in der Nähe dieses Schreibtisches:

Sie werden vom Tisch blockiert, auch wenn auf der rechten Seite etwas Platz zur Verfügung steht. Ist es ein Fehler in unserem Kollisionsalgorithmus? Nein, es ist nicht so (Babylon.js ist fehlerfrei!). Dies liegt daran, dass Michel Rousseau, der 3D-Künstler, der diese Szene gebaut hat, dies durch Wahl getan hat. Um die Kollisionserkennung zu vereinfachen, hat er einen speziellen Kollider verwendet.

Was ist ein Collider??

Anstatt die Kollisionen mit den vollständigen detaillierten Netzen zu testen, können Sie sie in einfache unsichtbare Geometrien einfügen. Diese Kollisoren fungieren als Netzdarstellung und werden stattdessen von der Kollisions-Engine verwendet. Meistens werden Sie die Unterschiede nicht sehen, aber es wird uns erlauben, viel weniger CPU zu verwenden, da die Berechnung dahinter viel einfacher ist.

Jede Engine unterstützt mindestens zwei Arten von Collidern: die Begrenzungsfeld und das begrenzende Kugel. Sie werden es besser verstehen, wenn Sie dieses Bild betrachten:

Extrahiert aus: Computervisualisierung, Raytracing, Videospielen, Austausch von Begrenzungsboxen

Diese schöne gelbe Ente ist das Netz, das angezeigt werden soll. Anstatt die Kollisionen gegen jede ihrer Flächen zu testen, können wir versuchen, sie in die beste Begrenzungsgeometrie einzufügen. In diesem Fall scheint eine Box eine bessere Wahl zu sein als eine Kugel, die als Netzstopfer fungiert. Die Wahl hängt jedoch wirklich vom Netz selbst ab.

Gehen wir zurück zur Espilit-Szene und zeigen das unsichtbare Begrenzungselement in einer halbtransparenten roten Farbe an:

Sie können jetzt verstehen, warum Sie sich nicht auf der rechten Seite des Schreibtisches bewegen können. Dies liegt daran, dass Sie mit dieser Box kollidieren (na ja, die Kamera Babylon.js kollidiert). Wenn Sie dies tun möchten, ändern Sie einfach die Größe, indem Sie die Breite verringern, um sie perfekt an die Breite des Schreibtisches anzupassen.

Hinweis: Wenn Sie anfangen möchten, Babylon.js zu lernen, können Sie an dem kostenlosen Schulungskurs bei Microsoft Virtual Academy (MVA) teilnehmen. Sie können zum Beispiel direkt zu Einführung in WebGL 3D mit HTML5 und Babylon.js springen: Babylon.js für Anfänger verwenden, wo wir diesen Kollisionsteil von Babylon.js behandeln. Sie können sich auch den Code in unserem interaktiven Spielplatz-Tool Babylon.js Spielplatz: Kollisionen ansehen.

Je nach Komplexität der Kollisions- oder Physik-Engine stehen andere Arten von Kollidern zur Verfügung: die Kapsel und das Mesh, zum Beispiel.

Auszug aus: Erste Schritte mit Unity - Colliders & UnityScript

Kapsel ist nützlich für Menschen oder Humanoide, da sie besser zu unserem Körper passt als eine Box oder Kugel. Mesh ist fast nie das komplette Netz selbst - eher eine vereinfachte Version des ursprünglichen Netzes, auf das Sie abzielen -, aber es ist immer noch viel genauer als eine Box, eine Kugel oder eine Kapsel.

2. Laden der Startszene

Um unsere Espilit-Szene zu laden, haben Sie verschiedene Möglichkeiten:

Option 1: Laden Sie es aus unserem GitHub-Repository herunter, und befolgen Sie die Einführung in WebGL 3D mit HTML5 und Babylon.js: Loading Assets-Modul unseres MVA-Kurses, um zu lernen, wie Sie eine .babylon-Szene laden. Grundsätzlich müssen Sie die Assets und die Babylon.js-Engine auf einem Webserver hosten und die richtigen MIME-Typen für die Erweiterung .babylon festlegen.

Option 2: Laden Sie diese vorinstallierte Visual Studio-Lösung herunter (ZIP-Datei).  

Hinweis: Wenn Sie mit Visual Studio nicht vertraut sind, werfen Sie einen Blick auf diesen Artikel: Webentwickler, Visual Studio könnte ein tolles kostenloses Tool zum Entwickeln sein. Beachten Sie auch, dass die Pro-Version jetzt für viele verschiedene Szenarien kostenlos ist. Es heißt Visual Studio 2013 Community Edition.

Natürlich können Sie diesem Lernprogramm trotzdem folgen, wenn Sie Visual Studio nicht verwenden möchten. Hier ist der Code zum Laden unserer Szene. Denken Sie daran, dass die meisten Browser jetzt WebGL unterstützen. Denken Sie daran, den Internet Explorer auch auf Ihrem Mac zu testen.

///  Var-Motor; var Leinwand; var szene; 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, Funktion (loadedScene) scene = loadedScene; // Warten, bis Texturen und Shader bereit sind scene.executeWhenReady (function () // Kamera anhängen) Zeichenflächeneingaben scene.activeCamera.attachControl (Zeichenfläche); // Sobald die Szene geladen ist, registrieren Sie einfach eine Render-Schleife, um sie zu rendern. function (progress) // To do: Rückmeldung an den Benutzer geben);  

Wenn Sie dieses Material verwenden, profitieren Sie nur von der eingebetteten Kollisions-Engine von Babylon.js. In der Tat machen wir einen Unterschied zwischen unserer Kollisionsmaschine und einer Physikmaschine. 

Die Kollisionsmaschine ist hauptsächlich für die Kamera vorgesehen, die mit der Szene interagiert. Sie können die Schwerkraft in der Kamera aktivieren oder nicht, und Sie können das aktivieren checkCollision Option an der Kamera und an den verschiedenen Maschen. 

Die Kollisionsengine kann Ihnen auch helfen zu wissen, ob zwei Maschen kollidieren. Aber das ist alles (das ist schon viel!). Die Kollisions-Engine generiert keine Aktionen, keine Kraft oder keinen Impuls, nachdem zwei Babylon.js-Objekte kollidieren. Sie benötigen dafür eine Physik-Engine, um die Objekte zum Leben zu erwecken.

Die Art, wie wir Physik in Babylon.js integriert haben, erfolgt über einen Plugin-Mechanismus. Mehr darüber erfahren Sie hier: Hinzufügen eines eigenen Plugins für Physik-Module zu Babylon.js. Wir unterstützen zwei Open-Source-Physik-Engines: Cannon.js und Oimo.js. Oimo ist jetzt die bevorzugte Standard-Physik-Engine.

Wenn Sie Option 1 zum Laden der Szene gewählt haben, müssen Sie Oimo.js von unserem GitHub herunterladen. Es ist eine leicht aktualisierte Version, die wir zur besseren Unterstützung von Babylon.js erstellt haben. Wenn Sie sich für Option 2 entschieden haben, wird dies bereits in der VS-Lösung unter der Option "Referenz" angegeben Skripte Mappe.

3. Aktivieren der Physikunterstützung in der Szene und Verwandeln von Collidern in Impulse für Physik

Zuerst müssen Sie die Physik auf der Bühne aktivieren. Dazu fügen Sie bitte folgende Codezeilen hinzu:

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

Sie richten die Schwerkraftstufe ein (-10 auf der Y-Achse in diesem Beispielcode (der mehr oder weniger dem entspricht, was wir auf der Erde haben) und der Physik-Engine, die Sie verwenden möchten. Wir werden Oimo.js verwenden, aber die kommentierte Zeile zeigt, wie Cannon.js verwendet wird.

Jetzt müssen wir alle nicht sichtbaren Kollider durchlaufen, die von der Kollisions-Engine verwendet werden, und die physikalischen Eigenschaften für sie aktivieren. Dafür müssen Sie einfach alle Netze wo finden checkCollisions ist eingestellt auf wahr aber nicht sichtbar in der Szene:

für (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]);  

Bitte erkläre das meshesColliderList ebenfalls:

var meshesColliderList = [];

Und wir sind fertig! Wir sind bereit, einige Objekte in unsere Szene zu werfen und in diesem wunderschönen, aber viel zu ruhigen Museum viel Durcheinander zu stecken.

4. Erstellen von Kugeln und Boxen mit physikalischen Zuständen

Wir werden jetzt einige Kugeln (mit Amiga-Textur) und einige Kästchen (mit Holzstruktur) zur Szene hinzufügen. 

Für diese Netze wird der Physikstatus festgelegt. Dies bedeutet beispielsweise, dass sie auf dem Boden abprallen, wenn Sie sie in der Luft starten, zwischen ihnen springen, nachdem eine Kollision erkannt wurde, und so weiter. Die Physik-Engine muss wissen, welche Art von Betrüger Sie für das Netz (Ebene, Kugel oder Box heute) sowie die Masse und die Reibungseigenschaften verwenden möchten.

Wenn Sie sich für Option 1 entschieden haben, können Sie die beiden Texturen hier herunterladen.

Fügen Sie diesen Code Ihrem Projekt hinzu:

Funktion CreateMaterials () materialAmiga = new BABYLON.StandardMaterial ("amiga", Szene); materialAmiga.diffuseTexture = new BABYLON.Texture ("assets / amiga.jpg", Szene); materialAmiga.emissiveColor = new BABYLON.Color3 (0,5, 0,5, 0,5); materialAmiga.diffuseTexture.uScale = 5; materialAmiga.diffuseTexture.vScale = 5; materialWood = new BABYLON.StandardMaterial ("Holz", Szene); materialWood.diffuseTexture = new BABYLON.Texture ("assets / wood.jpg", Szene); materialWood.emissiveColor = new BABYLON.Color3 (0,5, 0,5, 0,5);  function addListeners () window.addEventListener ("keydown", function (evt) // s für Sphäre if (evt.keyCode == 83) für (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 );   ); 

Sie sehen, dass Boxen um den Faktor 1 schwerer sind als die Kugeln 4.

Hinweis: Wenn Sie wissen möchten, wie das Material in Babylon.js funktioniert, schauen Sie sich das Modul Einführung in WebGL 3D mit HTML5 und Babylon.js: Material und Eingaben an oder spielen Sie mit unserem speziellen Playground-Beispiel, Babylon.js Playground: Materials-Beispiel.

Fügen Sie diese beiden Codezeilen nach dem hinzu scene.enablePhysics Linie:

CreateMaterials (); addListeners ();

Und starten Sie das Webprojekt. Navigieren Sie zur Mitte des Museums und drücken Sie die s oder b Schlüssel. Sie erhalten dieses unterhaltsame Ergebnis:

5. Hinzufügen von Kommissionierunterstützung zum Klicken auf Maschen

Fügen wir eine weitere coole Funktion hinzu: Die Fähigkeit, auf eines der Objekte zu klicken, um es wegzuwerfen. Dazu müssen Sie einen Strahl aus den 2D-Koordinaten der Maus in die 3D-Szene senden, prüfen, ob dieser Strahl eines der interessanten Netze berührt, und falls ja, eine Impulskraft auf ihn anwenden, um zu versuchen, ihn zu verschieben.

Hinweis: Um zu verstehen, wie die Kommissionierung funktioniert, lesen Sie bitte das MVA-Modul Einführung in WebGL 3D mit HTML5 und Babylon.js: Erweiterte Funktionen. Oder spielen Sie mit unserem Online-Beispiel Babylon.js Playground: Picking sample.

Fügen Sie diesen Code dem hinzu addListeners () Funktion:

canvas.addEventListener ("mousedown", Funktion (evt) var pickResult = scene.pick (evt.clientX, evt.clientY, Funktion (Netz) 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);;

Starten Sie Ihren Code in Ihrem bevorzugten Browser. Sie können jetzt auf Ihre physischen Netze klicken, um mit ihnen zu spielen.

6. Anzeigen der Begrenzungsrahmen, um die ganze Geschichte besser zu verstehen

Schließlich erstellen wir eine Debug-Szene, in der Sie die Collider anzeigen / ausblenden und die physikalischen Eigenschaften für sie aktivieren bzw. deaktivieren können.

Wir werden die Benutzeroberfläche in dieses div einfügen:

Und wir werden diese Funktion verwenden, um die Benutzeroberfläche zu behandeln:

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

Ich weiß, es erzeugt eine sehr hässliche Benutzeroberfläche, aber ich war zu faul, mehr Zeit damit zu verbringen. Fühlen Sie sich frei, um es zu verbessern!

Rufen Sie diese neue Funktion auf und starten Sie das Webprojekt. Zeigen Sie nun beispielsweise die Collider 12 und 17 an:

Mit dem zweiten Kontrollkästchen können Sie auch die physikalischen Eigenschaften aktivieren / deaktivieren. Wenn Sie zum Beispiel die Physik-Eigenschaften des Colliders 12 deaktivieren und die Kugeln starten, werden sie jetzt durch diese Wand gehen! Dies ist im folgenden Screenshot als Kugel dargestellt, die vom roten Quadrat umgeben ist:

Sie können mit diesem Debugging-Beispiel direkt in Ihrem Browser hier spielen: Babylon.js Espilit Physicsdebug-Demo.

Bitte sehen Sie sich auch diese fantastische Demo an, die von Samuel Girardin erstellt wurde und die Oimo.js für einige lustige Charaktere verwendet:

Ich hoffe, dir hat dieses Tutorial gefallen! Du kannst mich gerne auf Twitter anpingen, um einen Kommentar dazu zu schreiben, oder das Kommentarfeld unten verwenden.

Dieser Artikel ist Teil der Web-Dev-Tech-Serie von Microsoft. Wir freuen uns zu teilen Microsoft Edge und das Neue EdgeHTML-Rendering-Engine mit dir. Erhalten Sie kostenlose virtuelle Maschinen oder testen Sie remote auf Ihrem Mac, iOS, Android oder Windows-Gerät. http://dev.modern.ie/.