Skip to content

Commit 4e6a8d9

Browse files
authored
Merge pull request #1238 from liabru/performance-2
Improved performance and reduced memory usage
2 parents 962fba5 + 5e503e3 commit 4e6a8d9

File tree

10 files changed

+198
-159
lines changed

10 files changed

+198
-159
lines changed

examples/remove.js

+23-10
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ Example.remove = function() {
1313
Events = Matter.Events;
1414

1515
// create engine
16-
var engine = Engine.create(),
17-
world = engine.world;
16+
var engine = Engine.create({
17+
enableSleeping: true
18+
});
19+
20+
var world = engine.world;
1821

1922
// create renderer
2023
var render = Render.create({
@@ -24,6 +27,7 @@ Example.remove = function() {
2427
width: 800,
2528
height: 600,
2629
showAngleIndicator: true,
30+
showSleeping: true
2731
}
2832
});
2933

@@ -33,9 +37,6 @@ Example.remove = function() {
3337
var runner = Runner.create();
3438
Runner.run(runner, engine);
3539

36-
var stack = null,
37-
lastTimestamp = 0;
38-
3940
var createStack = function() {
4041
return Composites.stack(20, 20, 10, 5, 0, 0, function(x, y) {
4142
var sides = Math.round(Common.random(1, 8));
@@ -61,15 +62,28 @@ Example.remove = function() {
6162
});
6263
};
6364

64-
// add and remove stacks every few updates
65+
var stack = null,
66+
bottomStack = createStack(),
67+
lastTimestamp = 0;
68+
69+
// add and remove bodies and composites every few updates
6570
Events.on(engine, 'afterUpdate', function(event) {
6671
// limit rate
67-
if (stack && event.timestamp - lastTimestamp < 800) {
72+
if (event.timestamp - lastTimestamp < 800) {
6873
return;
6974
}
7075

7176
lastTimestamp = event.timestamp;
7277

78+
// remove an old body
79+
Composite.remove(bottomStack, bottomStack.bodies[0]);
80+
81+
// add a new body
82+
Composite.add(
83+
bottomStack,
84+
Bodies.rectangle(Common.random(100, 500), 50, Common.random(25, 50), Common.random(25, 50))
85+
);
86+
7387
// remove last stack
7488
if (stack) {
7589
Composite.remove(world, stack);
@@ -82,10 +96,9 @@ Example.remove = function() {
8296
Composite.add(world, stack);
8397
});
8498

85-
// add another stack that will not be removed
86-
Composite.add(world, createStack());
87-
8899
Composite.add(world, [
100+
bottomStack,
101+
89102
// walls
90103
Bodies.rectangle(400, 0, 800, 50, { isStatic: true }),
91104
Bodies.rectangle(400, 600, 800, 50, { isStatic: true }),

src/body/Composite.js

+10
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,15 @@ var Body = require('./Body');
192192
*/
193193
Composite.removeComposite = function(compositeA, compositeB, deep) {
194194
var position = Common.indexOf(compositeA.composites, compositeB);
195+
195196
if (position !== -1) {
197+
var bodies = Composite.allBodies(compositeB);
198+
196199
Composite.removeCompositeAt(compositeA, position);
200+
201+
for (var i = 0; i < bodies.length; i++) {
202+
bodies[i].sleepCounter = 0;
203+
}
197204
}
198205

199206
if (deep) {
@@ -244,8 +251,10 @@ var Body = require('./Body');
244251
*/
245252
Composite.removeBody = function(composite, body, deep) {
246253
var position = Common.indexOf(composite.bodies, body);
254+
247255
if (position !== -1) {
248256
Composite.removeBodyAt(composite, position);
257+
body.sleepCounter = 0;
249258
}
250259

251260
if (deep) {
@@ -296,6 +305,7 @@ var Body = require('./Body');
296305
*/
297306
Composite.removeConstraint = function(composite, constraint, deep) {
298307
var position = Common.indexOf(composite.constraints, constraint);
308+
299309
if (position !== -1) {
300310
Composite.removeConstraintAt(composite, position);
301311
}

src/collision/Collision.js

+41-46
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ var Pair = require('./Pair');
4747
normal: { x: 0, y: 0 },
4848
tangent: { x: 0, y: 0 },
4949
penetration: { x: 0, y: 0 },
50-
supports: []
50+
supports: [null, null],
51+
supportCount: 0
5152
};
5253
};
5354

@@ -99,27 +100,32 @@ var Pair = require('./Pair');
99100
}
100101

101102
var normal = collision.normal,
103+
tangent = collision.tangent,
104+
penetration = collision.penetration,
102105
supports = collision.supports,
106+
depth = minOverlap.overlap,
103107
minAxis = minOverlap.axis,
104-
minAxisX = minAxis.x,
105-
minAxisY = minAxis.y;
108+
normalX = minAxis.x,
109+
normalY = minAxis.y,
110+
deltaX = bodyB.position.x - bodyA.position.x,
111+
deltaY = bodyB.position.y - bodyA.position.y;
106112

107113
// 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+
if (normalX * deltaX + normalY * deltaY >= 0) {
115+
normalX = -normalX;
116+
normalY = -normalY;
114117
}
118+
119+
normal.x = normalX;
120+
normal.y = normalY;
115121

116-
collision.tangent.x = -normal.y;
117-
collision.tangent.y = normal.x;
122+
tangent.x = -normalY;
123+
tangent.y = normalX;
118124

119-
collision.depth = minOverlap.overlap;
125+
penetration.x = normalX * depth;
126+
penetration.y = normalY * depth;
120127

121-
collision.penetration.x = normal.x * collision.depth;
122-
collision.penetration.y = normal.y * collision.depth;
128+
collision.depth = depth;
123129

124130
// find support points, there is always either exactly one or two
125131
var supportsB = Collision._findSupports(bodyA, bodyB, normal, 1),
@@ -152,8 +158,8 @@ var Pair = require('./Pair');
152158
supports[supportCount++] = supportsB[0];
153159
}
154160

155-
// update supports array size
156-
supports.length = supportCount;
161+
// update support count
162+
collision.supportCount = supportCount;
157163

158164
return collision;
159165
};
@@ -232,32 +238,6 @@ var Pair = require('./Pair');
232238
result.overlap = overlapMin;
233239
};
234240

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-
261241
/**
262242
* Finds supporting vertices given two bodies along a given direction using hill-climbing.
263243
* @method _findSupports
@@ -275,15 +255,15 @@ var Pair = require('./Pair');
275255
bodyAPositionY = bodyA.position.y,
276256
normalX = normal.x * direction,
277257
normalY = normal.y * direction,
278-
nearestDistance = Number.MAX_VALUE,
279-
vertexA,
280-
vertexB,
258+
vertexA = vertices[0],
259+
vertexB = vertexA,
260+
nearestDistance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y),
281261
vertexC,
282262
distance,
283263
j;
284264

285265
// find deepest vertex relative to the axis
286-
for (j = 0; j < verticesLength; j += 1) {
266+
for (j = 1; j < verticesLength; j += 1) {
287267
vertexB = vertices[j];
288268
distance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y);
289269

@@ -398,11 +378,26 @@ var Pair = require('./Pair');
398378

399379
/**
400380
* An array of body vertices that represent the support points in the collision.
381+
*
382+
* _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active.
383+
* Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports.
384+
*
401385
* These are the deepest vertices (along the collision normal) of each body that are contained by the other body's vertices.
402386
*
403387
* @property supports
404388
* @type vector[]
405389
* @default []
406390
*/
407391

392+
/**
393+
* The number of active supports for this collision found in `collision.supports`.
394+
*
395+
* _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active.
396+
* Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports.
397+
*
398+
* @property supportCount
399+
* @type number
400+
* @default 0
401+
*/
402+
408403
})();

src/collision/Contact.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = Contact;
1313
/**
1414
* Creates a new contact.
1515
* @method create
16-
* @param {vertex} vertex
16+
* @param {vertex} [vertex]
1717
* @return {contact} A new contact
1818
*/
1919
Contact.create = function(vertex) {

src/collision/Detector.js

+18-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var Collision = require('./Collision');
2222
Detector.create = function(options) {
2323
var defaults = {
2424
bodies: [],
25+
collisions: [],
2526
pairs: null
2627
};
2728

@@ -45,6 +46,7 @@ var Collision = require('./Collision');
4546
*/
4647
Detector.clear = function(detector) {
4748
detector.bodies = [];
49+
detector.collisions = [];
4850
};
4951

5052
/**
@@ -57,12 +59,13 @@ var Collision = require('./Collision');
5759
* @return {collision[]} collisions
5860
*/
5961
Detector.collisions = function(detector) {
60-
var collisions = [],
61-
pairs = detector.pairs,
62+
var pairs = detector.pairs,
6263
bodies = detector.bodies,
6364
bodiesLength = bodies.length,
6465
canCollide = Detector.canCollide,
6566
collides = Collision.collides,
67+
collisions = detector.collisions,
68+
collisionIndex = 0,
6669
i,
6770
j;
6871

@@ -104,7 +107,7 @@ var Collision = require('./Collision');
104107
var collision = collides(bodyA, bodyB, pairs);
105108

106109
if (collision) {
107-
collisions.push(collision);
110+
collisions[collisionIndex++] = collision;
108111
}
109112
} else {
110113
var partsAStart = partsALength > 1 ? 1 : 0,
@@ -126,14 +129,18 @@ var Collision = require('./Collision');
126129
var collision = collides(partA, partB, pairs);
127130

128131
if (collision) {
129-
collisions.push(collision);
132+
collisions[collisionIndex++] = collision;
130133
}
131134
}
132135
}
133136
}
134137
}
135138
}
136139

140+
if (collisions.length !== collisionIndex) {
141+
collisions.length = collisionIndex;
142+
}
143+
137144
return collisions;
138145
};
139146

@@ -180,6 +187,13 @@ var Collision = require('./Collision');
180187
* @default []
181188
*/
182189

190+
/**
191+
* The array of `Matter.Collision` found in the last call to `Detector.collisions` on this detector.
192+
* @property collisions
193+
* @type collision[]
194+
* @default []
195+
*/
196+
183197
/**
184198
* Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage.
185199
* @property pairs

0 commit comments

Comments
 (0)