0
0
Fork 0
mirror of https://github.com/liabru/matter-js.git synced 2025-02-01 18:24:54 -05:00

improved delta consistency

This commit is contained in:
liabru 2022-01-01 21:20:52 +00:00
parent 11d5e73c1f
commit 87af8a1740
3 changed files with 27 additions and 28 deletions

View file

@ -9,17 +9,17 @@ var Resolver = {};
module.exports = Resolver; module.exports = Resolver;
var Vertices = require('../geometry/Vertices'); var Vertices = require('../geometry/Vertices');
var Vector = require('../geometry/Vector');
var Common = require('../core/Common'); var Common = require('../core/Common');
var Bounds = require('../geometry/Bounds'); var Bounds = require('../geometry/Bounds');
(function() { (function() {
Resolver._restingThresh = 4; Resolver._restingThresh = 2;
Resolver._restingThreshTangent = 6; Resolver._restingThreshTangent = Math.sqrt(6);
Resolver._positionDampen = 0.9; Resolver._positionDampen = 0.9;
Resolver._positionWarming = 0.8; Resolver._positionWarming = 0.8;
Resolver._frictionNormalMultiplier = 5; Resolver._frictionNormalMultiplier = 5;
Resolver._frictionMaxStatic = Number.MAX_VALUE;
/** /**
* Prepare pairs for position solving. * Prepare pairs for position solving.
@ -49,9 +49,9 @@ var Bounds = require('../geometry/Bounds');
* Find a solution for pair positions. * Find a solution for pair positions.
* @method solvePosition * @method solvePosition
* @param {pair[]} pairs * @param {pair[]} pairs
* @param {number} delta * @param {number} positionIterations
*/ */
Resolver.solvePosition = function(pairs, delta) { Resolver.solvePosition = function(pairs, positionIterations) {
var i, var i,
pair, pair,
collision, collision,
@ -60,9 +60,7 @@ var Bounds = require('../geometry/Bounds');
normal, normal,
contactShare, contactShare,
positionImpulse, positionImpulse,
timeScale = delta / Common._timeUnit, positionDampen = Resolver._positionDampen * Common.clamp(20 / positionIterations, 0, 1),
damping = Common.clamp(Resolver._positionDampen * timeScale, 0, 1),
positionDampen = Resolver._positionDampen,
pairsLength = pairs.length; pairsLength = pairs.length;
// find impulses required to resolve penetration // find impulses required to resolve penetration
@ -93,7 +91,7 @@ var Bounds = require('../geometry/Bounds');
bodyA = collision.parentA; bodyA = collision.parentA;
bodyB = collision.parentB; bodyB = collision.parentB;
normal = collision.normal; normal = collision.normal;
positionImpulse = (pair.separation - pair.slop) * damping; positionImpulse = pair.separation - pair.slop;
if (bodyA.isStatic || bodyB.isStatic) if (bodyA.isStatic || bodyB.isStatic)
positionImpulse *= 2; positionImpulse *= 2;
@ -227,12 +225,12 @@ var Bounds = require('../geometry/Bounds');
*/ */
Resolver.solveVelocity = function(pairs, delta) { Resolver.solveVelocity = function(pairs, delta) {
var timeScale = delta / Common._timeUnit, var timeScale = delta / Common._timeUnit,
timeScale2 = timeScale * timeScale, timeScaleSquared = timeScale * timeScale,
timeScale3 = timeScale2 * timeScale, timeScaleCubed = timeScaleSquared * timeScale,
restingThresh = Resolver._restingThresh * timeScale2, restingThresh = -Resolver._restingThresh * timeScale,
frictionNormalMultiplier = Resolver._frictionNormalMultiplier, frictionNormalMultiplier = Resolver._frictionNormalMultiplier,
restingThreshTangent = Resolver._restingThreshTangent * timeScale2, restingThreshTangent = Resolver._restingThreshTangent * timeScale,
NumberMaxValue = Number.MAX_VALUE, frictionMaxStatic = Resolver._frictionMaxStatic * timeScale,
pairsLength = pairs.length, pairsLength = pairs.length,
tangentImpulse, tangentImpulse,
maxFriction, maxFriction,
@ -258,7 +256,7 @@ var Bounds = require('../geometry/Bounds');
contactsLength = contacts.length, contactsLength = contacts.length,
contactShare = 1 / contactsLength, contactShare = 1 / contactsLength,
inverseMassTotal = bodyA.inverseMass + bodyB.inverseMass, inverseMassTotal = bodyA.inverseMass + bodyB.inverseMass,
friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier * timeScale2; friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier * timeScale;
// update body velocities // update body velocities
bodyAVelocity.x = bodyA.position.x - bodyA.positionPrev.x; bodyAVelocity.x = bodyA.position.x - bodyA.positionPrev.x;
@ -291,14 +289,14 @@ var Bounds = require('../geometry/Bounds');
// coulomb friction // coulomb friction
var normalOverlap = pair.separation + normalVelocity; var normalOverlap = pair.separation + normalVelocity;
var normalForce = Math.min(normalOverlap, 1) * timeScale3; var normalForce = Math.min(normalOverlap, 1);
normalForce = normalOverlap < 0 ? 0 : normalForce; normalForce = normalOverlap < 0 ? 0 : normalForce;
var frictionLimit = normalForce * friction; var frictionLimit = normalForce * friction;
if (tangentVelocity > frictionLimit || -tangentVelocity > frictionLimit) { if (tangentVelocity < -frictionLimit || tangentVelocity > frictionLimit) {
maxFriction = (tangentVelocity > 0 ? tangentVelocity : -tangentVelocity) * timeScale; maxFriction = (tangentVelocity > 0 ? tangentVelocity : -tangentVelocity);
tangentImpulse = pair.friction * (tangentVelocity > 0 ? 1 : -1) * timeScale3; tangentImpulse = pair.friction * (tangentVelocity > 0 ? 1 : -1) * timeScaleCubed;
if (tangentImpulse < -maxFriction) { if (tangentImpulse < -maxFriction) {
tangentImpulse = -maxFriction; tangentImpulse = -maxFriction;
@ -307,7 +305,7 @@ var Bounds = require('../geometry/Bounds');
} }
} else { } else {
tangentImpulse = tangentVelocity; tangentImpulse = tangentVelocity;
maxFriction = NumberMaxValue; maxFriction = frictionMaxStatic;
} }
// account for mass, inertia and contact offset // account for mass, inertia and contact offset
@ -320,7 +318,7 @@ var Bounds = require('../geometry/Bounds');
tangentImpulse *= share; tangentImpulse *= share;
// handle high velocity and resting collisions separately // handle high velocity and resting collisions separately
if (normalVelocity < 0 && normalVelocity * normalVelocity > restingThresh) { if (normalVelocity < restingThresh) {
// high normal velocity so clear cached contact normal impulse // high normal velocity so clear cached contact normal impulse
contact.normalImpulse = 0; contact.normalImpulse = 0;
} else { } else {
@ -328,12 +326,12 @@ var Bounds = require('../geometry/Bounds');
// impulse constraint tends to 0 // impulse constraint tends to 0
var contactNormalImpulse = contact.normalImpulse; var contactNormalImpulse = contact.normalImpulse;
contact.normalImpulse += normalImpulse; contact.normalImpulse += normalImpulse;
contact.normalImpulse = Math.min(contact.normalImpulse, 0); if (contact.normalImpulse > 0) contact.normalImpulse = 0;
normalImpulse = contact.normalImpulse - contactNormalImpulse; normalImpulse = contact.normalImpulse - contactNormalImpulse;
} }
// handle high velocity and resting collisions separately // handle high velocity and resting collisions separately
if (tangentVelocity * tangentVelocity > restingThreshTangent) { if (tangentVelocity < -restingThreshTangent || tangentVelocity > restingThreshTangent) {
// high tangent velocity so clear cached contact tangent impulse // high tangent velocity so clear cached contact tangent impulse
contact.tangentImpulse = 0; contact.tangentImpulse = 0;
} else { } else {

View file

@ -154,7 +154,7 @@ var Body = require('../body/Body');
// iteratively resolve position between collisions // iteratively resolve position between collisions
Resolver.preSolvePosition(pairs.list); Resolver.preSolvePosition(pairs.list);
for (i = 0; i < engine.positionIterations; i++) { for (i = 0; i < engine.positionIterations; i++) {
Resolver.solvePosition(pairs.list, delta); Resolver.solvePosition(pairs.list, engine.positionIterations);
} }
Resolver.postSolvePosition(allBodies); Resolver.postSolvePosition(allBodies);

View file

@ -25,8 +25,8 @@ var Common = require('./Common');
*/ */
Sleeping.update = function(bodies, delta) { Sleeping.update = function(bodies, delta) {
var timeScale = delta / Common._timeUnit, var timeScale = delta / Common._timeUnit,
timeScale2 = timeScale * timeScale, timeScaleSquared = timeScale * timeScale,
motionSleepThreshold = Sleeping._motionSleepThreshold * timeScale2; motionSleepThreshold = Sleeping._motionSleepThreshold * timeScaleSquared;
// update bodies sleeping status // update bodies sleeping status
for (var i = 0; i < bodies.length; i++) { for (var i = 0; i < bodies.length; i++) {
@ -64,7 +64,8 @@ var Common = require('./Common');
* @param {number} delta * @param {number} delta
*/ */
Sleeping.afterCollisions = function(pairs, delta) { Sleeping.afterCollisions = function(pairs, delta) {
var timeScale = delta / Common._timeUnit; var timeScale = delta / Common._timeUnit,
motionSleepThreshold = Sleeping._motionSleepThreshold * timeScale * timeScale;
// wake up bodies involved in collisions // wake up bodies involved in collisions
for (var i = 0; i < pairs.length; i++) { for (var i = 0; i < pairs.length; i++) {
@ -86,7 +87,7 @@ var Common = require('./Common');
var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB, var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB,
movingBody = sleepingBody === bodyA ? bodyB : bodyA; movingBody = sleepingBody === bodyA ? bodyB : bodyA;
if (!sleepingBody.isStatic && movingBody.motion > Sleeping._motionWakeThreshold * timeScale * timeScale) { if (!sleepingBody.isStatic && movingBody.motion > motionSleepThreshold) {
Sleeping.set(sleepingBody, false); Sleeping.set(sleepingBody, false);
} }
} }