Skip to content

Commit 0784a5b

Browse files
committed
Added readonly body.deltaTime
Added delta property to engine update event Added delta argument to various internal functions Changed timeScale argument to use delta instead on various internal functions Fixed issues when using an engine update delta of 0 Improved time independence for friction, air friction, restitution, sleeping, collisions, constraints Removed optional correction argument from Engine.update Removed correction and timeScale from Body.update and Matter.Runner
1 parent 2ec247b commit 0784a5b

9 files changed

Lines changed: 114 additions & 107 deletions

File tree

src/body/Body.js

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ module.exports = Body;
1515
var Vertices = require('../geometry/Vertices');
1616
var Vector = require('../geometry/Vector');
1717
var Sleeping = require('../core/Sleeping');
18-
var Render = require('../render/Render');
1918
var Common = require('../core/Common');
2019
var Bounds = require('../geometry/Bounds');
2120
var Axes = require('../geometry/Axes');
2221

2322
(function() {
2423

24+
Body._timeCorrection = true;
2525
Body._inertiaScale = 4;
2626
Body._nextCollidingGroupId = 1;
2727
Body._nextNonCollidingGroupId = -1;
@@ -95,6 +95,7 @@ var Axes = require('../geometry/Axes');
9595
area: 0,
9696
mass: 0,
9797
inertia: 0,
98+
deltaTime: null,
9899
_original: null
99100
};
100101

@@ -462,8 +463,8 @@ var Axes = require('../geometry/Axes');
462463
*/
463464
Body.setPosition = function(body, position) {
464465
var delta = Vector.sub(position, body.position);
465-
body.positionPrev.x += delta.x;
466-
body.positionPrev.y += delta.y;
466+
body.positionPrev.x += delta.x;
467+
body.positionPrev.y += delta.y;
467468

468469
for (var i = 0; i < body.parts.length; i++) {
469470
var part = body.parts[i];
@@ -482,7 +483,7 @@ var Axes = require('../geometry/Axes');
482483
*/
483484
Body.setAngle = function(body, angle) {
484485
var delta = angle - body.angle;
485-
body.anglePrev += delta;
486+
body.anglePrev += delta;
486487

487488
for (var i = 0; i < body.parts.length; i++) {
488489
var part = body.parts[i];
@@ -625,26 +626,28 @@ var Axes = require('../geometry/Axes');
625626
* Performs a simulation step for the given `body`, including updating position and angle using Verlet integration.
626627
* @method update
627628
* @param {body} body
628-
* @param {number} deltaTime
629-
* @param {number} timeScale
630-
* @param {number} correction
629+
* @param {number} [deltaTime=16.666]
631630
*/
632-
Body.update = function(body, deltaTime, timeScale, correction) {
633-
var deltaTimeSquared = Math.pow(deltaTime * timeScale * body.timeScale, 2);
631+
Body.update = function(body, deltaTime) {
632+
deltaTime = (typeof deltaTime !== 'undefined' ? deltaTime : Common._timeUnit) * body.timeScale;
633+
634+
var deltaTimeSquared = deltaTime * deltaTime,
635+
correction = Body._timeCorrection ? deltaTime / (body.deltaTime || deltaTime) : 1;
634636

635637
// from the previous step
636-
var frictionAir = 1 - body.frictionAir * timeScale * body.timeScale,
637-
velocityPrevX = body.position.x - body.positionPrev.x,
638-
velocityPrevY = body.position.y - body.positionPrev.y;
638+
var frictionAir = 1 - body.frictionAir * (deltaTime / Common._timeUnit),
639+
velocityPrevX = (body.position.x - body.positionPrev.x) * correction,
640+
velocityPrevY = (body.position.y - body.positionPrev.y) * correction;
639641

640642
// update velocity with Verlet integration
641-
body.velocity.x = (velocityPrevX * frictionAir * correction) + (body.force.x / body.mass) * deltaTimeSquared;
642-
body.velocity.y = (velocityPrevY * frictionAir * correction) + (body.force.y / body.mass) * deltaTimeSquared;
643+
body.velocity.x = (velocityPrevX * frictionAir) + (body.force.x / body.mass) * deltaTimeSquared;
644+
body.velocity.y = (velocityPrevY * frictionAir) + (body.force.y / body.mass) * deltaTimeSquared;
643645

644646
body.positionPrev.x = body.position.x;
645647
body.positionPrev.y = body.position.y;
646648
body.position.x += body.velocity.x;
647649
body.position.y += body.velocity.y;
650+
body.deltaTime = deltaTime;
648651

649652
// update angular velocity with Verlet integration
650653
body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared;
@@ -880,7 +883,7 @@ var Axes = require('../geometry/Axes');
880883
/**
881884
* A `Vector` that _measures_ the current velocity of the body after the last `Body.update`. It is read-only.
882885
* If you need to modify a body's velocity directly, you should either apply a force or simply change the body's `position` (as the engine uses position-Verlet integration).
883-
*
886+
*
884887
* @readOnly
885888
* @property velocity
886889
* @type vector
@@ -1109,6 +1112,16 @@ var Axes = require('../geometry/Axes');
11091112
* @default 1
11101113
*/
11111114

1115+
/**
1116+
* A `Number` that records the last delta time value used to update this body.
1117+
* This is automatically updated by the engine inside of `Body.update`.
1118+
*
1119+
* @readOnly
1120+
* @property deltaTime
1121+
* @type number
1122+
* @default null
1123+
*/
1124+
11121125
/**
11131126
* An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`.
11141127
*

src/collision/Detector.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ var Bounds = require('../geometry/Bounds');
2121
* @method collisions
2222
* @param {pair[]} broadphasePairs
2323
* @param {engine} engine
24+
* @param {number} delta
2425
* @return {array} collisions
2526
*/
26-
Detector.collisions = function(broadphasePairs, engine) {
27+
Detector.collisions = function(broadphasePairs, engine, delta) {
2728
var collisions = [],
2829
pairsTable = engine.pairs.table;
2930

@@ -66,7 +67,7 @@ var Bounds = require('../geometry/Bounds');
6667
}
6768

6869
// narrow phase
69-
var collision = SAT.collides(partA, partB, previousCollision);
70+
var collision = SAT.collides(partA, partB, previousCollision, delta);
7071

7172
// @if DEBUG
7273
metrics.narrowphaseTests += 1;

src/collision/Resolver.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ var Bounds = require('../geometry/Bounds');
4949
* @method solvePosition
5050
* @param {pair[]} pairs
5151
* @param {body[]} bodies
52-
* @param {number} timeScale
52+
* @param {number} delta
5353
*/
54-
Resolver.solvePosition = function(pairs, bodies, timeScale) {
54+
Resolver.solvePosition = function(pairs, bodies, delta) {
5555
var i,
5656
normalX,
5757
normalY,
@@ -68,7 +68,8 @@ var Bounds = require('../geometry/Bounds');
6868
bodyBtoAX,
6969
bodyBtoAY,
7070
positionImpulse,
71-
impulseCoefficient = timeScale * Resolver._positionDampen;
71+
timeScale = delta / Common._timeUnit,
72+
impulseCoefficient = Resolver._positionDampen * timeScale;
7273

7374
for (i = 0; i < bodies.length; i++) {
7475
var body = bodies[i];
@@ -231,10 +232,12 @@ var Bounds = require('../geometry/Bounds');
231232
* Find a solution for pair velocities.
232233
* @method solveVelocity
233234
* @param {pair[]} pairs
234-
* @param {number} timeScale
235+
* @param {number} delta
235236
*/
236-
Resolver.solveVelocity = function(pairs, timeScale) {
237-
var timeScaleSquared = timeScale * timeScale,
237+
Resolver.solveVelocity = function(pairs, delta) {
238+
var timeScale = delta / Common._timeUnit,
239+
timeScale2 = timeScale * timeScale,
240+
timeScale3 = timeScale2 * timeScale,
238241
impulse = Vector._temp[0],
239242
tempA = Vector._temp[1],
240243
tempB = Vector._temp[2],
@@ -287,10 +290,10 @@ var Bounds = require('../geometry/Bounds');
287290
var tangentImpulse = tangentVelocity,
288291
maxFriction = Infinity;
289292

290-
if (tangentSpeed > pair.friction * pair.frictionStatic * normalForce * timeScaleSquared) {
291-
maxFriction = tangentSpeed;
293+
if (tangentSpeed > pair.friction * pair.frictionStatic * normalForce * timeScale3) {
294+
maxFriction = tangentSpeed * timeScale;
292295
tangentImpulse = Common.clamp(
293-
pair.friction * tangentVelocityDirection * timeScaleSquared,
296+
pair.friction * tangentVelocityDirection * timeScale3,
294297
-maxFriction, maxFriction
295298
);
296299
}
@@ -304,7 +307,7 @@ var Bounds = require('../geometry/Bounds');
304307
tangentImpulse *= share;
305308

306309
// handle high velocity and resting collisions separately
307-
if (normalVelocity < 0 && normalVelocity * normalVelocity > Resolver._restingThresh * timeScaleSquared) {
310+
if (normalVelocity < 0 && normalVelocity * normalVelocity > Resolver._restingThresh * timeScale2) {
308311
// high normal velocity so clear cached contact normal impulse
309312
contact.normalImpulse = 0;
310313
} else {
@@ -316,7 +319,7 @@ var Bounds = require('../geometry/Bounds');
316319
}
317320

318321
// handle high velocity and resting collisions separately
319-
if (tangentVelocity * tangentVelocity > Resolver._restingThreshTangent * timeScaleSquared) {
322+
if (tangentVelocity * tangentVelocity > Resolver._restingThreshTangent * timeScale2) {
320323
// high tangent velocity so clear cached contact tangent impulse
321324
contact.tangentImpulse = 0;
322325
} else {

src/collision/SAT.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,30 @@ module.exports = SAT;
1212

1313
var Vertices = require('../geometry/Vertices');
1414
var Vector = require('../geometry/Vector');
15+
var Common = require('../core/Common');
1516

1617
(function() {
1718

19+
SAT._reuseMotionThresh = 0.2;
20+
1821
/**
1922
* Detect collision between two bodies using the Separating Axis Theorem.
2023
* @method collides
2124
* @param {body} bodyA
2225
* @param {body} bodyB
2326
* @param {collision} previousCollision
27+
* @param {number} [delta=0]
2428
* @return {collision} collision
2529
*/
26-
SAT.collides = function(bodyA, bodyB, previousCollision) {
30+
SAT.collides = function(bodyA, bodyB, previousCollision, delta) {
2731
var overlapAB,
2832
overlapBA,
2933
minOverlap,
3034
collision,
31-
canReusePrevCol = false;
35+
canReusePrevCol = false,
36+
timeScale = delta / Common._timeUnit;
37+
38+
delta = typeof delta !== 'undefined' ? delta : 0;
3239

3340
if (previousCollision) {
3441
// estimate total motion
@@ -39,7 +46,7 @@ var Vector = require('../geometry/Vector');
3946

4047
// we may be able to (partially) reuse collision result
4148
// but only safe if collision was resting
42-
canReusePrevCol = previousCollision && previousCollision.collided && motion < 0.2;
49+
canReusePrevCol = previousCollision && previousCollision.collided && motion < SAT._reuseMotionThresh * timeScale * timeScale;
4350

4451
// reuse collision object
4552
collision = previousCollision;

src/constraint/Constraint.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,11 @@ var Common = require('../core/Common');
110110
* @private
111111
* @method solveAll
112112
* @param {constraint[]} constraints
113-
* @param {number} timeScale
113+
* @param {number} delta
114114
*/
115-
Constraint.solveAll = function(constraints, timeScale) {
115+
Constraint.solveAll = function(constraints, delta) {
116+
var timeScale = Common.clamp(delta / Common._timeUnit, 0, 1);
117+
116118
// Solve fixed constraints first.
117119
for (var i = 0; i < constraints.length; i += 1) {
118120
var constraint = constraints[i],
@@ -183,7 +185,9 @@ var Common = require('../core/Common');
183185

184186
// solve distance constraint with Gauss-Siedel method
185187
var difference = (currentLength - constraint.length) / currentLength,
186-
stiffness = constraint.stiffness < 1 ? constraint.stiffness * timeScale : constraint.stiffness,
188+
isRigid = constraint.stiffness >= 1 || constraint.length === 0,
189+
stiffness = isRigid ? constraint.stiffness : constraint.stiffness * timeScale * timeScale,
190+
damping = constraint.damping * timeScale,
187191
force = Vector.mult(delta, difference * stiffness),
188192
massTotal = (bodyA ? bodyA.inverseMass : 0) + (bodyB ? bodyB.inverseMass : 0),
189193
inertiaTotal = (bodyA ? bodyA.inverseInertia : 0) + (bodyB ? bodyB.inverseInertia : 0),
@@ -193,8 +197,8 @@ var Common = require('../core/Common');
193197
normal,
194198
normalVelocity,
195199
relativeVelocity;
196-
197-
if (constraint.damping) {
200+
201+
if (damping > 0) {
198202
var zero = Vector.create();
199203
normal = Vector.div(delta, currentLength);
200204

@@ -218,9 +222,9 @@ var Common = require('../core/Common');
218222
bodyA.position.y -= force.y * share;
219223

220224
// apply damping
221-
if (constraint.damping) {
222-
bodyA.positionPrev.x -= constraint.damping * normal.x * normalVelocity * share;
223-
bodyA.positionPrev.y -= constraint.damping * normal.y * normalVelocity * share;
225+
if (damping > 0) {
226+
bodyA.positionPrev.x -= damping * normal.x * normalVelocity * share;
227+
bodyA.positionPrev.y -= damping * normal.y * normalVelocity * share;
224228
}
225229

226230
// apply torque
@@ -241,9 +245,9 @@ var Common = require('../core/Common');
241245
bodyB.position.y += force.y * share;
242246

243247
// apply damping
244-
if (constraint.damping) {
245-
bodyB.positionPrev.x += constraint.damping * normal.x * normalVelocity * share;
246-
bodyB.positionPrev.y += constraint.damping * normal.y * normalVelocity * share;
248+
if (damping > 0) {
249+
bodyB.positionPrev.x += damping * normal.x * normalVelocity * share;
250+
bodyB.positionPrev.y += damping * normal.y * normalVelocity * share;
247251
}
248252

249253
// apply torque

src/core/Common.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module.exports = Common;
1010

1111
(function() {
1212

13+
Common._timeUnit = 1000 / 60;
1314
Common._nextId = 0;
1415
Common._seed = 0;
1516
Common._nowStartTime = +(new Date());

0 commit comments

Comments
 (0)