From 653a110d64fbab9a7ddd4775719be6dcec9b7220 Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 23 Jul 2023 11:20:28 +0100 Subject: [PATCH 01/14] optimised Collision._findSupports --- src/collision/Collision.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/collision/Collision.js b/src/collision/Collision.js index 40b6cdfb..86634e65 100644 --- a/src/collision/Collision.js +++ b/src/collision/Collision.js @@ -275,15 +275,15 @@ var Pair = require('./Pair'); bodyAPositionY = bodyA.position.y, normalX = normal.x * direction, normalY = normal.y * direction, - nearestDistance = Number.MAX_VALUE, - vertexA, - vertexB, + vertexA = vertices[0], + vertexB = vertexA, + nearestDistance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y), vertexC, distance, j; // find deepest vertex relative to the axis - for (j = 0; j < verticesLength; j += 1) { + for (j = 1; j < verticesLength; j += 1) { vertexB = vertices[j]; distance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y); From 4c56e5b11dd5b88a8f611c25eb6ae254427c8768 Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 23 Jul 2023 11:22:59 +0100 Subject: [PATCH 02/14] removed Collision._projectToAxis --- src/collision/Collision.js | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/src/collision/Collision.js b/src/collision/Collision.js index 86634e65..8d21b328 100644 --- a/src/collision/Collision.js +++ b/src/collision/Collision.js @@ -153,7 +153,7 @@ var Pair = require('./Pair'); } // update supports array size - supports.length = supportCount; + supports.length = supportCount; return collision; }; @@ -232,32 +232,6 @@ var Pair = require('./Pair'); result.overlap = overlapMin; }; - /** - * Projects vertices on an axis and returns an interval. - * @method _projectToAxis - * @private - * @param {} projection - * @param {} vertices - * @param {} axis - */ - Collision._projectToAxis = function(projection, vertices, axis) { - var min = vertices[0].x * axis.x + vertices[0].y * axis.y, - max = min; - - for (var i = 1; i < vertices.length; i += 1) { - var dot = vertices[i].x * axis.x + vertices[i].y * axis.y; - - if (dot > max) { - max = dot; - } else if (dot < min) { - min = dot; - } - } - - projection.min = min; - projection.max = max; - }; - /** * Finds supporting vertices given two bodies along a given direction using hill-climbing. * @method _findSupports From f9208df1db3c03f41763b68ab4fd12b0bb4064ef Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 23 Jul 2023 12:18:03 +0100 Subject: [PATCH 03/14] optimised pairs and collisions memory and gc use --- src/collision/Collision.js | 4 ++- src/collision/Detector.js | 22 ++++++++++++++--- src/collision/Pair.js | 16 +++++++++--- src/collision/Pairs.js | 50 +++++++++++++++++++++++--------------- src/core/Engine.js | 2 +- 5 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/collision/Collision.js b/src/collision/Collision.js index 8d21b328..1f24db90 100644 --- a/src/collision/Collision.js +++ b/src/collision/Collision.js @@ -152,8 +152,10 @@ var Pair = require('./Pair'); supports[supportCount++] = supportsB[0]; } - // update supports array size + // update supports array size if changed + if (supports.length !== supportCount) { supports.length = supportCount; + } return collision; }; diff --git a/src/collision/Detector.js b/src/collision/Detector.js index a4626e29..c6059b07 100644 --- a/src/collision/Detector.js +++ b/src/collision/Detector.js @@ -22,6 +22,7 @@ var Collision = require('./Collision'); Detector.create = function(options) { var defaults = { bodies: [], + collisions: [], pairs: null }; @@ -45,6 +46,7 @@ var Collision = require('./Collision'); */ Detector.clear = function(detector) { detector.bodies = []; + detector.collisions = []; }; /** @@ -57,12 +59,13 @@ var Collision = require('./Collision'); * @return {collision[]} collisions */ Detector.collisions = function(detector) { - var collisions = [], - pairs = detector.pairs, + var pairs = detector.pairs, bodies = detector.bodies, bodiesLength = bodies.length, canCollide = Detector.canCollide, collides = Collision.collides, + collisions = detector.collisions, + collisionIndex = 0, i, j; @@ -104,7 +107,7 @@ var Collision = require('./Collision'); var collision = collides(bodyA, bodyB, pairs); if (collision) { - collisions.push(collision); + collisions[collisionIndex++] = collision; } } else { var partsAStart = partsALength > 1 ? 1 : 0, @@ -126,7 +129,7 @@ var Collision = require('./Collision'); var collision = collides(partA, partB, pairs); 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; }; @@ -180,6 +187,13 @@ var Collision = require('./Collision'); * @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. * @property pairs diff --git a/src/collision/Pair.js b/src/collision/Pair.js index 8f7ed810..b4ae5bb4 100644 --- a/src/collision/Pair.js +++ b/src/collision/Pair.js @@ -74,19 +74,27 @@ var Contact = require('./Contact'); pair.slop = parentA.slop > parentB.slop ? parentA.slop : parentB.slop; collision.pair = pair; - activeContacts.length = 0; + + var activeContactIndex = 0, + supportsLength = supports.length; - for (var i = 0; i < supports.length; i++) { + for (var i = 0; i < supportsLength; i++) { var support = supports[i], contactId = support.body === parentA ? support.index : parentAVerticesLength + support.index, contact = contacts[contactId]; if (contact) { - activeContacts.push(contact); + activeContacts[activeContactIndex++] = contact; } 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; + } }; /** diff --git a/src/collision/Pairs.js b/src/collision/Pairs.js index 2c62cd36..bb223b54 100644 --- a/src/collision/Pairs.js +++ b/src/collision/Pairs.js @@ -39,21 +39,19 @@ var Common = require('../core/Common'); Pairs.update = function(pairs, collisions, timestamp) { var pairsList = pairs.list, pairsListLength = pairsList.length, + pairsListIndex = pairsListLength, pairsTable = pairs.table, collisionsLength = collisions.length, collisionStart = pairs.collisionStart, collisionEnd = pairs.collisionEnd, collisionActive = pairs.collisionActive, + collisionStartIndex = 0, + collisionEndIndex = 0, + collisionActiveIndex = 0, collision, - pairIndex, pair, i; - // clear collision state arrays, but maintain old reference - collisionStart.length = 0; - collisionEnd.length = 0; - collisionActive.length = 0; - for (i = 0; i < pairsListLength; i++) { pairsList[i].confirmedActive = false; } @@ -66,10 +64,10 @@ var Common = require('../core/Common'); // pair already exists (but may or may not be active) if (pair.isActive) { // pair exists and is active - collisionActive.push(pair); + collisionActive[collisionActiveIndex++] = pair; } else { // pair exists but was inactive, so a collision has just started again - collisionStart.push(pair); + collisionStart[collisionStartIndex++] = pair; } // update the pair @@ -80,14 +78,14 @@ var Common = require('../core/Common'); pair = Pair.create(collision, timestamp); pairsTable[pair.id] = pair; - // push the new pair - collisionStart.push(pair); - pairsList.push(pair); + // add the new pair + collisionStart[collisionStartIndex++] = pair; + pairsList[pairsListIndex++] = pair; } } // find pairs that are no longer active - var removePairIndex = []; + pairsListIndex = 0; pairsListLength = pairsList.length; for (i = 0; i < pairsListLength; i++) { @@ -95,20 +93,32 @@ var Common = require('../core/Common'); if (!pair.confirmedActive) { Pair.setActive(pair, false, timestamp); - collisionEnd.push(pair); + collisionEnd[collisionEndIndex++] = pair; + // remove inactive pairs if (!pair.collision.bodyA.isSleeping && !pair.collision.bodyB.isSleeping) { - removePairIndex.push(i); + delete pairsTable[pair.id]; } + } else { + pairsList[pairsListIndex++] = pair; } } - // remove inactive pairs - for (i = 0; i < removePairIndex.length; i++) { - pairIndex = removePairIndex[i] - i; - pair = pairsList[pairIndex]; - pairsList.splice(pairIndex, 1); - delete pairsTable[pair.id]; + // 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; } }; diff --git a/src/core/Engine.js b/src/core/Engine.js index 91b55ac4..cdf03c4a 100644 --- a/src/core/Engine.js +++ b/src/core/Engine.js @@ -60,6 +60,7 @@ var Body = require('../body/Body'); engine.world = options.world || Composite.create({ label: 'World' }); engine.pairs = options.pairs || Pairs.create(); engine.detector = options.detector || Detector.create(); + engine.detector.pairs = engine.pairs; // for temporary back compatibility only engine.grid = { buckets: [] }; @@ -138,7 +139,6 @@ var Body = require('../body/Body'); Constraint.postSolveAll(allBodies); // find all collisions - detector.pairs = engine.pairs; var collisions = Detector.collisions(detector); // update collision pairs From 97d502ea979fcb687eb249177ba1de4711602c9c Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 23 Jul 2023 12:50:21 +0100 Subject: [PATCH 04/14] optimised contacts and supports memory and gc use --- src/collision/Collision.js | 24 +++++++++++++---- src/collision/Contact.js | 2 +- src/collision/Pair.js | 53 ++++++++++++++++++++------------------ src/collision/Resolver.js | 22 ++++++++-------- src/render/Render.js | 16 ++++++------ 5 files changed, 67 insertions(+), 50 deletions(-) diff --git a/src/collision/Collision.js b/src/collision/Collision.js index 1f24db90..58ae8f75 100644 --- a/src/collision/Collision.js +++ b/src/collision/Collision.js @@ -47,7 +47,8 @@ var Pair = require('./Pair'); normal: { x: 0, y: 0 }, tangent: { x: 0, y: 0 }, penetration: { x: 0, y: 0 }, - supports: [] + supports: [null, null], + supportCount: 0 }; }; @@ -152,10 +153,8 @@ var Pair = require('./Pair'); supports[supportCount++] = supportsB[0]; } - // update supports array size if changed - if (supports.length !== supportCount) { - supports.length = supportCount; - } + // update support count + collision.supportCount = supportCount; return collision; }; @@ -374,6 +373,10 @@ var Pair = require('./Pair'); /** * An array of body vertices that represent the support points in the collision. + * + * _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active. + * Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports. + * * These are the deepest vertices (along the collision normal) of each body that are contained by the other body's vertices. * * @property supports @@ -381,4 +384,15 @@ var Pair = require('./Pair'); * @default [] */ + /** + * The number of active supports for this collision found in `collision.supports`. + * + * _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active. + * Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports. + * + * @property supportCount + * @type number + * @default 0 + */ + })(); diff --git a/src/collision/Contact.js b/src/collision/Contact.js index 56f16cc0..5ec9f0b4 100644 --- a/src/collision/Contact.js +++ b/src/collision/Contact.js @@ -13,7 +13,7 @@ module.exports = Contact; /** * Creates a new contact. * @method create - * @param {vertex} vertex + * @param {vertex} [vertex] * @return {contact} A new contact */ Contact.create = function(vertex) { diff --git a/src/collision/Pair.js b/src/collision/Pair.js index b4ae5bb4..72c54f43 100644 --- a/src/collision/Pair.js +++ b/src/collision/Pair.js @@ -28,8 +28,8 @@ var Contact = require('./Contact'); bodyA: bodyA, bodyB: bodyB, collision: collision, - contacts: [], - activeContacts: [], + contacts: [Contact.create(), Contact.create()], + contactCount: 0, separation: 0, isActive: true, confirmedActive: true, @@ -56,12 +56,11 @@ var Contact = require('./Contact'); * @param {number} timestamp */ Pair.update = function(pair, collision, timestamp) { - var contacts = pair.contacts, - supports = collision.supports, - activeContacts = pair.activeContacts, + var supports = collision.supports, + supportCount = collision.supportCount, + contacts = pair.contacts, parentA = collision.parentA, - parentB = collision.parentB, - parentAVerticesLength = parentA.vertices.length; + parentB = collision.parentB; pair.isActive = true; pair.timeUpdated = timestamp; @@ -73,27 +72,31 @@ var Contact = require('./Contact'); pair.restitution = parentA.restitution > parentB.restitution ? parentA.restitution : parentB.restitution; pair.slop = parentA.slop > parentB.slop ? parentA.slop : parentB.slop; + pair.contactCount = supportCount; collision.pair = pair; - var activeContactIndex = 0, - supportsLength = supports.length; - - for (var i = 0; i < supportsLength; i++) { - var support = supports[i], - contactId = support.body === parentA ? support.index : parentAVerticesLength + support.index, - contact = contacts[contactId]; - - if (contact) { - activeContacts[activeContactIndex++] = contact; - } else { - contact = Contact.create(support); - activeContacts[activeContactIndex++] = contact; - contacts[contactId] = contact; - } + var support = supports[0], + contact = contacts[0]; + + // reset first contact if support changed + if (contact.vertex !== support) { + contact.vertex = support; + contact.normalImpulse = 0; + contact.tangentImpulse = 0; } - if (activeContacts.length !== activeContactIndex) { - activeContacts.length = activeContactIndex; + if (supportCount < 2) { + return; + } + + support = supports[1]; + contact = contacts[1]; + + // reset second contact if support changed + if (contact.vertex !== support) { + contact.vertex = support; + contact.normalImpulse = 0; + contact.tangentImpulse = 0; } }; @@ -110,7 +113,7 @@ var Contact = require('./Contact'); pair.timeUpdated = timestamp; } else { pair.isActive = false; - pair.activeContacts.length = 0; + pair.contactCount = 0; } }; diff --git a/src/collision/Resolver.js b/src/collision/Resolver.js index 9fd7d396..0335902e 100644 --- a/src/collision/Resolver.js +++ b/src/collision/Resolver.js @@ -29,7 +29,7 @@ var Bounds = require('../geometry/Bounds'); Resolver.preSolvePosition = function(pairs) { var i, pair, - activeCount, + contactCount, pairsLength = pairs.length; // find total contacts on each body @@ -39,9 +39,9 @@ var Bounds = require('../geometry/Bounds'); if (!pair.isActive) continue; - activeCount = pair.activeContacts.length; - pair.collision.parentA.totalContacts += activeCount; - pair.collision.parentB.totalContacts += activeCount; + contactCount = pair.contactCount; + pair.collision.parentA.totalContacts += contactCount; + pair.collision.parentB.totalContacts += contactCount; } }; @@ -176,8 +176,8 @@ var Bounds = require('../geometry/Bounds'); if (!pair.isActive || pair.isSensor) continue; - var contacts = pair.activeContacts, - contactsLength = contacts.length, + var contacts = pair.contacts, + contactCount = pair.contactCount, collision = pair.collision, bodyA = collision.parentA, bodyB = collision.parentB, @@ -185,7 +185,7 @@ var Bounds = require('../geometry/Bounds'); tangent = collision.tangent; // resolve each contact - for (j = 0; j < contactsLength; j++) { + for (j = 0; j < contactCount; j++) { var contact = contacts[j], contactVertex = contact.vertex, normalImpulse = contact.normalImpulse, @@ -254,9 +254,9 @@ var Bounds = require('../geometry/Bounds'); normalY = collision.normal.y, tangentX = collision.tangent.x, tangentY = collision.tangent.y, - contacts = pair.activeContacts, - contactsLength = contacts.length, - contactShare = 1 / contactsLength, + contacts = pair.contacts, + contactCount = pair.contactCount, + contactShare = 1 / contactCount, inverseMassTotal = bodyA.inverseMass + bodyB.inverseMass, friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier; @@ -269,7 +269,7 @@ var Bounds = require('../geometry/Bounds'); bodyB.angularVelocity = bodyB.angle - bodyB.anglePrev; // resolve each contact - for (j = 0; j < contactsLength; j++) { + for (j = 0; j < contactCount; j++) { var contact = contacts[j], contactVertex = contact.vertex; diff --git a/src/render/Render.js b/src/render/Render.js index 1002a42a..af5a833b 100644 --- a/src/render/Render.js +++ b/src/render/Render.js @@ -1205,8 +1205,8 @@ var Mouse = require('../core/Mouse'); continue; collision = pair.collision; - for (j = 0; j < pair.activeContacts.length; j++) { - var contact = pair.activeContacts[j], + for (j = 0; j < pair.contactCount; j++) { + var contact = pair.contacts[j], vertex = contact.vertex; c.rect(vertex.x - 1.5, vertex.y - 1.5, 3.5, 3.5); } @@ -1230,13 +1230,13 @@ var Mouse = require('../core/Mouse'); collision = pair.collision; - if (pair.activeContacts.length > 0) { - var normalPosX = pair.activeContacts[0].vertex.x, - normalPosY = pair.activeContacts[0].vertex.y; + if (pair.contactCount > 0) { + var normalPosX = pair.contacts[0].vertex.x, + normalPosY = pair.contacts[0].vertex.y; - if (pair.activeContacts.length === 2) { - normalPosX = (pair.activeContacts[0].vertex.x + pair.activeContacts[1].vertex.x) / 2; - normalPosY = (pair.activeContacts[0].vertex.y + pair.activeContacts[1].vertex.y) / 2; + if (pair.contactCount === 2) { + normalPosX = (pair.contacts[0].vertex.x + pair.contacts[1].vertex.x) / 2; + normalPosY = (pair.contacts[0].vertex.y + pair.contacts[1].vertex.y) / 2; } if (collision.bodyB === collision.supports[0].body || collision.bodyA.isStatic === true) { From 182ba905d4da10bd126d55d751bbe74c25f0ada6 Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 23 Jul 2023 13:50:26 +0100 Subject: [PATCH 05/14] optimised Resolver.solveVelocity --- src/collision/Resolver.js | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/collision/Resolver.js b/src/collision/Resolver.js index 0335902e..df0a5937 100644 --- a/src/collision/Resolver.js +++ b/src/collision/Resolver.js @@ -248,25 +248,23 @@ var Bounds = require('../geometry/Bounds'); var collision = pair.collision, bodyA = collision.parentA, bodyB = collision.parentB, - bodyAVelocity = bodyA.velocity, - bodyBVelocity = bodyB.velocity, normalX = collision.normal.x, normalY = collision.normal.y, tangentX = collision.tangent.x, tangentY = collision.tangent.y, + inverseMassTotal = pair.inverseMass, + friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier, contacts = pair.contacts, contactCount = pair.contactCount, - contactShare = 1 / contactCount, - inverseMassTotal = bodyA.inverseMass + bodyB.inverseMass, - friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier; - - // update body velocities - bodyAVelocity.x = bodyA.position.x - bodyA.positionPrev.x; - bodyAVelocity.y = bodyA.position.y - bodyA.positionPrev.y; - bodyBVelocity.x = bodyB.position.x - bodyB.positionPrev.x; - bodyBVelocity.y = bodyB.position.y - bodyB.positionPrev.y; - bodyA.angularVelocity = bodyA.angle - bodyA.anglePrev; - bodyB.angularVelocity = bodyB.angle - bodyB.anglePrev; + contactShare = 1 / contactCount; + + // get body velocities + var bodyAVelocityX = bodyA.position.x - bodyA.positionPrev.x, + bodyAVelocityY = bodyA.position.y - bodyA.positionPrev.y, + bodyAAngularVelocity = bodyA.angle - bodyA.anglePrev, + bodyBVelocityX = bodyB.position.x - bodyB.positionPrev.x, + bodyBVelocityY = bodyB.position.y - bodyB.positionPrev.y, + bodyBAngularVelocity = bodyB.angle - bodyB.anglePrev; // resolve each contact for (j = 0; j < contactCount; j++) { @@ -278,10 +276,10 @@ var Bounds = require('../geometry/Bounds'); offsetBX = contactVertex.x - bodyB.position.x, offsetBY = contactVertex.y - bodyB.position.y; - var velocityPointAX = bodyAVelocity.x - offsetAY * bodyA.angularVelocity, - velocityPointAY = bodyAVelocity.y + offsetAX * bodyA.angularVelocity, - velocityPointBX = bodyBVelocity.x - offsetBY * bodyB.angularVelocity, - velocityPointBY = bodyBVelocity.y + offsetBX * bodyB.angularVelocity; + var velocityPointAX = bodyAVelocityX - offsetAY * bodyAAngularVelocity, + velocityPointAY = bodyAVelocityY + offsetAX * bodyAAngularVelocity, + velocityPointBX = bodyBVelocityX - offsetBY * bodyBAngularVelocity, + velocityPointBY = bodyBVelocityY + offsetBX * bodyBAngularVelocity; var relativeVelocityX = velocityPointAX - velocityPointBX, relativeVelocityY = velocityPointAY - velocityPointBY; From 5b6f30b08c7edec08f1654f1e546c140f284bec0 Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 23 Jul 2023 14:08:35 +0100 Subject: [PATCH 06/14] changed Pair.id format to use shorter ids --- src/collision/Pair.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/collision/Pair.js b/src/collision/Pair.js index 72c54f43..eac2d974 100644 --- a/src/collision/Pair.js +++ b/src/collision/Pair.js @@ -125,11 +125,8 @@ var Contact = require('./Contact'); * @return {string} Unique pairId */ Pair.id = function(bodyA, bodyB) { - if (bodyA.id < bodyB.id) { - return 'A' + bodyA.id + 'B' + bodyB.id; - } else { - return 'A' + bodyB.id + 'B' + bodyA.id; - } + return bodyA.id < bodyB.id ? bodyA.id.toString(36) + ':' + bodyB.id.toString(36) + : bodyB.id.toString(36) + ':' + bodyA.id.toString(36); }; })(); From 72bc203c27549fa263c6183eea720e299a462527 Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 13 Aug 2023 14:54:30 +0100 Subject: [PATCH 07/14] removed pair.confirmedActive --- src/collision/Pair.js | 1 - src/collision/Pairs.js | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/collision/Pair.js b/src/collision/Pair.js index eac2d974..f1b4e6b0 100644 --- a/src/collision/Pair.js +++ b/src/collision/Pair.js @@ -32,7 +32,6 @@ var Contact = require('./Contact'); contactCount: 0, separation: 0, isActive: true, - confirmedActive: true, isSensor: bodyA.isSensor || bodyB.isSensor, timeCreated: timestamp, timeUpdated: timestamp, diff --git a/src/collision/Pairs.js b/src/collision/Pairs.js index bb223b54..99c02ca0 100644 --- a/src/collision/Pairs.js +++ b/src/collision/Pairs.js @@ -52,10 +52,6 @@ var Common = require('../core/Common'); pair, i; - for (i = 0; i < pairsListLength; i++) { - pairsList[i].confirmedActive = false; - } - for (i = 0; i < collisionsLength; i++) { collision = collisions[i]; pair = collision.pair; @@ -72,7 +68,6 @@ var Common = require('../core/Common'); // update the pair Pair.update(pair, collision, timestamp); - pair.confirmedActive = true; } else { // pair did not exist, create a new pair pair = Pair.create(collision, timestamp); @@ -91,7 +86,7 @@ var Common = require('../core/Common'); for (i = 0; i < pairsListLength; i++) { pair = pairsList[i]; - if (!pair.confirmedActive) { + if (pair.timeUpdated < timestamp) { Pair.setActive(pair, false, timestamp); collisionEnd[collisionEndIndex++] = pair; From e9da32c8864b9530925ff2c8d447cc6cafcffd7f Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 13 Aug 2023 15:31:52 +0100 Subject: [PATCH 08/14] added local pairs functions in Pairs.update --- src/collision/Pair.js | 2 +- src/collision/Pairs.js | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/collision/Pair.js b/src/collision/Pair.js index f1b4e6b0..f965313b 100644 --- a/src/collision/Pair.js +++ b/src/collision/Pair.js @@ -75,7 +75,7 @@ var Contact = require('./Contact'); collision.pair = pair; var support = supports[0], - contact = contacts[0]; + contact = contacts[0]; // reset first contact if support changed if (contact.vertex !== support) { diff --git a/src/collision/Pairs.js b/src/collision/Pairs.js index 99c02ca0..2cb9d186 100644 --- a/src/collision/Pairs.js +++ b/src/collision/Pairs.js @@ -37,14 +37,17 @@ var Common = require('../core/Common'); * @param {number} timestamp */ Pairs.update = function(pairs, collisions, timestamp) { - var pairsList = pairs.list, + var pairUpdate = Pair.update, + pairCreate = Pair.create, + pairSetActive = Pair.setActive, + pairsTable = pairs.table, + pairsList = pairs.list, pairsListLength = pairsList.length, pairsListIndex = pairsListLength, - pairsTable = pairs.table, - collisionsLength = collisions.length, collisionStart = pairs.collisionStart, collisionEnd = pairs.collisionEnd, collisionActive = pairs.collisionActive, + collisionsLength = collisions.length, collisionStartIndex = 0, collisionEndIndex = 0, collisionActiveIndex = 0, @@ -67,10 +70,10 @@ var Common = require('../core/Common'); } // update the pair - Pair.update(pair, collision, timestamp); + pairUpdate(pair, collision, timestamp); } else { // pair did not exist, create a new pair - pair = Pair.create(collision, timestamp); + pair = pairCreate(collision, timestamp); pairsTable[pair.id] = pair; // add the new pair @@ -87,7 +90,7 @@ var Common = require('../core/Common'); pair = pairsList[i]; if (pair.timeUpdated < timestamp) { - Pair.setActive(pair, false, timestamp); + pairSetActive(pair, false, timestamp); collisionEnd[collisionEndIndex++] = pair; // remove inactive pairs From 51f49ce9d38f6b4ab3bb24c064358724308d7234 Mon Sep 17 00:00:00 2001 From: liabru Date: Mon, 13 Nov 2023 23:32:39 +0000 Subject: [PATCH 09/14] fix collision events for sleeping pairs, closes #1077 --- src/collision/Pairs.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/collision/Pairs.js b/src/collision/Pairs.js index 2cb9d186..ac00e82b 100644 --- a/src/collision/Pairs.js +++ b/src/collision/Pairs.js @@ -64,9 +64,6 @@ var Common = require('../core/Common'); if (pair.isActive) { // pair exists and is active collisionActive[collisionActiveIndex++] = pair; - } else { - // pair exists but was inactive, so a collision has just started again - collisionStart[collisionStartIndex++] = pair; } // update the pair @@ -89,16 +86,21 @@ var Common = require('../core/Common'); for (i = 0; i < pairsListLength; i++) { pair = pairsList[i]; - if (pair.timeUpdated < timestamp) { + // pair is active if updated this timestep + if (pair.timeUpdated >= timestamp) { + // keep active pairs + pairsList[pairsListIndex++] = pair; + } else { pairSetActive(pair, false, timestamp); - collisionEnd[collisionEndIndex++] = pair; - // remove inactive pairs - if (!pair.collision.bodyA.isSleeping && !pair.collision.bodyB.isSleeping) { + // keep inactive pairs if both bodies may be sleeping + if (pair.collision.bodyA.sleepCounter > 0 && pair.collision.bodyB.sleepCounter > 0) { + pairsList[pairsListIndex++] = pair; + } else { + // remove inactive pairs if either body awake + collisionEnd[collisionEndIndex++] = pair; delete pairsTable[pair.id]; } - } else { - pairsList[pairsListIndex++] = pair; } } From 6f8a54b253b4e7bd475588ae660ba61d6d4d4872 Mon Sep 17 00:00:00 2001 From: liabru Date: Tue, 14 Nov 2023 21:01:43 +0000 Subject: [PATCH 10/14] optimised Collision.collides --- src/collision/Collision.js | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/collision/Collision.js b/src/collision/Collision.js index 58ae8f75..4aa5ca3c 100644 --- a/src/collision/Collision.js +++ b/src/collision/Collision.js @@ -100,27 +100,32 @@ var Pair = require('./Pair'); } var normal = collision.normal, + tangent = collision.tangent, + penetration = collision.penetration, supports = collision.supports, + depth = minOverlap.overlap, minAxis = minOverlap.axis, - minAxisX = minAxis.x, - minAxisY = minAxis.y; + normalX = minAxis.x, + normalY = minAxis.y, + deltaX = bodyB.position.x - bodyA.position.x, + deltaY = bodyB.position.y - bodyA.position.y; // ensure normal is facing away from bodyA - if (minAxisX * (bodyB.position.x - bodyA.position.x) + minAxisY * (bodyB.position.y - bodyA.position.y) < 0) { - normal.x = minAxisX; - normal.y = minAxisY; - } else { - normal.x = -minAxisX; - normal.y = -minAxisY; + if (normalX * deltaX + normalY * deltaY >= 0) { + normalX = -normalX; + normalY = -normalY; } + + normal.x = normalX; + normal.y = normalY; - collision.tangent.x = -normal.y; - collision.tangent.y = normal.x; + tangent.x = -normalY; + tangent.y = normalX; - collision.depth = minOverlap.overlap; + penetration.x = normalX * depth; + penetration.y = normalY * depth; - collision.penetration.x = normal.x * collision.depth; - collision.penetration.y = normal.y * collision.depth; + collision.depth = depth; // find support points, there is always either exactly one or two var supportsB = Collision._findSupports(bodyA, bodyB, normal, 1), From 6d10c3d14e58c00812b7f1bcf36c7ab36971eb90 Mon Sep 17 00:00:00 2001 From: liabru Date: Sat, 25 Nov 2023 14:04:56 +0000 Subject: [PATCH 11/14] changed Composte.removeComposite and Composte.removeBody to reset body.sleepCounter --- src/body/Composite.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/body/Composite.js b/src/body/Composite.js index b814d7d2..efbe6f3c 100644 --- a/src/body/Composite.js +++ b/src/body/Composite.js @@ -192,8 +192,15 @@ var Body = require('./Body'); */ Composite.removeComposite = function(compositeA, compositeB, deep) { var position = Common.indexOf(compositeA.composites, compositeB); + if (position !== -1) { + var bodies = Composite.allBodies(compositeB); + Composite.removeCompositeAt(compositeA, position); + + for (var i = 0; i < bodies.length; i++) { + bodies[i].sleepCounter = 0; + } } if (deep) { @@ -244,8 +251,10 @@ var Body = require('./Body'); */ Composite.removeBody = function(composite, body, deep) { var position = Common.indexOf(composite.bodies, body); + if (position !== -1) { Composite.removeBodyAt(composite, position); + body.sleepCounter = 0; } if (deep) { @@ -296,6 +305,7 @@ var Body = require('./Body'); */ Composite.removeConstraint = function(composite, constraint, deep) { var position = Common.indexOf(composite.constraints, constraint); + if (position !== -1) { Composite.removeConstraintAt(composite, position); } From 1209e88fe247df8dee0f1072d57324ae2ba5491f Mon Sep 17 00:00:00 2001 From: liabru Date: Sat, 25 Nov 2023 14:06:04 +0000 Subject: [PATCH 12/14] added body removal to Example.remove --- examples/remove.js | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/examples/remove.js b/examples/remove.js index cd4db31f..38ff103f 100644 --- a/examples/remove.js +++ b/examples/remove.js @@ -13,8 +13,11 @@ Example.remove = function() { Events = Matter.Events; // create engine - var engine = Engine.create(), - world = engine.world; + var engine = Engine.create({ + enableSleeping: true + }); + + var world = engine.world; // create renderer var render = Render.create({ @@ -24,6 +27,7 @@ Example.remove = function() { width: 800, height: 600, showAngleIndicator: true, + showSleeping: true } }); @@ -33,9 +37,6 @@ Example.remove = function() { var runner = Runner.create(); Runner.run(runner, engine); - var stack = null, - lastTimestamp = 0; - var createStack = function() { return Composites.stack(20, 20, 10, 5, 0, 0, function(x, y) { var sides = Math.round(Common.random(1, 8)); @@ -61,15 +62,28 @@ Example.remove = function() { }); }; - // add and remove stacks every few updates + var stack = null, + bottomStack = createStack(), + lastTimestamp = 0; + + // add and remove bodies and composites every few updates Events.on(engine, 'afterUpdate', function(event) { // limit rate - if (stack && event.timestamp - lastTimestamp < 800) { + if (event.timestamp - lastTimestamp < 800) { return; } lastTimestamp = event.timestamp; + // remove an old body + Composite.remove(bottomStack, bottomStack.bodies[0]); + + // add a new body + Composite.add( + bottomStack, + Bodies.rectangle(Common.random(100, 500), 50, Common.random(25, 50), Common.random(25, 50)) + ); + // remove last stack if (stack) { Composite.remove(world, stack); @@ -82,10 +96,9 @@ Example.remove = function() { Composite.add(world, stack); }); - // add another stack that will not be removed - Composite.add(world, createStack()); - Composite.add(world, [ + bottomStack, + // walls Bodies.rectangle(400, 0, 800, 50, { isStatic: true }), Bodies.rectangle(400, 600, 800, 50, { isStatic: true }), From 89963f77a04a9c44dc53fe0d041c3edb28fda8db Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 3 Mar 2024 21:48:05 +0000 Subject: [PATCH 13/14] optimised Resolver.solvePosition --- src/collision/Resolver.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/collision/Resolver.js b/src/collision/Resolver.js index df0a5937..db44fb8e 100644 --- a/src/collision/Resolver.js +++ b/src/collision/Resolver.js @@ -79,8 +79,8 @@ var Bounds = require('../geometry/Bounds'); // get current separation between body edges involved in collision pair.separation = - normal.x * (bodyB.positionImpulse.x + collision.penetration.x - bodyA.positionImpulse.x) - + normal.y * (bodyB.positionImpulse.y + collision.penetration.y - bodyA.positionImpulse.y); + collision.depth + normal.x * (bodyB.positionImpulse.x - bodyA.positionImpulse.x) + + normal.y * (bodyB.positionImpulse.y - bodyA.positionImpulse.y); } for (i = 0; i < pairsLength; i++) { From e891d37b65ed7e706d37643300c73eca6a222aea Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 3 Mar 2024 21:50:40 +0000 Subject: [PATCH 14/14] preserve pair.contacts order --- src/collision/Pair.js | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/collision/Pair.js b/src/collision/Pair.js index f965313b..549ff366 100644 --- a/src/collision/Pair.js +++ b/src/collision/Pair.js @@ -74,29 +74,21 @@ var Contact = require('./Contact'); pair.contactCount = supportCount; collision.pair = pair; - var support = supports[0], - contact = contacts[0]; - - // reset first contact if support changed - if (contact.vertex !== support) { - contact.vertex = support; - contact.normalImpulse = 0; - contact.tangentImpulse = 0; - } - - if (supportCount < 2) { - return; + var supportA = supports[0], + contactA = contacts[0], + supportB = supports[1], + contactB = contacts[1]; + + // match contacts to supports + if (contactB.vertex === supportA || contactA.vertex === supportB) { + contacts[1] = contactA; + contacts[0] = contactA = contactB; + contactB = contacts[1]; } - support = supports[1]; - contact = contacts[1]; - - // reset second contact if support changed - if (contact.vertex !== support) { - contact.vertex = support; - contact.normalImpulse = 0; - contact.tangentImpulse = 0; - } + // update contacts + contactA.vertex = supportA; + contactB.vertex = supportB; }; /**