#

API Docs for: 0.6.1
Show: Inherited Protected Private Deprecated

# File: src/collision/Broadphase.js

    var Body = require('../objects/Body');
    var Vec3 = require('../math/Vec3');
    var Quaternion = require('../math/Quaternion');
    var Shape = require('../shapes/Shape');
    var Plane = require('../shapes/Plane');

    module.exports = Broadphase;

    /**
     * Base class for broadphase implementations
     * @class Broadphase
     * @constructor
     * @author schteppe
     */
    function Broadphase(){
        /**
        * The world to search for collisions in.
        * @property world
        * @type {World}
        */
        this.world = null;

        /**
         * If set to true, the broadphase uses bounding boxes for intersection test, else it uses bounding spheres.
         * @property useBoundingBoxes
         * @type {Boolean}
         */
        this.useBoundingBoxes = false;

        /**
         * Set to true if the objects in the world moved.
         * @property {Boolean} dirty
         */
        this.dirty = true;
    }

    /**
     * Get the collision pairs from the world
     * @method collisionPairs
     * @param {World} world The world to search in
     * @param {Array} p1 Empty array to be filled with body objects
     * @param {Array} p2 Empty array to be filled with body objects
     */
    Broadphase.prototype.collisionPairs = function(world,p1,p2){
        throw new Error("collisionPairs not implemented for this BroadPhase class!");
    };

    /**
     * Check if a body pair needs to be intersection tested at all.
     * @method needBroadphaseCollision
     * @param {Body} bodyA
     * @param {Body} bodyB
     * @return {bool}
     */
    var Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC = Body.STATIC | Body.KINEMATIC;
    Broadphase.prototype.needBroadphaseCollision = function(bodyA,bodyB){

        // Check collision filter masks
        if( (bodyA.collisionFilterGroup & bodyB.collisionFilterMask)===0 || (bodyB.collisionFilterGroup & bodyA.collisionFilterMask)===0){
            return false;
        }

        // Check types
        if(((bodyA.type & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC)!==0 || bodyA.sleepState === Body.SLEEPING) &&
           ((bodyB.type & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC)!==0 || bodyB.sleepState === Body.SLEEPING)) {
            // Both bodies are static, kinematic or sleeping. Skip.
            return false;
        }

        return true;
    };

    /**
     * Check if the bounding volumes of two bodies intersect.
     * @method intersectionTest
     * @param {Body} bodyA
     * @param {Body} bodyB
     * @param {array} pairs1
     * @param {array} pairs2
      */
    Broadphase.prototype.intersectionTest = function(bodyA, bodyB, pairs1, pairs2){
        if(this.useBoundingBoxes){
            this.doBoundingBoxBroadphase(bodyA,bodyB,pairs1,pairs2);
        } else {
            this.doBoundingSphereBroadphase(bodyA,bodyB,pairs1,pairs2);
        }
    };

    /**
     * Check if the bounding spheres of two bodies are intersecting.
     * @method doBoundingSphereBroadphase
     * @param {Body} bodyA
     * @param {Body} bodyB
     * @param {Array} pairs1 bodyA is appended to this array if intersection
     * @param {Array} pairs2 bodyB is appended to this array if intersection
     */
    var Broadphase_collisionPairs_r = new Vec3(), // Temp objects
        Broadphase_collisionPairs_normal =  new Vec3(),
        Broadphase_collisionPairs_quat =  new Quaternion(),
        Broadphase_collisionPairs_relpos  =  new Vec3();
    Broadphase.prototype.doBoundingSphereBroadphase = function(bodyA,bodyB,pairs1,pairs2){
        var r = Broadphase_collisionPairs_r;
        bodyB.position.vsub(bodyA.position,r);
        var boundingRadiusSum2 = Math.pow(bodyA.boundingRadius + bodyB.boundingRadius, 2);
        var norm2 = r.norm2();
        if(norm2 < boundingRadiusSum2){
            pairs1.push(bodyA);
            pairs2.push(bodyB);
        }
    };

    /**
     * Check if the bounding boxes of two bodies are intersecting.
     * @method doBoundingBoxBroadphase
     * @param {Body} bodyA
     * @param {Body} bodyB
     * @param {Array} pairs1
     * @param {Array} pairs2
     */
    Broadphase.prototype.doBoundingBoxBroadphase = function(bodyA,bodyB,pairs1,pairs2){
        if(bodyA.aabbNeedsUpdate){
            bodyA.computeAABB();
        }
        if(bodyB.aabbNeedsUpdate){
            bodyB.computeAABB();
        }

        // Check AABB / AABB
        if(bodyA.aabb.overlaps(bodyB.aabb)){
            pairs1.push(bodyA);
            pairs2.push(bodyB);
        }
    };

    /**
     * Removes duplicate pairs from the pair arrays.
     * @method makePairsUnique
     * @param {Array} pairs1
     * @param {Array} pairs2
     */
    var Broadphase_makePairsUnique_temp = { keys:[] },
        Broadphase_makePairsUnique_p1 = [],
        Broadphase_makePairsUnique_p2 = [];
    Broadphase.prototype.makePairsUnique = function(pairs1,pairs2){
        var t = Broadphase_makePairsUnique_temp,
            p1 = Broadphase_makePairsUnique_p1,
            p2 = Broadphase_makePairsUnique_p2,
            N = pairs1.length;

        for(var i=0; i!==N; i++){
            p1[i] = pairs1[i];
            p2[i] = pairs2[i];
        }

        pairs1.length = 0;
        pairs2.length = 0;

        for(var i=0; i!==N; i++){
            var id1 = p1[i].id,
                id2 = p2[i].id;
            var key = id1 < id2 ? id1+","+id2 :  id2+","+id1;
            t[key] = i;
            t.keys.push(key);
        }

        for(var i=0; i!==t.keys.length; i++){
            var key = t.keys.pop(),
                pairIndex = t[key];
            pairs1.push(p1[pairIndex]);
            pairs2.push(p2[pairIndex]);
            delete t[key];
        }
    };

    /**
     * To be implemented by subcasses
     * @method setWorld
     * @param {World} world
     */
    Broadphase.prototype.setWorld = function(world){
    };

    /**
     * Check if the bounding spheres of two bodies overlap.
     * @method boundingSphereCheck
     * @param {Body} bodyA
     * @param {Body} bodyB
     * @return {boolean}
     */
    var bsc_dist = new Vec3();
    Broadphase.boundingSphereCheck = function(bodyA,bodyB){
        var dist = bsc_dist;
        bodyA.position.vsub(bodyB.position,dist);
        return Math.pow(bodyA.shape.boundingSphereRadius + bodyB.shape.boundingSphereRadius,2) > dist.norm2();
    };

    /**
     * Returns all the bodies within the AABB.
     * @method aabbQuery
     * @param  {World} world
     * @param  {AABB} aabb
     * @param  {array} result An array to store resulting bodies in.
     * @return {array}
     */
    Broadphase.prototype.aabbQuery = function(world, aabb, result){
        console.warn('.aabbQuery is not implemented in this Broadphase subclass.');
        return [];
    };