API Docs for: 0.5.0
Show:

File: src/collision/GridBroadphase.js

var Circle = require('../shapes/Circle')
,   Plane = require('../shapes/Plane')
,   Particle = require('../shapes/Particle')
,   Broadphase = require('../collision/Broadphase')
,   vec2 = require('../math/vec2')
,   Utils = require('../utils/Utils')

module.exports = GridBroadphase;

/**
 * Broadphase that uses axis-aligned bins.
 * @class GridBroadphase
 * @constructor
 * @extends Broadphase
 * @param {object} [options]
 * @param {number} [options.xmin]   Lower x bound of the grid
 * @param {number} [options.xmax]   Upper x bound
 * @param {number} [options.ymin]   Lower y bound
 * @param {number} [options.ymax]   Upper y bound
 * @param {number} [options.nx]     Number of bins along x axis
 * @param {number} [options.ny]     Number of bins along y axis
 * @todo Should have an option for dynamic scene size
 */
function GridBroadphase(options){
    options = options || {};
    Broadphase.apply(this);

    Utils.extend(options,{
        xmin:   -100,
        xmax:   100,
        ymin:   -100,
        ymax:   100,
        nx:     10,
        ny:     10
    });

    this.xmin = options.xmin;
    this.ymin = options.ymin;
    this.xmax = options.xmax;
    this.ymax = options.ymax;
    this.nx = options.nx;
    this.ny = options.ny;

    this.binsizeX = (this.xmax-this.xmin) / this.nx;
    this.binsizeY = (this.ymax-this.ymin) / this.ny;
}
GridBroadphase.prototype = new Broadphase();

/**
 * Get collision pairs.
 * @method getCollisionPairs
 * @param  {World} world
 * @return {Array}
 */
GridBroadphase.prototype.getCollisionPairs = function(world){
    var result = [],
        bodies = world.bodies,
        Ncolliding = bodies.length,
        binsizeX = this.binsizeX,
        binsizeY = this.binsizeY,
        nx = this.nx,
        ny = this.ny,
        xmin = this.xmin,
        ymin = this.ymin,
        xmax = this.xmax,
        ymax = this.ymax;

    // Todo: make garbage free
    var bins=[], Nbins=nx*ny;
    for(var i=0; i<Nbins; i++){
        bins.push([]);
    }

    var xmult = nx / (xmax-xmin);
    var ymult = ny / (ymax-ymin);

    // Put all bodies into bins
    for(var i=0; i!==Ncolliding; i++){
        var bi = bodies[i];
        var aabb = bi.aabb;
        var lowerX = Math.max(aabb.lowerBound[0], xmin);
        var lowerY = Math.max(aabb.lowerBound[1], ymin);
        var upperX = Math.min(aabb.upperBound[0], xmax);
        var upperY = Math.min(aabb.upperBound[1], ymax);
        var xi1 = Math.floor(xmult * (lowerX - xmin));
        var yi1 = Math.floor(ymult * (lowerY - ymin));
        var xi2 = Math.floor(xmult * (upperX - xmin));
        var yi2 = Math.floor(ymult * (upperY - ymin));

        // Put in bin
        for(var j=xi1; j<=xi2; j++){
            for(var k=yi1; k<=yi2; k++){
                var xi = j;
                var yi = k;
                var idx = xi*(ny-1) + yi;
                if(idx >= 0 && idx < Nbins){
                    bins[ idx ].push(bi);
                }
            }
        }
    }

    // Check each bin
    for(var i=0; i!==Nbins; i++){
        var bin = bins[i];

        for(var j=0, NbodiesInBin=bin.length; j!==NbodiesInBin; j++){
            var bi = bin[j];
            for(var k=0; k!==j; k++){
                var bj = bin[k];
                if(Broadphase.canCollide(bi,bj) && this.boundingVolumeCheck(bi,bj)){
                    result.push(bi,bj);
                }
            }
        }
    }
    return result;
};