11/**
2- * The `Matter.Detector` module contains methods for detecting collisions given a set of pairs .
2+ * The `Matter.Detector` module contains methods for efficiently detecting collisions between a list of bodies using a broadphase algorithm .
33*
44* @class Detector
55*/
66
7- // TODO: speculative contacts
8-
97var Detector = { } ;
108
119module . exports = Detector ;
1210
13- var SAT = require ( './SAT ' ) ;
14- var Pair = require ( './Pair ' ) ;
11+ var Common = require ( '../core/Common ' ) ;
12+ var Collision = require ( './Collision ' ) ;
1513
1614( function ( ) {
1715
1816 /**
19- * Finds all collisions given a list of pairs.
17+ * Creates a new collision detector.
18+ * @method create
19+ * @param { } options
20+ * @return {detector } A new collision detector
21+ */
22+ Detector . create = function ( options ) {
23+ var defaults = {
24+ bodies : [ ] ,
25+ pairs : null
26+ } ;
27+
28+ return Common . extend ( defaults , options ) ;
29+ } ;
30+
31+ /**
32+ * Sets the list of bodies in the detector.
33+ * @method setBodies
34+ * @param {detector } detector
35+ * @param {body[] } bodies
36+ */
37+ Detector . setBodies = function ( detector , bodies ) {
38+ detector . bodies = bodies . slice ( 0 ) ;
39+ } ;
40+
41+ /**
42+ * Clears the detector including its list of bodies.
43+ * @method clear
44+ * @param {detector } detector
45+ */
46+ Detector . clear = function ( detector ) {
47+ detector . bodies = [ ] ;
48+ } ;
49+
50+ /**
51+ * Efficiently finds all collisions among all the bodies in `detector.bodies` using a broadphase algorithm.
52+ *
53+ * _Note:_ The specific ordering of collisions returned is not guaranteed between releases and may change for performance reasons.
54+ * If a specific ordering is required then apply a sort to the resulting array.
2055 * @method collisions
21- * @param {pair[] } broadphasePairs
22- * @param {engine } engine
23- * @return {array } collisions
56+ * @param {detector } detector
57+ * @return {collision[] } collisions
2458 */
25- Detector . collisions = function ( broadphasePairs , engine ) {
59+ Detector . collisions = function ( detector ) {
2660 var collisions = [ ] ,
27- pairs = engine . pairs ,
28- broadphasePairsLength = broadphasePairs . length ,
61+ pairs = detector . pairs ,
62+ bodies = detector . bodies ,
63+ bodiesLength = bodies . length ,
2964 canCollide = Detector . canCollide ,
30- collides = SAT . collides ,
31- i ;
32-
33- for ( i = 0 ; i < broadphasePairsLength ; i ++ ) {
34- var broadphasePair = broadphasePairs [ i ] ,
35- bodyA = broadphasePair [ 0 ] ,
36- bodyB = broadphasePair [ 1 ] ;
37-
38- if ( ( bodyA . isStatic || bodyA . isSleeping ) && ( bodyB . isStatic || bodyB . isSleeping ) )
39- continue ;
40-
41- if ( ! canCollide ( bodyA . collisionFilter , bodyB . collisionFilter ) )
42- continue ;
43-
44- var boundsA = bodyA . bounds ,
45- boundsB = bodyB . bounds ;
46-
47- if ( boundsA . min . x > boundsB . max . x || boundsA . max . x < boundsB . min . x
48- || boundsA . max . y < boundsB . min . y || boundsA . min . y > boundsB . max . y ) {
49- continue ;
50- }
65+ collides = Collision . collides ,
66+ i ,
67+ j ;
68+
69+ bodies . sort ( Detector . _compareBoundsX ) ;
70+
71+ for ( i = 0 ; i < bodiesLength ; i ++ ) {
72+ var bodyA = bodies [ i ] ,
73+ boundsA = bodyA . bounds ,
74+ boundXMax = bodyA . bounds . max . x ,
75+ boundYMax = bodyA . bounds . max . y ,
76+ boundYMin = bodyA . bounds . min . y ,
77+ bodyAStatic = bodyA . isStatic || bodyA . isSleeping ,
78+ partsALength = bodyA . parts . length ,
79+ partsASingle = partsALength === 1 ;
80+
81+ for ( j = i + 1 ; j < bodiesLength ; j ++ ) {
82+ var bodyB = bodies [ j ] ,
83+ boundsB = bodyB . bounds ;
84+
85+ if ( boundsB . min . x > boundXMax ) {
86+ break ;
87+ }
5188
52- var partsALength = bodyA . parts . length ,
53- partsBLength = bodyB . parts . length ;
89+ if ( boundYMax < boundsB . min . y || boundYMin > boundsB . max . y ) {
90+ continue ;
91+ }
5492
55- if ( partsALength === 1 && partsBLength === 1 ) {
56- var collision = collides ( bodyA , bodyB , pairs ) ;
93+ if ( bodyAStatic && ( bodyB . isStatic || bodyB . isSleeping ) ) {
94+ continue ;
95+ }
5796
58- if ( collision ) {
59- collisions . push ( collision ) ;
97+ if ( ! canCollide ( bodyA . collisionFilter , bodyB . collisionFilter ) ) {
98+ continue ;
6099 }
61- } else {
62- var partsAStart = partsALength > 1 ? 1 : 0 ,
63- partsBStart = partsBLength > 1 ? 1 : 0 ;
64-
65- for ( var j = partsAStart ; j < partsALength ; j ++ ) {
66- var partA = bodyA . parts [ j ] ,
67- boundsA = partA . bounds ;
68-
69- for ( var k = partsBStart ; k < partsBLength ; k ++ ) {
70- var partB = bodyB . parts [ k ] ,
71- boundsB = partB . bounds ;
72-
73- if ( boundsA . min . x > boundsB . max . x || boundsA . max . x < boundsB . min . x
74- || boundsA . max . y < boundsB . min . y || boundsA . min . y > boundsB . max . y ) {
75- continue ;
76- }
77100
78- var collision = collides ( partA , partB , pairs ) ;
101+ var partsBLength = bodyB . parts . length ;
102+
103+ if ( partsASingle && partsBLength === 1 ) {
104+ var collision = collides ( bodyA , bodyB , pairs ) ;
79105
80- if ( collision ) {
81- collisions . push ( collision ) ;
106+ if ( collision ) {
107+ collisions . push ( collision ) ;
108+ }
109+ } else {
110+ var partsAStart = partsALength > 1 ? 1 : 0 ,
111+ partsBStart = partsBLength > 1 ? 1 : 0 ;
112+
113+ for ( var k = partsAStart ; k < partsALength ; k ++ ) {
114+ var partA = bodyA . parts [ k ] ,
115+ boundsA = partA . bounds ;
116+
117+ for ( var z = partsBStart ; z < partsBLength ; z ++ ) {
118+ var partB = bodyB . parts [ z ] ,
119+ boundsB = partB . bounds ;
120+
121+ if ( boundsA . min . x > boundsB . max . x || boundsA . max . x < boundsB . min . x
122+ || boundsA . max . y < boundsB . min . y || boundsA . min . y > boundsB . max . y ) {
123+ continue ;
124+ }
125+
126+ var collision = collides ( partA , partB , pairs ) ;
127+
128+ if ( collision ) {
129+ collisions . push ( collision ) ;
130+ }
82131 }
83132 }
84133 }
@@ -103,4 +152,39 @@ var Pair = require('./Pair');
103152 return ( filterA . mask & filterB . category ) !== 0 && ( filterB . mask & filterA . category ) !== 0 ;
104153 } ;
105154
155+ /**
156+ * The comparison function used in the broadphase algorithm.
157+ * Returns the signed delta of the bodies bounds on the x-axis.
158+ * @private
159+ * @method _sortCompare
160+ * @param {body } bodyA
161+ * @param {body } bodyB
162+ * @return {number } The signed delta used for sorting
163+ */
164+ Detector . _compareBoundsX = function ( bodyA , bodyB ) {
165+ return bodyA . bounds . min . x - bodyB . bounds . min . x ;
166+ } ;
167+
168+ /*
169+ *
170+ * Properties Documentation
171+ *
172+ */
173+
174+ /**
175+ * The array of `Matter.Body` between which the detector finds collisions.
176+ *
177+ * _Note:_ The order of bodies in this array _is not fixed_ and will be continually managed by the detector.
178+ * @property bodies
179+ * @type body[]
180+ * @default []
181+ */
182+
183+ /**
184+ * Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage.
185+ * @property pairs
186+ * @type {pairs|null }
187+ * @default null
188+ */
189+
106190} ) ( ) ;
0 commit comments