diff --git a/src/body/Body.js b/src/body/Body.js index 5564902e..576c8993 100644 --- a/src/body/Body.js +++ b/src/body/Body.js @@ -52,6 +52,7 @@ var Body = {}; density: 0.001, restitution: 0, friction: 0.1, + frictionStatic: 0.5, frictionAir: 0.01, collisionFilter: { category: 0x0001, diff --git a/src/collision/Pair.js b/src/collision/Pair.js index 30cbfc77..ec4dffdc 100644 --- a/src/collision/Pair.js +++ b/src/collision/Pair.js @@ -32,6 +32,7 @@ var Pair = {}; timeUpdated: timestamp, inverseMass: parentA.inverseMass + parentB.inverseMass, friction: Math.min(parentA.friction, parentB.friction), + frictionStatic: Math.max(parentA.frictionStatic, parentB.frictionStatic), restitution: Math.max(parentA.restitution, parentB.restitution), slop: Math.max(parentA.slop, parentB.slop) }; @@ -57,6 +58,7 @@ var Pair = {}; pair.collision = collision; pair.inverseMass = parentA.inverseMass + parentB.inverseMass; pair.friction = Math.min(parentA.friction, parentB.friction); + pair.frictionStatic = Math.max(parentA.frictionStatic, parentB.frictionStatic); pair.restitution = Math.max(parentA.restitution, parentB.restitution); pair.slop = Math.max(parentA.slop, parentB.slop); activeContacts.length = 0; diff --git a/src/collision/Resolver.js b/src/collision/Resolver.js index 2c2c3476..42864c31 100644 --- a/src/collision/Resolver.js +++ b/src/collision/Resolver.js @@ -11,6 +11,7 @@ var Resolver = {}; Resolver._restingThresh = 4; Resolver._positionDampen = 0.9; Resolver._positionWarming = 0.8; + Resolver._frictionNormalMultiplier = 5; /** * Description @@ -264,20 +265,25 @@ var Resolver = {}; // raw impulses var normalImpulse = (1 + pair.restitution) * normalVelocity, - normalForce = Common.clamp(pair.separation + normalVelocity, 0, 1); + normalForce = Common.clamp(pair.separation + normalVelocity, 0, 1) * Resolver._frictionNormalMultiplier; // coulomb friction - var tangentImpulse = tangentVelocity; - if (tangentSpeed > normalForce * pair.friction * timeScaleSquared) - tangentImpulse = normalForce * pair.friction * timeScaleSquared * tangentVelocityDirection; + var tangentImpulse = tangentVelocity, + maxFriction = Infinity; + + if (tangentSpeed > pair.friction * pair.frictionStatic * normalForce * timeScaleSquared) { + tangentImpulse = pair.friction * tangentVelocityDirection * timeScaleSquared; + maxFriction = tangentSpeed; + } // modify impulses accounting for mass, inertia and offset var oAcN = Vector.cross(offsetA, normal), oBcN = Vector.cross(offsetB, normal), - share = contactShare / (pair.inverseMass + bodyA.inverseInertia * oAcN * oAcN + bodyB.inverseInertia * oBcN * oBcN); + share = contactShare / (bodyA.inverseMass + bodyB.inverseMass + bodyA.inverseInertia * oAcN * oAcN + bodyB.inverseInertia * oBcN * oBcN); + normalImpulse *= share; - tangentImpulse *= share; - + tangentImpulse *= Math.min(share, 1); + // handle high velocity and resting collisions separately if (normalVelocity < 0 && normalVelocity * normalVelocity > Resolver._restingThresh * timeScaleSquared) { // high velocity so clear cached contact impulse @@ -293,7 +299,7 @@ var Resolver = {}; // tangent impulse, tends to -maxFriction or maxFriction var contactTangentImpulse = contact.tangentImpulse; - contact.tangentImpulse = Common.clamp(contact.tangentImpulse + tangentImpulse, -tangentSpeed, tangentSpeed); + contact.tangentImpulse = Common.clamp(contact.tangentImpulse + tangentImpulse, -maxFriction, maxFriction); tangentImpulse = contact.tangentImpulse - contactTangentImpulse; }