0
0
Fork 0
mirror of https://github.com/liabru/matter-js.git synced 2024-11-23 09:26:51 -05:00

optimised pairs and collisions memory and gc use

This commit is contained in:
liabru 2023-07-23 12:18:03 +01:00
parent 4c56e5b11d
commit f9208df1db
5 changed files with 64 additions and 30 deletions

View file

@ -152,8 +152,10 @@ var Pair = require('./Pair');
supports[supportCount++] = supportsB[0]; supports[supportCount++] = supportsB[0];
} }
// update supports array size // update supports array size if changed
if (supports.length !== supportCount) {
supports.length = supportCount; supports.length = supportCount;
}
return collision; return collision;
}; };

View file

@ -22,6 +22,7 @@ var Collision = require('./Collision');
Detector.create = function(options) { Detector.create = function(options) {
var defaults = { var defaults = {
bodies: [], bodies: [],
collisions: [],
pairs: null pairs: null
}; };
@ -45,6 +46,7 @@ var Collision = require('./Collision');
*/ */
Detector.clear = function(detector) { Detector.clear = function(detector) {
detector.bodies = []; detector.bodies = [];
detector.collisions = [];
}; };
/** /**
@ -57,12 +59,13 @@ var Collision = require('./Collision');
* @return {collision[]} collisions * @return {collision[]} collisions
*/ */
Detector.collisions = function(detector) { Detector.collisions = function(detector) {
var collisions = [], var pairs = detector.pairs,
pairs = detector.pairs,
bodies = detector.bodies, bodies = detector.bodies,
bodiesLength = bodies.length, bodiesLength = bodies.length,
canCollide = Detector.canCollide, canCollide = Detector.canCollide,
collides = Collision.collides, collides = Collision.collides,
collisions = detector.collisions,
collisionIndex = 0,
i, i,
j; j;
@ -104,7 +107,7 @@ var Collision = require('./Collision');
var collision = collides(bodyA, bodyB, pairs); var collision = collides(bodyA, bodyB, pairs);
if (collision) { if (collision) {
collisions.push(collision); collisions[collisionIndex++] = collision;
} }
} else { } else {
var partsAStart = partsALength > 1 ? 1 : 0, var partsAStart = partsALength > 1 ? 1 : 0,
@ -126,7 +129,7 @@ var Collision = require('./Collision');
var collision = collides(partA, partB, pairs); var collision = collides(partA, partB, pairs);
if (collision) { if (collision) {
collisions.push(collision); collisions[collisionIndex++] = collision;
} }
} }
} }
@ -134,6 +137,10 @@ var Collision = require('./Collision');
} }
} }
if (collisions.length !== collisionIndex) {
collisions.length = collisionIndex;
}
return collisions; return collisions;
}; };
@ -180,6 +187,13 @@ var Collision = require('./Collision');
* @default [] * @default []
*/ */
/**
* The array of `Matter.Collision` found in the last call to `Detector.collisions` on this detector.
* @property collisions
* @type collision[]
* @default []
*/
/** /**
* Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage. * Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage.
* @property pairs * @property pairs

View file

@ -74,19 +74,27 @@ var Contact = require('./Contact');
pair.slop = parentA.slop > parentB.slop ? parentA.slop : parentB.slop; pair.slop = parentA.slop > parentB.slop ? parentA.slop : parentB.slop;
collision.pair = pair; collision.pair = pair;
activeContacts.length = 0;
for (var i = 0; i < supports.length; i++) { var activeContactIndex = 0,
supportsLength = supports.length;
for (var i = 0; i < supportsLength; i++) {
var support = supports[i], var support = supports[i],
contactId = support.body === parentA ? support.index : parentAVerticesLength + support.index, contactId = support.body === parentA ? support.index : parentAVerticesLength + support.index,
contact = contacts[contactId]; contact = contacts[contactId];
if (contact) { if (contact) {
activeContacts.push(contact); activeContacts[activeContactIndex++] = contact;
} else { } else {
activeContacts.push(contacts[contactId] = Contact.create(support)); contact = Contact.create(support);
activeContacts[activeContactIndex++] = contact;
contacts[contactId] = contact;
} }
} }
if (activeContacts.length !== activeContactIndex) {
activeContacts.length = activeContactIndex;
}
}; };
/** /**

View file

@ -39,21 +39,19 @@ var Common = require('../core/Common');
Pairs.update = function(pairs, collisions, timestamp) { Pairs.update = function(pairs, collisions, timestamp) {
var pairsList = pairs.list, var pairsList = pairs.list,
pairsListLength = pairsList.length, pairsListLength = pairsList.length,
pairsListIndex = pairsListLength,
pairsTable = pairs.table, pairsTable = pairs.table,
collisionsLength = collisions.length, collisionsLength = collisions.length,
collisionStart = pairs.collisionStart, collisionStart = pairs.collisionStart,
collisionEnd = pairs.collisionEnd, collisionEnd = pairs.collisionEnd,
collisionActive = pairs.collisionActive, collisionActive = pairs.collisionActive,
collisionStartIndex = 0,
collisionEndIndex = 0,
collisionActiveIndex = 0,
collision, collision,
pairIndex,
pair, pair,
i; i;
// clear collision state arrays, but maintain old reference
collisionStart.length = 0;
collisionEnd.length = 0;
collisionActive.length = 0;
for (i = 0; i < pairsListLength; i++) { for (i = 0; i < pairsListLength; i++) {
pairsList[i].confirmedActive = false; pairsList[i].confirmedActive = false;
} }
@ -66,10 +64,10 @@ var Common = require('../core/Common');
// pair already exists (but may or may not be active) // pair already exists (but may or may not be active)
if (pair.isActive) { if (pair.isActive) {
// pair exists and is active // pair exists and is active
collisionActive.push(pair); collisionActive[collisionActiveIndex++] = pair;
} else { } else {
// pair exists but was inactive, so a collision has just started again // pair exists but was inactive, so a collision has just started again
collisionStart.push(pair); collisionStart[collisionStartIndex++] = pair;
} }
// update the pair // update the pair
@ -80,14 +78,14 @@ var Common = require('../core/Common');
pair = Pair.create(collision, timestamp); pair = Pair.create(collision, timestamp);
pairsTable[pair.id] = pair; pairsTable[pair.id] = pair;
// push the new pair // add the new pair
collisionStart.push(pair); collisionStart[collisionStartIndex++] = pair;
pairsList.push(pair); pairsList[pairsListIndex++] = pair;
} }
} }
// find pairs that are no longer active // find pairs that are no longer active
var removePairIndex = []; pairsListIndex = 0;
pairsListLength = pairsList.length; pairsListLength = pairsList.length;
for (i = 0; i < pairsListLength; i++) { for (i = 0; i < pairsListLength; i++) {
@ -95,21 +93,33 @@ var Common = require('../core/Common');
if (!pair.confirmedActive) { if (!pair.confirmedActive) {
Pair.setActive(pair, false, timestamp); Pair.setActive(pair, false, timestamp);
collisionEnd.push(pair); collisionEnd[collisionEndIndex++] = pair;
if (!pair.collision.bodyA.isSleeping && !pair.collision.bodyB.isSleeping) {
removePairIndex.push(i);
}
}
}
// remove inactive pairs // remove inactive pairs
for (i = 0; i < removePairIndex.length; i++) { if (!pair.collision.bodyA.isSleeping && !pair.collision.bodyB.isSleeping) {
pairIndex = removePairIndex[i] - i;
pair = pairsList[pairIndex];
pairsList.splice(pairIndex, 1);
delete pairsTable[pair.id]; delete pairsTable[pair.id];
} }
} else {
pairsList[pairsListIndex++] = pair;
}
}
// update array lengths if changed
if (pairsList.length !== pairsListIndex) {
pairsList.length = pairsListIndex;
}
if (collisionStart.length !== collisionStartIndex) {
collisionStart.length = collisionStartIndex;
}
if (collisionEnd.length !== collisionEndIndex) {
collisionEnd.length = collisionEndIndex;
}
if (collisionActive.length !== collisionActiveIndex) {
collisionActive.length = collisionActiveIndex;
}
}; };
/** /**

View file

@ -60,6 +60,7 @@ var Body = require('../body/Body');
engine.world = options.world || Composite.create({ label: 'World' }); engine.world = options.world || Composite.create({ label: 'World' });
engine.pairs = options.pairs || Pairs.create(); engine.pairs = options.pairs || Pairs.create();
engine.detector = options.detector || Detector.create(); engine.detector = options.detector || Detector.create();
engine.detector.pairs = engine.pairs;
// for temporary back compatibility only // for temporary back compatibility only
engine.grid = { buckets: [] }; engine.grid = { buckets: [] };
@ -138,7 +139,6 @@ var Body = require('../body/Body');
Constraint.postSolveAll(allBodies); Constraint.postSolveAll(allBodies);
// find all collisions // find all collisions
detector.pairs = engine.pairs;
var collisions = Detector.collisions(detector); var collisions = Detector.collisions(detector);
// update collision pairs // update collision pairs