Thursday, August 11, 2016

WebGL Physics and Collision Detection Using Babylon.js and Oimo.js_part 2 (end)

4. Creating Spheres & Boxes With Physics States

We’re now going to add some spheres (with an Amiga texture) and some boxes (with a wood texture) to the scene.

These meshes will have physics state set. For instance, this means that they will bounce on the floor if you launch them in the air, bounce between them after a collision has been detected, and so on. The physics engine needs to know which kind of impostor you’d like to use for the mesh (plane, sphere, or box today), as well as the mass and friction properties.

If you’ve chosen Option 1, you can download the two textures here.

Add this code to your project:
  1. function CreateMaterials() {
  2.     materialAmiga = new BABYLON.StandardMaterial("amiga", scene);
  3.     materialAmiga.diffuseTexture = new BABYLON.Texture("assets/amiga.jpg", scene);
  4.     materialAmiga.emissiveColor = new BABYLON.Color3(0.5, 0.5, 0.5);
  5.     materialAmiga.diffuseTexture.uScale = 5;
  6.     materialAmiga.diffuseTexture.vScale = 5;
  7.     materialWood = new BABYLON.StandardMaterial("wood", scene);
  8.     materialWood.diffuseTexture = new BABYLON.Texture("assets/wood.jpg", scene);
  9.     materialWood.emissiveColor = new BABYLON.Color3(0.5, 0.5, 0.5);
  10. }
  11. function addListeners() {
  12.     window.addEventListener("keydown", function (evt) {
  13.         // s for sphere
  14.         if (evt.keyCode == 83) {
  15.             for (var index = 0; index < 25; index++) {
  16.                 var sphere = BABYLON.Mesh.CreateSphere("Sphere0", 10, 0.5, scene);
  17.                 sphere.material = materialAmiga;
  18.                 sphere.position = new BABYLON.Vector3(0 + index / 10, 3, 5 + index / 10);
  19.                 sphere.setPhysicsState(BABYLON.PhysicsEngine.SphereImpostor, { mass: 1 });
  20.             }
  21.         }
  22.         // b for box
  23.         if (evt.keyCode == 66) {
  24.             for (var index = 0; index < 10; index++) {
  25.                 var box0 = BABYLON.Mesh.CreateBox("Box0", 0.5, scene);
  26.                 box0.position = new BABYLON.Vector3(0 + index / 5, 3, 5 + index / 5);
  27.                 box0.material = materialWood;
  28.                 box0.setPhysicsState(BABYLON.PhysicsEngine.BoxImpostor, { mass: 4 });
  29.             }
  30.         }
  31.     });
  32. }
You can see that boxes are heavier than the spheres by a factor of 4.

Note: If you need to understand how material works in Babylon.js, watch the module Introduction to WebGL 3D with HTML5 and Babylon.js: Understanding Materials and Inputs, or play with our dedicated Playground sample, Babylon.js Playground: Materials sample.

Add these two lines of code after the scene.enablePhysics line:
  1. CreateMaterials();
  2. addListeners();
And launch the web project. Navigate to the center of the museum and press the s or b keys. You’ll obtain this fun result:


5. Adding Picking Support to Click on Meshes

Let’s add another cool feature: the ability to click on one of the objects to throw it away. For that, you need to send a ray from the 2D coordinates of the mouse inside the 3D scene, check whether this ray touches one of the interesting meshes, and if so, apply an impulse force on it to try to move it.

Note: to understand how picking works, please view the MVA module Introduction to WebGL 3D with HTML5 and Babylon.js: Advanced Features. Or play with our online sample, Babylon.js Playground: Picking sample.

Add this code into the addListeners() function:
  1. canvas.addEventListener("mousedown", function (evt) {
  2.     var pickResult = scene.pick(evt.clientX, evt.clientY, function (mesh) {
  3.         if (mesh.name.indexOf("Sphere0") !== -1 || mesh.name.indexOf("Box0") !== -1) {
  4.             return true;
  5.         }
  6.         return false;
  7.     });
  8.     if (pickResult.hit) {
  9.         var dir = pickResult.pickedPoint.subtract(scene.activeCamera.position);
  10.         dir.normalize();
  11.         pickResult.pickedMesh.applyImpulse(dir.scale(1), pickResult.pickedPoint);
  12.     }
  13. });
