API Docs for: 0.6.1
Show:

File: src/collision/Broadphase.js

  1. var Body = require('../objects/Body');
  2. var Vec3 = require('../math/Vec3');
  3. var Quaternion = require('../math/Quaternion');
  4. var Shape = require('../shapes/Shape');
  5. var Plane = require('../shapes/Plane');
  6.  
  7. module.exports = Broadphase;
  8.  
  9. /**
  10. * Base class for broadphase implementations
  11. * @class Broadphase
  12. * @constructor
  13. * @author schteppe
  14. */
  15. function Broadphase(){
  16. /**
  17. * The world to search for collisions in.
  18. * @property world
  19. * @type {World}
  20. */
  21. this.world = null;
  22.  
  23. /**
  24. * If set to true, the broadphase uses bounding boxes for intersection test, else it uses bounding spheres.
  25. * @property useBoundingBoxes
  26. * @type {Boolean}
  27. */
  28. this.useBoundingBoxes = false;
  29.  
  30. /**
  31. * Set to true if the objects in the world moved.
  32. * @property {Boolean} dirty
  33. */
  34. this.dirty = true;
  35. }
  36.  
  37. /**
  38. * Get the collision pairs from the world
  39. * @method collisionPairs
  40. * @param {World} world The world to search in
  41. * @param {Array} p1 Empty array to be filled with body objects
  42. * @param {Array} p2 Empty array to be filled with body objects
  43. */
  44. Broadphase.prototype.collisionPairs = function(world,p1,p2){
  45. throw new Error("collisionPairs not implemented for this BroadPhase class!");
  46. };
  47.  
  48. /**
  49. * Check if a body pair needs to be intersection tested at all.
  50. * @method needBroadphaseCollision
  51. * @param {Body} bodyA
  52. * @param {Body} bodyB
  53. * @return {bool}
  54. */
  55. var Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC = Body.STATIC | Body.KINEMATIC;
  56. Broadphase.prototype.needBroadphaseCollision = function(bodyA,bodyB){
  57.  
  58. // Check collision filter masks
  59. if( (bodyA.collisionFilterGroup & bodyB.collisionFilterMask)===0 || (bodyB.collisionFilterGroup & bodyA.collisionFilterMask)===0){
  60. return false;
  61. }
  62.  
  63. // Check types
  64. if(((bodyA.type & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC)!==0 || bodyA.sleepState === Body.SLEEPING) &&
  65. ((bodyB.type & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC)!==0 || bodyB.sleepState === Body.SLEEPING)) {
  66. // Both bodies are static, kinematic or sleeping. Skip.
  67. return false;
  68. }
  69.  
  70. return true;
  71. };
  72.  
  73. /**
  74. * Check if the bounding volumes of two bodies intersect.
  75. * @method intersectionTest
  76. * @param {Body} bodyA
  77. * @param {Body} bodyB
  78. * @param {array} pairs1
  79. * @param {array} pairs2
  80. */
  81. Broadphase.prototype.intersectionTest = function(bodyA, bodyB, pairs1, pairs2){
  82. if(this.useBoundingBoxes){
  83. this.doBoundingBoxBroadphase(bodyA,bodyB,pairs1,pairs2);
  84. } else {
  85. this.doBoundingSphereBroadphase(bodyA,bodyB,pairs1,pairs2);
  86. }
  87. };
  88.  
  89. /**
  90. * Check if the bounding spheres of two bodies are intersecting.
  91. * @method doBoundingSphereBroadphase
  92. * @param {Body} bodyA
  93. * @param {Body} bodyB
  94. * @param {Array} pairs1 bodyA is appended to this array if intersection
  95. * @param {Array} pairs2 bodyB is appended to this array if intersection
  96. */
  97. var Broadphase_collisionPairs_r = new Vec3(), // Temp objects
  98. Broadphase_collisionPairs_normal = new Vec3(),
  99. Broadphase_collisionPairs_quat = new Quaternion(),
  100. Broadphase_collisionPairs_relpos = new Vec3();
  101. Broadphase.prototype.doBoundingSphereBroadphase = function(bodyA,bodyB,pairs1,pairs2){
  102. var r = Broadphase_collisionPairs_r;
  103. bodyB.position.vsub(bodyA.position,r);
  104. var boundingRadiusSum2 = Math.pow(bodyA.boundingRadius + bodyB.boundingRadius, 2);
  105. var norm2 = r.norm2();
  106. if(norm2 < boundingRadiusSum2){
  107. pairs1.push(bodyA);
  108. pairs2.push(bodyB);
  109. }
  110. };
  111.  
  112. /**
  113. * Check if the bounding boxes of two bodies are intersecting.
  114. * @method doBoundingBoxBroadphase
  115. * @param {Body} bodyA
  116. * @param {Body} bodyB
  117. * @param {Array} pairs1
  118. * @param {Array} pairs2
  119. */
  120. Broadphase.prototype.doBoundingBoxBroadphase = function(bodyA,bodyB,pairs1,pairs2){
  121. if(bodyA.aabbNeedsUpdate){
  122. bodyA.computeAABB();
  123. }
  124. if(bodyB.aabbNeedsUpdate){
  125. bodyB.computeAABB();
  126. }
  127.  
  128. // Check AABB / AABB
  129. if(bodyA.aabb.overlaps(bodyB.aabb)){
  130. pairs1.push(bodyA);
  131. pairs2.push(bodyB);
  132. }
  133. };
  134.  
  135. /**
  136. * Removes duplicate pairs from the pair arrays.
  137. * @method makePairsUnique
  138. * @param {Array} pairs1
  139. * @param {Array} pairs2
  140. */
  141. var Broadphase_makePairsUnique_temp = { keys:[] },
  142. Broadphase_makePairsUnique_p1 = [],
  143. Broadphase_makePairsUnique_p2 = [];
  144. Broadphase.prototype.makePairsUnique = function(pairs1,pairs2){
  145. var t = Broadphase_makePairsUnique_temp,
  146. p1 = Broadphase_makePairsUnique_p1,
  147. p2 = Broadphase_makePairsUnique_p2,
  148. N = pairs1.length;
  149.  
  150. for(var i=0; i!==N; i++){
  151. p1[i] = pairs1[i];
  152. p2[i] = pairs2[i];
  153. }
  154.  
  155. pairs1.length = 0;
  156. pairs2.length = 0;
  157.  
  158. for(var i=0; i!==N; i++){
  159. var id1 = p1[i].id,
  160. id2 = p2[i].id;
  161. var key = id1 < id2 ? id1+","+id2 : id2+","+id1;
  162. t[key] = i;
  163. t.keys.push(key);
  164. }
  165.  
  166. for(var i=0; i!==t.keys.length; i++){
  167. var key = t.keys.pop(),
  168. pairIndex = t[key];
  169. pairs1.push(p1[pairIndex]);
  170. pairs2.push(p2[pairIndex]);
  171. delete t[key];
  172. }
  173. };
  174.  
  175. /**
  176. * To be implemented by subcasses
  177. * @method setWorld
  178. * @param {World} world
  179. */
  180. Broadphase.prototype.setWorld = function(world){
  181. };
  182.  
  183. /**
  184. * Check if the bounding spheres of two bodies overlap.
  185. * @method boundingSphereCheck
  186. * @param {Body} bodyA
  187. * @param {Body} bodyB
  188. * @return {boolean}
  189. */
  190. var bsc_dist = new Vec3();
  191. Broadphase.boundingSphereCheck = function(bodyA,bodyB){
  192. var dist = bsc_dist;
  193. bodyA.position.vsub(bodyB.position,dist);
  194. return Math.pow(bodyA.shape.boundingSphereRadius + bodyB.shape.boundingSphereRadius,2) > dist.norm2();
  195. };
  196.  
  197. /**
  198. * Returns all the bodies within the AABB.
  199. * @method aabbQuery
  200. * @param {World} world
  201. * @param {AABB} aabb
  202. * @param {array} result An array to store resulting bodies in.
  203. * @return {array}
  204. */
  205. Broadphase.prototype.aabbQuery = function(world, aabb, result){
  206. console.warn('.aabbQuery is not implemented in this Broadphase subclass.');
  207. return [];
  208. };