PhysicsJS: I wrote a physics engine for javascript

 

I’ve finally released a little project I’ve been working on lately: PhysicsJS. It’s a physics engine written in javascript. For those who haven’t used or heard of a physics engine before, a physics engine is a library that helps simulate physical realism in a computer program. For example, here’s a little jsFiddle of a classic tearable cloth simulation I made with PhysicsJS. You can use your mouse to move and even tear the cloth.

It’s not quite the same as the type of physics simulation a physicist would use, because generally a physics engine will do computations in real time, so the algorithms need to be fast. The algorithms in (real-time) physics engines will cut some corners to acheive an effect that is physically plausible to the eye, even if it’s not what would really happen. Usually they are used in game development but there are, of course, other applications also.

There are actually a few javascript physics engines that have been released recently. The two that I’ve most recently come across are VerletJS and coffeephysics. While both are really cool, and have great example simulations, neither have good documentation, and both are very specialized to particular types of effect. Of course, there’s always the classic Box2DJS, which was ported over from a flash implementation… and it shows in the API. While I do love what Box2DJS can do, it’s also a monster of a library, weighing 724 KB minified.

After playing around with physics engines and creating modest simulations of my own, I decided to see if I could pool all of my work into a little library, that hopefully could evolve into something people would find useful. The result is PhysicsJS. It’s generally well documented and the code is written as cleanly as I could. It’s also modular, so the bare-bones functionality is only 32 KB (minified) and the (current) full functionality is 52 KB (minified), but it was written with AMD in mind, so you can include exactly what you need to get the job done with requreJS. It’s also extendable; I wanted to make sure that it would be easy to mixin new functionality of any kind, and replace what isn’t suitable. I’m hoping people will start writing plugins to extend the capabilities, which is an exciting prospect! It’s also fun to use. Only time will tell whether or not it’s an intuitive API… but I’d like to think it is.

Anyways, go check it out and play around. There are some cool demos of the functionality. I’m really interested to see what people think of it so send me your feedback. If you’re interested in contributing, I’d love people to make some plugins to extend the functionality, and also fix some of the quirks in its algorithms.

Enjoy!

Playing with asm.js and Browser Physics

 

Asm.js Physics Demo

Lately I’ve been very intrigued about Mozilla’s asm.js specification. ASM.js is a subset of javascript that allows javascript interpreters to compile code ahead of time, directly into assembly code. This results in huge speed increases.

Current benchmarks of asm.js code running in Firefox’s Nightly build, place javascript at only half the speed of native compiled code! A big difference from the usual, which is around 4 to 10 times slower. One fun showcase of this was the recently ported Unreal Engine 3 to Asm.js.

Yes. We’re running high performance 3D games in web browsers now…

John Resig has a nice writeup about asm.js, including a QA transcript with David Herman (Senior Researcher at Mozilla Research). You should give it a read if you’re interested.

Of course, being curious and well caffeinated, I like to play around. I did a simple benchmark and a little proof of concept of my own. But first, let’s quickly go over asm.js.

asm.js Modules in a nutshell

Firstly, a disclaimer. asm.js code is a pain to write by hand. (I do so because I drink too much coffee…) I don’t really recommend starting any large project thinking that you’ll write it in asm.js from scratch. Likely, the best way to leverage asm.js will be to write in another language (like C++, or something like LLJS), and then “compile” it into asm.js. The painful part is mainly that it feels like writing in two languages at once. It’s javascript… but it feels like something else… anyways, let’s move on.

Asm.js contexts begin with a declaration like this:

"use asm";

This is in the spirit of the "use strict"; declaration, that you are hopefully familiar with. (If not, google it. It’s good to know).

This will most often be placed inside a function that acts as a “factory” for an asm.js module. This asm.js module format looks like this:

function my_module( stdlib, foreign, heap ){
    "use asm";

    // magic... (not really)

    return {
        someMethod: someMethod
    };
}

