Skip to content

Commit

Permalink
optimised contacts and supports memory and gc use
Browse files Browse the repository at this point in the history
  • Loading branch information
liabru committed Jul 23, 2023
1 parent f9208df commit 97d502e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 50 deletions.
24 changes: 19 additions & 5 deletions src/collision/Collision.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
};

Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -374,11 +373,26 @@ 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
* @type vector[]
* @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
*/

})();
2 changes: 1 addition & 1 deletion src/collision/Contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
53 changes: 28 additions & 25 deletions src/collision/Pair.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand All @@ -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;
}
};

Expand All @@ -110,7 +113,7 @@ var Contact = require('./Contact');
pair.timeUpdated = timestamp;
} else {
pair.isActive = false;
pair.activeContacts.length = 0;
pair.contactCount = 0;
}
};

Expand Down
22 changes: 11 additions & 11 deletions src/collision/Resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
};

Expand Down Expand Up @@ -176,16 +176,16 @@ 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,
normal = collision.normal,
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,
Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand Down
16 changes: 8 additions & 8 deletions src/render/Render.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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) {
Expand Down

0 comments on commit 97d502e

Please sign in to comment.