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 [];
- };
-