Launch your code in your favorite browser. You can now click on your physic meshes to play with them.

6. Displaying the Bounding Boxes to Better Understand the Whole Story

Finally, we’re going to create a debug scene to let you display/hide the colliders and activate/deactivate the physics properties on them.

We’re going to inject the UI into this div:
  1. <div id=“lcContainer”>
  2.     <ul id=“listColliders”>
  3.     </ul>
  4. </div>
And we’ll use this function to handle the UI:
  1. function CreateCollidersHTMLList() {
  2.     var listColliders = document.getElementById(“listColliders”);
  3.     for (var j = 0; j < meshesColliderList.length; j++) {
  4.         var newLi = document.createElement(“li”);
  5.         var chkVisibility = document.createElement(‘input’);
  6.         chkVisibility.type = “checkbox”;
  7.         chkVisibility.name = meshesColliderList[j].name;
  8.         chkVisibility.id = “colvis” + j;
  9.         var chkPhysics = document.createElement(‘input’);
  10.         chkPhysics.type = “checkbox”;
  11.         chkPhysics.name = meshesColliderList[j].name;
  12.         chkPhysics.id = “colphysx” + j;
  13.         (function (j) {
  14.             chkVisibility.addEventListener(
  15.              “click”,
  16.              function (event) {
  17.                  onChangeVisibility(j, event);
  18.              },
  19.              false
  20.            );
  21.             chkPhysics.addEventListener(
  22.             “click”,
  23.             function (event) {
  24.                 onChangePhysics(j, event);
  25.             },
  26.             false
  27.             );
  28.         })(j)
  29.         newLi.textContent = meshesColliderList[j].name + “ visibility/physx “;
  30.         newLi.appendChild(chkVisibility);
  31.         newLi.appendChild(chkPhysics);
  32.         listColliders.appendChild(newLi);
  33.     }
  34.     function onChangeVisibility(id, event) {
  35.         if (!meshesColliderList[id].isVisible) {
  36.             meshesColliderList[id].isVisible = true;
  37.             meshesColliderList[id].material.alpha = 0.75;
  38.             meshesColliderList[id].material.ambientColor.r = 1;
  39.         }
  40.         else {
  41.             meshesColliderList[id].isVisible = false;
  42.         }
  43.     }
  44.     function onChangePhysics(id, event) {
  45.         if (!meshesColliderList[id].checkCollisions) {
  46.             meshesColliderList[id].checkCollisions = true;
  47.             meshesColliderList[id].setPhysicsState(BABYLON.PhysicsEngine.BoxImpostor, { mass: 0, 
  48.                                                    friction: 0.5, restitution: 0.7 });
  49.         }
  50.         else {
  51.             meshesColliderList[id].checkCollisions = false;
  52.             meshesColliderList[id].setPhysicsState(BABYLON.PhysicsEngine.NoImpostor);
  53.         }
  54.     }
  55. }
I know, it generates a very ugly UI, but I was too lazy to spend more time on it. Feel free to improve it!

Call this new function and launch the web project. Now, for instance, display the colliders 12 and 17:


You can also, with the second checkbox, enable/disable the physics properties. For instance, if you disable the physics properties on collider 12 and launch the spheres, they will now go through this wall! This is shown in the following screenshot as the sphere surrounded by the red square:


You can play with this debugging sample directly in your browser here: Babylon.js Espilit Physicsdebug demo.

Please also have a look at this awesome demo built by Samuel Girardin that also uses Oimo.js on some funny characters:
This article is part of the web dev tech series from Microsoft.
Written by David Rousset

If you found this post interesting, follow and support us.
Suggest for you:

Build Responsive Real World Websites with HTML5 and CSS3

Build Professional Websites with HTML5 and CSS3 from Scratch

Advanced HTML5 Tutorial for Web Developers

Coding Made Easy: HTML & CSS For Beginners

Easily Learn HTML 5 From Scratch

No comments:

Post a Comment