Create wonderful interactive games for the web: Using webgl and a physics engine (babylon.js & cannon.js)

Did you ever notice how a physics game is addictive? Actually, I can spend hours playing with small physics simulations just because it looks so real.

That’s why I decided to integrate a physics engine into babylon.js.

Can’t wait and want to play right now? Just go there..

State of the art

The purpose was not to create a physics engine from scratch., There are already a few good physics engine written for JavaScript by the community (This is one of the reason why I love JavaScript: there is always a .js project for what you want to do ^^). Here are some examples (I do not talk about 2D engine but only 3D ones):

  • Cannon.js: A pure JavaScript engine. I decided to use this one because the code is clear, efficient and very well maintained
  • JigLibJS: A JavaScript port of a C/C++ library called JigLib
  • Ammo.js: A JavaScript port of Bullet engine.The port was made using Emscripten and thus this is an automated port.
  • Bullet.js: Another JavaScript port of Bullet

All of these engines are great but I had to make a choice. So I decided to use a purely JavaScript engine (in opposite to a port of an existing one) because I wanted an engine designed and thought for JavaScript.

For instance, I did not keep Ammo.js because it was created with Emscripten. Because of how Emscripten converts libraries to Javascript there are some things in Ammo.js which are more difficult to use – pointers for instance add an extra layer of complication.

Because they are ports and not written in Javascript, they are not optimized for the web. Javascript has its own features and quirks which make developing for it unique.

Activating physics with babylon.js

So let’s go back to Babylon.js. From the point of view of a web developer, physics engine can give you a lot of cool features among which we can get for instance:

  • Realistic simulation of basic shapes (Box, Sphere, compound, etc…)
  • Simulation of friction and bounciness
  • Link between objects (to simulate chains for instance)

So let’s have a look on how to activate all these funny things with Babylon.js:

Enabling physics engine

To enable the physics engine, you just have to run this line of code:

scene.enablePhysics();

Please note that the physics simulation can be really expensive when it comes to talk about performance

You can define the gravity of your simulation with the following command:

scene.setGravity(new BABYLON.Vector3(0, -10, 0));

Defining impostors for your meshes

The simulation will not directly work on your meshes (far too complex). Actually, you will need to create a geometric impostor for them. Right now, I only support boxes, spheres and planes but in a not too distant future I will continue adding new impostors.

To define an impostor, you just have to call the setPhysicState function:

sphere.setPhysicsState({ impostor: BABYLON.PhysicsEngine.SphereImpostor, mass: 1 });

The mass parameter can be set to 0 if you want to create a static object (such as a ground for instance).

You can also define the friction (resistance of the object to movement) and the restitution (tendency of the object to bounce after colliding with another):

ground.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: 0, friction: 0.5, restitution: 0.7 });

The initial position and rotation (using mesh.rotationQuaternion property) of the mesh are used to define the position and rotation of the impostors.

You can also link your impostors in order to always keep meshes linked. You can for instance create chains like this one:

To do so, you just have (as always) one line of code to execute:

spheres[index].setPhysicsLinkWith(spheres[index + 1], new BABYLON.Vector3(0, 0.5, 0), new BABYLON.Vector3(0, -0.5, 0));

Creating compound impostors

If you want to create more complex physics objects you can use the scene.createCompoundImpostor function:

// Compound
var part0 = BABYLON.Mesh.CreateBox("part0", 3, scene);
part0.position = new BABYLON.Vector3(3, 30, 0);

var part1 = BABYLON.Mesh.CreateBox("part1", 3, scene);
part1.parent = part0; // We need a hierarchy for compound objects
part1.position = new BABYLON.Vector3(0, 3, 0);

scene.createCompoundImpostor({
    mass: 2, friction: 0.4, restitution: 0.3, parts: [
    { mesh: part0, impostor: BABYLON.PhysicsEngine.BoxImpostor },
    { mesh: part1, impostor: BABYLON.PhysicsEngine.BoxImpostor }]
});

This will create an unique rigid body object based on the hierarchy provided.

Beware, to create a compound impostor, you must create a hierarchy and provide the root as first object

Applying an impulse

Once your scene is set up, you can play with your meshes using this code:

var pickResult = scene.pick(evt.clientX, evt.clientY);
var dir = pickResult.pickedPoint.subtract(scene.activeCamera.position);
dir.normalize();
pickResult.pickedMesh.applyImpulse(dir.scale(10), pickResult.pickedPoint);

This will apply an impulse on the selected mesh at a given point (in world space).

Exporting a blender scene with physics enabled

Thanks to the extensibility capabilities of Blender (with Python), I was able to support exporting physics information.

You just have to select a mesh and directly go to the Physics tab:

Blender will not let you define a mass equal to zero. But do not worry about that because the exporter will consider a value of 0.001 as zero.

Then, you will be able to define mass, shape, friction and restitution (Bounciness):

And you’re done! Simply export your scene to a .babylon file and use it in your own app/site or drag’n’drop it to our sandbox.

The power of the web

I keep being amazed by the power of current browsers. Right now, you can have a complete 3D simulation alongside an accurate physics engine. And that, with only a few lines of JavaScript code!!

You have now everything you need to create wonderful and dynamic games for the web and for Windows 8! So let’s unleash your creativity. Who knows, the next Angry Bird is perhaps a few lines of code away.