From 87af8a1740f26913d5491dafaa2a420805bd0c75 Mon Sep 17 00:00:00 2001 From: liabru Date: Sat, 1 Jan 2022 21:20:52 +0000 Subject: [PATCH] improved delta consistency --- src/collision/Resolver.js | 44 +++++++++++++++++++-------------------- src/core/Engine.js | 2 +- src/core/Sleeping.js | 9 ++++---- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/collision/Resolver.js b/src/collision/Resolver.js index 33775e6a..518604f5 100644 --- a/src/collision/Resolver.js +++ b/src/collision/Resolver.js @@ -9,17 +9,17 @@ var Resolver = {}; module.exports = Resolver; var Vertices = require('../geometry/Vertices'); -var Vector = require('../geometry/Vector'); var Common = require('../core/Common'); var Bounds = require('../geometry/Bounds'); (function() { - Resolver._restingThresh = 4; - Resolver._restingThreshTangent = 6; + Resolver._restingThresh = 2; + Resolver._restingThreshTangent = Math.sqrt(6); Resolver._positionDampen = 0.9; Resolver._positionWarming = 0.8; Resolver._frictionNormalMultiplier = 5; + Resolver._frictionMaxStatic = Number.MAX_VALUE; /** * Prepare pairs for position solving. @@ -49,9 +49,9 @@ var Bounds = require('../geometry/Bounds'); * Find a solution for pair positions. * @method solvePosition * @param {pair[]} pairs - * @param {number} delta + * @param {number} positionIterations */ - Resolver.solvePosition = function(pairs, delta) { + Resolver.solvePosition = function(pairs, positionIterations) { var i, pair, collision, @@ -60,9 +60,7 @@ var Bounds = require('../geometry/Bounds'); normal, contactShare, positionImpulse, - timeScale = delta / Common._timeUnit, - damping = Common.clamp(Resolver._positionDampen * timeScale, 0, 1), - positionDampen = Resolver._positionDampen, + positionDampen = Resolver._positionDampen * Common.clamp(20 / positionIterations, 0, 1), pairsLength = pairs.length; // find impulses required to resolve penetration @@ -93,7 +91,7 @@ var Bounds = require('../geometry/Bounds'); bodyA = collision.parentA; bodyB = collision.parentB; normal = collision.normal; - positionImpulse = (pair.separation - pair.slop) * damping; + positionImpulse = pair.separation - pair.slop; if (bodyA.isStatic || bodyB.isStatic) positionImpulse *= 2; @@ -227,12 +225,12 @@ var Bounds = require('../geometry/Bounds'); */ Resolver.solveVelocity = function(pairs, delta) { var timeScale = delta / Common._timeUnit, - timeScale2 = timeScale * timeScale, - timeScale3 = timeScale2 * timeScale, - restingThresh = Resolver._restingThresh * timeScale2, + timeScaleSquared = timeScale * timeScale, + timeScaleCubed = timeScaleSquared * timeScale, + restingThresh = -Resolver._restingThresh * timeScale, frictionNormalMultiplier = Resolver._frictionNormalMultiplier, - restingThreshTangent = Resolver._restingThreshTangent * timeScale2, - NumberMaxValue = Number.MAX_VALUE, + restingThreshTangent = Resolver._restingThreshTangent * timeScale, + frictionMaxStatic = Resolver._frictionMaxStatic * timeScale, pairsLength = pairs.length, tangentImpulse, maxFriction, @@ -258,7 +256,7 @@ var Bounds = require('../geometry/Bounds'); contactsLength = contacts.length, contactShare = 1 / contactsLength, inverseMassTotal = bodyA.inverseMass + bodyB.inverseMass, - friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier * timeScale2; + friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier * timeScale; // update body velocities bodyAVelocity.x = bodyA.position.x - bodyA.positionPrev.x; @@ -291,14 +289,14 @@ var Bounds = require('../geometry/Bounds'); // coulomb friction var normalOverlap = pair.separation + normalVelocity; - var normalForce = Math.min(normalOverlap, 1) * timeScale3; + var normalForce = Math.min(normalOverlap, 1); normalForce = normalOverlap < 0 ? 0 : normalForce; var frictionLimit = normalForce * friction; - if (tangentVelocity > frictionLimit || -tangentVelocity > frictionLimit) { - maxFriction = (tangentVelocity > 0 ? tangentVelocity : -tangentVelocity) * timeScale; - tangentImpulse = pair.friction * (tangentVelocity > 0 ? 1 : -1) * timeScale3; + if (tangentVelocity < -frictionLimit || tangentVelocity > frictionLimit) { + maxFriction = (tangentVelocity > 0 ? tangentVelocity : -tangentVelocity); + tangentImpulse = pair.friction * (tangentVelocity > 0 ? 1 : -1) * timeScaleCubed; if (tangentImpulse < -maxFriction) { tangentImpulse = -maxFriction; @@ -307,7 +305,7 @@ var Bounds = require('../geometry/Bounds'); } } else { tangentImpulse = tangentVelocity; - maxFriction = NumberMaxValue; + maxFriction = frictionMaxStatic; } // account for mass, inertia and contact offset @@ -320,7 +318,7 @@ var Bounds = require('../geometry/Bounds'); tangentImpulse *= share; // 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 contact.normalImpulse = 0; } else { @@ -328,12 +326,12 @@ var Bounds = require('../geometry/Bounds'); // impulse constraint tends to 0 var contactNormalImpulse = contact.normalImpulse; contact.normalImpulse += normalImpulse; - contact.normalImpulse = Math.min(contact.normalImpulse, 0); + if (contact.normalImpulse > 0) contact.normalImpulse = 0; normalImpulse = contact.normalImpulse - contactNormalImpulse; } // 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 contact.tangentImpulse = 0; } else { diff --git a/src/core/Engine.js b/src/core/Engine.js index 418a1eca..a3027322 100644 --- a/src/core/Engine.js +++ b/src/core/Engine.js @@ -154,7 +154,7 @@ var Body = require('../body/Body'); // iteratively resolve position between collisions Resolver.preSolvePosition(pairs.list); for (i = 0; i < engine.positionIterations; i++) { - Resolver.solvePosition(pairs.list, delta); + Resolver.solvePosition(pairs.list, engine.positionIterations); } Resolver.postSolvePosition(allBodies); diff --git a/src/core/Sleeping.js b/src/core/Sleeping.js index 9e0ca15d..ad22242f 100644 --- a/src/core/Sleeping.js +++ b/src/core/Sleeping.js @@ -25,8 +25,8 @@ var Common = require('./Common'); */ Sleeping.update = function(bodies, delta) { var timeScale = delta / Common._timeUnit, - timeScale2 = timeScale * timeScale, - motionSleepThreshold = Sleeping._motionSleepThreshold * timeScale2; + timeScaleSquared = timeScale * timeScale, + motionSleepThreshold = Sleeping._motionSleepThreshold * timeScaleSquared; // update bodies sleeping status for (var i = 0; i < bodies.length; i++) { @@ -64,7 +64,8 @@ var Common = require('./Common'); * @param {number} 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 for (var i = 0; i < pairs.length; i++) { @@ -86,7 +87,7 @@ var Common = require('./Common'); var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB, movingBody = sleepingBody === bodyA ? bodyB : bodyA; - if (!sleepingBody.isStatic && movingBody.motion > Sleeping._motionWakeThreshold * timeScale * timeScale) { + if (!sleepingBody.isStatic && movingBody.motion > motionSleepThreshold) { Sleeping.set(sleepingBody, false); } }