Scratchpads

Jasper edited this page Apr 22, 2014 · 6 revisions

See also: Scratchpad API reference

Any object creation inside a world's "step" phase is costly -- especially if it's inside additional loops. Vectors, especially, are most likely to end up in critical calculations but creating temporary vectors every iteration causes significant slow-downs for the engine. To solve this, when temporary vectors, or transforms are needed, they can be requested from the scratchpad service and then released to be recycled in later calculations.

NOTE: Remember to always call .done() when the computation is complete, otherwise the scratchpad will throw an error.

To create a scratchpad instance, simply call Physics.scratchpad(). This scratchpad instance can be used to obtain recycled vectors, or transforms. They will likely be non-zero, and will need to be set to the appropriate values.

Typically the usage will look something like this:

function myAlgorithm( args ){
    var scratch = Physics.scratchpad() // obtain a new scratchpad instance
        ,tempV = scratch.vector().set( 2, 4 )
        ;
    // do some computation with tempV...

    // important final step: release the scratchpad for reuse and return result
    // passing result to `.done` is just a semantic trick
    return scratch.done( result );
}

It is also possible to wrap a function using Physics.scratchpad() to create a function that will be passed a scratchpad instance as its first parameter, and automatically call .done() for you. Do this like so:

var myAlgorithm = Physics.scratchpad(function( scratch, args ){
    var tempV = scratch.vector().set( 2, 4 );

    // do some computation with tempV...

    // no need to call .done since this function is wrapped
    return result;
});

// call it normally
myAlgorithm( args );

The source code for the .getPolygonArea() method demonstrates an example of the usage of scratchpads.

Physics.geometry.getPolygonArea = function getPolygonArea( hull ){

    var scratch = Physics.scratchpad()
        ,prev = scratch.vector()
        ,next = scratch.vector()
        ,ret = 0
        ,l = hull.length
        ;

    if ( l < 3 ){
        // it must be a point or a line
        // area = 0
        scratch.done();
        return 0;
    }

    prev.clone( hull[ l - 1 ] );

    for ( var i = 0; i < l; ++i ){

        next.clone( hull[ i ] );

        ret += prev.cross( next );

        prev.swap( next );
    }

    scratch.done();
    return ret / 2;
};

Register your own scratch object

If you create an object you would like to reuse with scratchpads, you can register it with the scratchpad service. Example:

var myObject = function(){
   this.foo = 'bar';
};

Physics.scratchpad.register('myObject', myObject);

// use it!
var scratch = Physics.scratchpad();
var instance = scratch.myObject();
scratch.done();