Skip to content

Commit

Permalink
added broadphase to Matter.Detector
Browse files Browse the repository at this point in the history
  • Loading branch information
liabru committed Dec 12, 2021
1 parent b9e7d9d commit a6b5e7d
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 112 deletions.
200 changes: 142 additions & 58 deletions src/collision/Detector.js
Original file line number Diff line number Diff line change
@@ -1,84 +1,133 @@
/**
* The `Matter.Detector` module contains methods for detecting collisions given a set of pairs.
* The `Matter.Detector` module contains methods for efficiently detecting collisions between a list of bodies using a broadphase algorithm.
*
* @class Detector
*/

// TODO: speculative contacts

var Detector = {};

module.exports = Detector;

var SAT = require('./SAT');
var Pair = require('./Pair');
var Common = require('../core/Common');
var Collision = require('./Collision');

(function() {

/**
* Finds all collisions given a list of pairs.
* Creates a new collision detector.
* @method create
* @param {} options
* @return {detector} A new collision detector
*/
Detector.create = function(options) {
var defaults = {
bodies: [],
pairs: null
};

return Common.extend(defaults, options);
};

/**
* Sets the list of bodies in the detector.
* @method setBodies
* @param {detector} detector
* @param {body[]} bodies
*/
Detector.setBodies = function(detector, bodies) {
detector.bodies = bodies.slice(0);
};

/**
* Clears the detector including its list of bodies.
* @method clear
* @param {detector} detector
*/
Detector.clear = function(detector) {
detector.bodies = [];
};

/**
* Efficiently finds all collisions among all the bodies in `detector.bodies` using a broadphase algorithm.
*
* _Note:_ The specific ordering of collisions returned is not guaranteed between releases and may change for performance reasons.
* If a specific ordering is required then apply a sort to the resulting array.
* @method collisions
* @param {pair[]} broadphasePairs
* @param {engine} engine
* @return {array} collisions
* @param {detector} detector
* @return {collision[]} collisions
*/
Detector.collisions = function(broadphasePairs, engine) {
Detector.collisions = function(detector) {
var collisions = [],
pairs = engine.pairs,
broadphasePairsLength = broadphasePairs.length,
pairs = detector.pairs,
bodies = detector.bodies,
bodiesLength = bodies.length,
canCollide = Detector.canCollide,
collides = SAT.collides,
i;

for (i = 0; i < broadphasePairsLength; i++) {
var broadphasePair = broadphasePairs[i],
bodyA = broadphasePair[0],
bodyB = broadphasePair[1];

if ((bodyA.isStatic || bodyA.isSleeping) && (bodyB.isStatic || bodyB.isSleeping))
continue;

if (!canCollide(bodyA.collisionFilter, bodyB.collisionFilter))
continue;

var boundsA = bodyA.bounds,
boundsB = bodyB.bounds;

if (boundsA.min.x > boundsB.max.x || boundsA.max.x < boundsB.min.x
|| boundsA.max.y < boundsB.min.y || boundsA.min.y > boundsB.max.y) {
continue;
}
collides = Collision.collides,
i,
j;

bodies.sort(Detector._compareBoundsX);

for (i = 0; i < bodiesLength; i++) {
var bodyA = bodies[i],
boundsA = bodyA.bounds,
boundXMax = bodyA.bounds.max.x,
boundYMax = bodyA.bounds.max.y,
boundYMin = bodyA.bounds.min.y,
bodyAStatic = bodyA.isStatic || bodyA.isSleeping,
partsALength = bodyA.parts.length,
partsASingle = partsALength === 1;

for (j = i + 1; j < bodiesLength; j++) {
var bodyB = bodies[j],
boundsB = bodyB.bounds;

if (boundsB.min.x > boundXMax) {
break;
}

var partsALength = bodyA.parts.length,
partsBLength = bodyB.parts.length;
if (boundYMax < boundsB.min.y || boundYMin > boundsB.max.y) {
continue;
}

if (partsALength === 1 && partsBLength === 1) {
var collision = collides(bodyA, bodyB, pairs);
if (bodyAStatic && (bodyB.isStatic || bodyB.isSleeping)) {
continue;
}

if (collision) {
collisions.push(collision);
if (!canCollide(bodyA.collisionFilter, bodyB.collisionFilter)) {
continue;
}
} else {
var partsAStart = partsALength > 1 ? 1 : 0,
partsBStart = partsBLength > 1 ? 1 : 0;

for (var j = partsAStart; j < partsALength; j++) {
var partA = bodyA.parts[j],
boundsA = partA.bounds;

for (var k = partsBStart; k < partsBLength; k++) {
var partB = bodyB.parts[k],
boundsB = partB.bounds;

if (boundsA.min.x > boundsB.max.x || boundsA.max.x < boundsB.min.x
|| boundsA.max.y < boundsB.min.y || boundsA.min.y > boundsB.max.y) {
continue;
}

var collision = collides(partA, partB, pairs);
var partsBLength = bodyB.parts.length;

if (partsASingle && partsBLength === 1) {
var collision = collides(bodyA, bodyB, pairs);

if (collision) {
collisions.push(collision);
if (collision) {
collisions.push(collision);
}
} else {
var partsAStart = partsALength > 1 ? 1 : 0,
partsBStart = partsBLength > 1 ? 1 : 0;

for (var k = partsAStart; k < partsALength; k++) {
var partA = bodyA.parts[k],
boundsA = partA.bounds;

for (var z = partsBStart; z < partsBLength; z++) {
var partB = bodyB.parts[z],
boundsB = partB.bounds;

if (boundsA.min.x > boundsB.max.x || boundsA.max.x < boundsB.min.x
|| boundsA.max.y < boundsB.min.y || boundsA.min.y > boundsB.max.y) {
continue;
}

var collision = collides(partA, partB, pairs);

if (collision) {
collisions.push(collision);
}
}
}
}
Expand All @@ -103,4 +152,39 @@ var Pair = require('./Pair');
return (filterA.mask & filterB.category) !== 0 && (filterB.mask & filterA.category) !== 0;
};

/**
* The comparison function used in the broadphase algorithm.
* Returns the signed delta of the bodies bounds on the x-axis.
* @private
* @method _sortCompare
* @param {body} bodyA
* @param {body} bodyB
* @return {number} The signed delta used for sorting
*/
Detector._compareBoundsX = function(bodyA, bodyB) {
return bodyA.bounds.min.x - bodyB.bounds.min.x;
};

/*
*
* Properties Documentation
*
*/

/**
* The array of `Matter.Body` between which the detector finds collisions.
*
* _Note:_ The order of bodies in this array _is not fixed_ and will be continually managed by the detector.
* @property bodies
* @type body[]
* @default []
*/

/**
* Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage.
* @property pairs
* @type {pairs|null}
* @default null
*/

})();
Loading

0 comments on commit a6b5e7d

Please sign in to comment.