11/**
2- * The `Matter.Collision` module contains methods for managing collision records.
2+ * The `Matter.Collision` module contains methods for detecting collisions between a given pair of bodies.
3+ *
4+ * For efficient detection between a list of bodies, see `Matter.Detector` and `Matter.Query`.
5+ *
6+ * See `Matter.Engine` for collision events.
37*
48* @class Collision
59*/
@@ -8,13 +12,27 @@ var Collision = {};
812
913module . exports = Collision ;
1014
15+ var Vertices = require ( '../geometry/Vertices' ) ;
16+ var Pair = require ( './Pair' ) ;
17+
1118( function ( ) {
19+ var _supports = [ ] ;
20+
21+ var _overlapAB = {
22+ overlap : 0 ,
23+ axis : null
24+ } ;
25+
26+ var _overlapBA = {
27+ overlap : 0 ,
28+ axis : null
29+ } ;
1230
1331 /**
1432 * Creates a new collision record.
1533 * @method create
16- * @param {body } bodyA
17- * @param {body } bodyB
34+ * @param {body } bodyA The first body part represented by the collision record
35+ * @param {body } bodyB The second body part represented by the collision record
1836 * @return {collision } A new collision record
1937 */
2038 Collision . create = function ( bodyA , bodyB ) {
@@ -33,4 +51,358 @@ module.exports = Collision;
3351 } ;
3452 } ;
3553
54+ /**
55+ * Detect collision between two bodies.
56+ * @method collides
57+ * @param {body } bodyA
58+ * @param {body } bodyB
59+ * @param {pairs } [pairs] Optionally reuse collision records from existing pairs.
60+ * @return {collision|null } A collision record if detected, otherwise null
61+ */
62+ Collision . collides = function ( bodyA , bodyB , pairs ) {
63+ Collision . _overlapAxes ( _overlapAB , bodyA . vertices , bodyB . vertices , bodyA . axes ) ;
64+
65+ if ( _overlapAB . overlap <= 0 ) {
66+ return null ;
67+ }
68+
69+ Collision . _overlapAxes ( _overlapBA , bodyB . vertices , bodyA . vertices , bodyB . axes ) ;
70+
71+ if ( _overlapBA . overlap <= 0 ) {
72+ return null ;
73+ }
74+
75+ // reuse collision records for gc efficiency
76+ var pair = pairs && pairs . table [ Pair . id ( bodyA , bodyB ) ] ,
77+ collision ;
78+
79+ if ( ! pair ) {
80+ collision = Collision . create ( bodyA , bodyB ) ;
81+ collision . collided = true ;
82+ collision . bodyA = bodyA . id < bodyB . id ? bodyA : bodyB ;
83+ collision . bodyB = bodyA . id < bodyB . id ? bodyB : bodyA ;
84+ collision . parentA = collision . bodyA . parent ;
85+ collision . parentB = collision . bodyB . parent ;
86+ } else {
87+ collision = pair . collision ;
88+ }
89+
90+ bodyA = collision . bodyA ;
91+ bodyB = collision . bodyB ;
92+
93+ var minOverlap ;
94+
95+ if ( _overlapAB . overlap < _overlapBA . overlap ) {
96+ minOverlap = _overlapAB ;
97+ } else {
98+ minOverlap = _overlapBA ;
99+ }
100+
101+ var normal = collision . normal ,
102+ supports = collision . supports ,
103+ minAxis = minOverlap . axis ,
104+ minAxisX = minAxis . x ,
105+ minAxisY = minAxis . y ;
106+
107+ // ensure normal is facing away from bodyA
108+ if ( minAxisX * ( bodyB . position . x - bodyA . position . x ) + minAxisY * ( bodyB . position . y - bodyA . position . y ) < 0 ) {
109+ normal . x = minAxisX ;
110+ normal . y = minAxisY ;
111+ } else {
112+ normal . x = - minAxisX ;
113+ normal . y = - minAxisY ;
114+ }
115+
116+ collision . tangent . x = - normal . y ;
117+ collision . tangent . y = normal . x ;
118+
119+ collision . depth = minOverlap . overlap ;
120+
121+ collision . penetration . x = normal . x * collision . depth ;
122+ collision . penetration . y = normal . y * collision . depth ;
123+
124+ // find support points, there is always either exactly one or two
125+ var supportsB = Collision . _findSupports ( bodyA , bodyB , normal , 1 ) ,
126+ supportCount = 0 ;
127+
128+ // find the supports from bodyB that are inside bodyA
129+ if ( Vertices . contains ( bodyA . vertices , supportsB [ 0 ] ) ) {
130+ supports [ supportCount ++ ] = supportsB [ 0 ] ;
131+ }
132+
133+ if ( Vertices . contains ( bodyA . vertices , supportsB [ 1 ] ) ) {
134+ supports [ supportCount ++ ] = supportsB [ 1 ] ;
135+ }
136+
137+ // find the supports from bodyA that are inside bodyB
138+ if ( supportCount < 2 ) {
139+ var supportsA = Collision . _findSupports ( bodyB , bodyA , normal , - 1 ) ;
140+
141+ if ( Vertices . contains ( bodyB . vertices , supportsA [ 0 ] ) ) {
142+ supports [ supportCount ++ ] = supportsA [ 0 ] ;
143+ }
144+
145+ if ( supportCount < 2 && Vertices . contains ( bodyB . vertices , supportsA [ 1 ] ) ) {
146+ supports [ supportCount ++ ] = supportsA [ 1 ] ;
147+ }
148+ }
149+
150+ // account for the edge case of overlapping but no vertex containment
151+ if ( supportCount === 0 ) {
152+ supports [ supportCount ++ ] = supportsB [ 0 ] ;
153+ }
154+
155+ // update supports array size
156+ supports . length = supportCount ;
157+
158+ return collision ;
159+ } ;
160+
161+ /**
162+ * Find the overlap between two sets of vertices.
163+ * @method _overlapAxes
164+ * @private
165+ * @param {object } result
166+ * @param {vertices } verticesA
167+ * @param {vertices } verticesB
168+ * @param {axes } axes
169+ */
170+ Collision . _overlapAxes = function ( result , verticesA , verticesB , axes ) {
171+ var verticesALength = verticesA . length ,
172+ verticesBLength = verticesB . length ,
173+ verticesAX = verticesA [ 0 ] . x ,
174+ verticesAY = verticesA [ 0 ] . y ,
175+ verticesBX = verticesB [ 0 ] . x ,
176+ verticesBY = verticesB [ 0 ] . y ,
177+ axesLength = axes . length ,
178+ overlapMin = Number . MAX_VALUE ,
179+ overlapAxisNumber = 0 ,
180+ overlap ,
181+ overlapAB ,
182+ overlapBA ,
183+ dot ,
184+ i ,
185+ j ;
186+
187+ for ( i = 0 ; i < axesLength ; i ++ ) {
188+ var axis = axes [ i ] ,
189+ axisX = axis . x ,
190+ axisY = axis . y ,
191+ minA = verticesAX * axisX + verticesAY * axisY ,
192+ minB = verticesBX * axisX + verticesBY * axisY ,
193+ maxA = minA ,
194+ maxB = minB ;
195+
196+ for ( j = 1 ; j < verticesALength ; j += 1 ) {
197+ dot = verticesA [ j ] . x * axisX + verticesA [ j ] . y * axisY ;
198+
199+ if ( dot > maxA ) {
200+ maxA = dot ;
201+ } else if ( dot < minA ) {
202+ minA = dot ;
203+ }
204+ }
205+
206+ for ( j = 1 ; j < verticesBLength ; j += 1 ) {
207+ dot = verticesB [ j ] . x * axisX + verticesB [ j ] . y * axisY ;
208+
209+ if ( dot > maxB ) {
210+ maxB = dot ;
211+ } else if ( dot < minB ) {
212+ minB = dot ;
213+ }
214+ }
215+
216+ overlapAB = maxA - minB ;
217+ overlapBA = maxB - minA ;
218+ overlap = overlapAB < overlapBA ? overlapAB : overlapBA ;
219+
220+ if ( overlap < overlapMin ) {
221+ overlapMin = overlap ;
222+ overlapAxisNumber = i ;
223+
224+ if ( overlap <= 0 ) {
225+ // can not be intersecting
226+ break ;
227+ }
228+ }
229+ }
230+
231+ result . axis = axes [ overlapAxisNumber ] ;
232+ result . overlap = overlapMin ;
233+ } ;
234+
235+ /**
236+ * Projects vertices on an axis and returns an interval.
237+ * @method _projectToAxis
238+ * @private
239+ * @param { } projection
240+ * @param { } vertices
241+ * @param { } axis
242+ */
243+ Collision . _projectToAxis = function ( projection , vertices , axis ) {
244+ var min = vertices [ 0 ] . x * axis . x + vertices [ 0 ] . y * axis . y ,
245+ max = min ;
246+
247+ for ( var i = 1 ; i < vertices . length ; i += 1 ) {
248+ var dot = vertices [ i ] . x * axis . x + vertices [ i ] . y * axis . y ;
249+
250+ if ( dot > max ) {
251+ max = dot ;
252+ } else if ( dot < min ) {
253+ min = dot ;
254+ }
255+ }
256+
257+ projection . min = min ;
258+ projection . max = max ;
259+ } ;
260+
261+ /**
262+ * Finds supporting vertices given two bodies along a given direction using hill-climbing.
263+ * @method _findSupports
264+ * @private
265+ * @param {body } bodyA
266+ * @param {body } bodyB
267+ * @param {vector } normal
268+ * @param {number } direction
269+ * @return [vector]
270+ */
271+ Collision . _findSupports = function ( bodyA , bodyB , normal , direction ) {
272+ var vertices = bodyB . vertices ,
273+ verticesLength = vertices . length ,
274+ bodyAPositionX = bodyA . position . x ,
275+ bodyAPositionY = bodyA . position . y ,
276+ normalX = normal . x * direction ,
277+ normalY = normal . y * direction ,
278+ nearestDistance = Number . MAX_VALUE ,
279+ vertexA ,
280+ vertexB ,
281+ vertexC ,
282+ distance ,
283+ j ;
284+
285+ // find deepest vertex relative to the axis
286+ for ( j = 0 ; j < verticesLength ; j += 1 ) {
287+ vertexB = vertices [ j ] ;
288+ distance = normalX * ( bodyAPositionX - vertexB . x ) + normalY * ( bodyAPositionY - vertexB . y ) ;
289+
290+ // convex hill-climbing
291+ if ( distance < nearestDistance ) {
292+ nearestDistance = distance ;
293+ vertexA = vertexB ;
294+ }
295+ }
296+
297+ // measure next vertex
298+ vertexC = vertices [ ( verticesLength + vertexA . index - 1 ) % verticesLength ] ;
299+ nearestDistance = normalX * ( bodyAPositionX - vertexC . x ) + normalY * ( bodyAPositionY - vertexC . y ) ;
300+
301+ // compare with previous vertex
302+ vertexB = vertices [ ( vertexA . index + 1 ) % verticesLength ] ;
303+ if ( normalX * ( bodyAPositionX - vertexB . x ) + normalY * ( bodyAPositionY - vertexB . y ) < nearestDistance ) {
304+ _supports [ 0 ] = vertexA ;
305+ _supports [ 1 ] = vertexB ;
306+
307+ return _supports ;
308+ }
309+
310+ _supports [ 0 ] = vertexA ;
311+ _supports [ 1 ] = vertexC ;
312+
313+ return _supports ;
314+ } ;
315+
316+ /*
317+ *
318+ * Properties Documentation
319+ *
320+ */
321+
322+ /**
323+ * A reference to the pair using this collision record, if there is one.
324+ *
325+ * @property pair
326+ * @type {pair|null }
327+ * @default null
328+ */
329+
330+ /**
331+ * A flag that indicates if the bodies were colliding when the collision was last updated.
332+ *
333+ * @property collided
334+ * @type boolean
335+ * @default false
336+ */
337+
338+ /**
339+ * The first body part represented by the collision (see also `collision.parentA`).
340+ *
341+ * @property bodyA
342+ * @type body
343+ */
344+
345+ /**
346+ * The second body part represented by the collision (see also `collision.parentB`).
347+ *
348+ * @property bodyB
349+ * @type body
350+ */
351+
352+ /**
353+ * The first body represented by the collision (i.e. `collision.bodyA.parent`).
354+ *
355+ * @property parentA
356+ * @type body
357+ */
358+
359+ /**
360+ * The second body represented by the collision (i.e. `collision.bodyB.parent`).
361+ *
362+ * @property parentB
363+ * @type body
364+ */
365+
366+ /**
367+ * A `Number` that represents the minimum separating distance between the bodies along the collision normal.
368+ *
369+ * @readOnly
370+ * @property depth
371+ * @type number
372+ * @default 0
373+ */
374+
375+ /**
376+ * A normalised `Vector` that represents the direction between the bodies that provides the minimum separating distance.
377+ *
378+ * @property normal
379+ * @type vector
380+ * @default { x: 0, y: 0 }
381+ */
382+
383+ /**
384+ * A normalised `Vector` that is the tangent direction to the collision normal.
385+ *
386+ * @property tangent
387+ * @type vector
388+ * @default { x: 0, y: 0 }
389+ */
390+
391+ /**
392+ * A `Vector` that represents the direction and depth of the collision.
393+ *
394+ * @property penetration
395+ * @type vector
396+ * @default { x: 0, y: 0 }
397+ */
398+
399+ /**
400+ * An array of body vertices that represent the support points in the collision.
401+ * These are the deepest vertices (along the collision normal) of each body that are contained by the other body's vertices.
402+ *
403+ * @property supports
404+ * @type vector[]
405+ * @default []
406+ */
407+
36408} ) ( ) ;
0 commit comments