var instance = my_module(
        window,
        {
            customProperty: value,
            externalFunction: function(){
                // ...
            }
        },
        new ArrayBuffer( size )
    );

When this function is run, it will return an instance of an asm.js module. If asm.js is supported, the methods in the returned object will be compiled into native code. If not, they will be javascript with identical functionality.

Inside the module factory, stdlib will hold standard global functionality (like Math), foreign is user specified and can be used to escape back into regular javascript, and heap is a fixed-size ArrayBuffer for storage.

The magic that happens in between relies on a very restrictive requirement that all primitives must be statically typed as integers, or floats. Numerical computation is pretty much all you can do in an asm.js context (and that’s why it’s so fast). Of course, javascript doesn’t allow for declaring types, so this is done by transforming variables into their types like so:

variable_int = variable_int|0;
variable_float = +variabla_float;

I’m not going to go into great detail about the specifics of hand crafting asm.js code. For that you should check out John Resig’s article and read the specification.

However, one of the big pains to writing it by hand is dealing with memory allocation. The only thing you really have access to in terms of memory, is the fixed-size ArrayBuffer you specify when you instantiate the asm.js module. You then have to then create views into the array buffer to manipulate data.

Easier asm.js Memory Management

Memory management becomes cumbersome. After playing around with it, I decided I needed to write a quick helper module to make this easier.

Basically, the helper lets you manipulate “collections” of objects that store all of their (primitive) properties in an array buffer. For example:

var coln = ASMHelpers.Collection({
        foo: 'int16'
    });

This would create a collection instance that holds objects that hold 16 bit integers in their foo properties. You can then add one of these objects to the collection and all of the ArrayBuffer memory management is taken care of behind the scenes:

coln.add({
    foo: 42
});

var obj = coln.at( 0 );
obj.foo; // => 42

The objects have getters and setters defined, so if you change the property, it will get changed in the array buffer.

obj.foo = 34; // changed in array buffer

Unfortunately, non of those tricks can be used in the context of an asm.js module. But that’s ok, because the helper collection sets up pointer addresses that can be used in asm.js. Here’s how:

// include asm.js module methods into the collection
coln.include(function(stdlib, coln, heap){
    "use asm";

    // general purpose std functions
    var sqrt = stdlib.Math.sqrt;
    // set up our view to look into the heap
    // this will be used to access our int16 properties
    // in our example, this would be the "foo" property
    var int16 = new stdlib.Int16Array( heap );

    // object property pointers, relative to object ptr
    var $foo = coln.$foo|0;
    
    // function to get the number of objects in the collection
    var getLen = coln.getLen;
    // the size of each object in bytes
    var size = coln.objSize|0;
    // starting point for iteration (ie: the address of first object)
    var iterator = coln.ptr|0;

    // example function that increments the foo property 
    // of every object by specified number
    //
    function incrementFoo( n ){
        // declare n as an integer
        n = n|0;

        // declare local variables
        var i = 0, l = 0, ptr = 0;
        ptr = iterator|0;
        l = getLen()|0;

        // loop through objects
        while ((i|0) < (l|0)){

            // foo += n;
            int16[(ptr + $foo) >> 1] = ( (n|0) + (int16[(ptr + $foo) >> 1]|0) )|0;
            // i++;
            i = ((i|0) + 1)|0;
            // ptr += size;
            ptr = ((ptr|0) + (size|0))|0;
        }
    }

    // these functions will get mixed into the collection
    return {

        incrementFoo: incrementFoo
    }
});

Benchmarking with JSPerf

Using this helper, I wrote a very simple 1D physics engine to test performance difference between simulating numbers of objects with the “use asm” declaration, and without it.

Here’s the benchmark on JSPerf

The results in Firefox 23 nightly build:

Aside for some weirdness on the last test, enabling asm.js is significantly faster for this physics algorithm.

Building a simple physics engine in asm.js

Of course, benchmarks are nice… but graphics are more fun! I wanted to keep going and see what this speed increase felt like for some real-time browser simulation.

asm.js Physics Demo To that end, I created this fun demo.