@@ -228,14 +228,17 @@ var Bounds = require('../geometry/Bounds');
228228 */
229229 Resolver . solveVelocity = function ( pairs , timeScale ) {
230230 var timeScaleSquared = timeScale * timeScale ,
231- impulse = Vector . _temp [ 0 ] ,
232- tempA = Vector . _temp [ 1 ] ,
233- tempB = Vector . _temp [ 2 ] ,
234- tempC = Vector . _temp [ 3 ] ,
235- tempD = Vector . _temp [ 4 ] ,
236- tempE = Vector . _temp [ 5 ] ;
237-
238- for ( var i = 0 ; i < pairs . length ; i ++ ) {
231+ restingThresh = Resolver . _restingThresh * timeScaleSquared ,
232+ frictionNormalMultiplier = Resolver . _frictionNormalMultiplier ,
233+ restingThreshTangent = Resolver . _restingThreshTangent * timeScaleSquared ,
234+ NumberMaxValue = Number . MAX_VALUE ,
235+ pairsLength = pairs . length ,
236+ tangentImpulse ,
237+ maxFriction ,
238+ i ,
239+ j ;
240+
241+ for ( i = 0 ; i < pairsLength ; i ++ ) {
239242 var pair = pairs [ i ] ;
240243
241244 if ( ! pair . isActive || pair . isSensor )
@@ -244,97 +247,119 @@ var Bounds = require('../geometry/Bounds');
244247 var collision = pair . collision ,
245248 bodyA = collision . parentA ,
246249 bodyB = collision . parentB ,
247- normal = collision . normal ,
248- tangent = collision . tangent ,
250+ bodyAVelocity = bodyA . velocity ,
251+ bodyBVelocity = bodyB . velocity ,
252+ normalX = collision . normal . x ,
253+ normalY = collision . normal . y ,
254+ tangentX = collision . tangent . x ,
255+ tangentY = collision . tangent . y ,
249256 contacts = pair . activeContacts ,
250- contactShare = 1 / contacts . length ;
257+ contactsLength = contacts . length ,
258+ contactShare = 1 / contactsLength ,
259+ inverseMassTotal = bodyA . inverseMass + bodyB . inverseMass ,
260+ friction = pair . friction * pair . frictionStatic * frictionNormalMultiplier * timeScaleSquared ;
251261
252262 // update body velocities
253- bodyA . velocity . x = bodyA . position . x - bodyA . positionPrev . x ;
254- bodyA . velocity . y = bodyA . position . y - bodyA . positionPrev . y ;
255- bodyB . velocity . x = bodyB . position . x - bodyB . positionPrev . x ;
256- bodyB . velocity . y = bodyB . position . y - bodyB . positionPrev . y ;
263+ bodyAVelocity . x = bodyA . position . x - bodyA . positionPrev . x ;
264+ bodyAVelocity . y = bodyA . position . y - bodyA . positionPrev . y ;
265+ bodyBVelocity . x = bodyB . position . x - bodyB . positionPrev . x ;
266+ bodyBVelocity . y = bodyB . position . y - bodyB . positionPrev . y ;
257267 bodyA . angularVelocity = bodyA . angle - bodyA . anglePrev ;
258268 bodyB . angularVelocity = bodyB . angle - bodyB . anglePrev ;
259269
260270 // resolve each contact
261- for ( var j = 0 ; j < contacts . length ; j ++ ) {
271+ for ( j = 0 ; j < contactsLength ; j ++ ) {
262272 var contact = contacts [ j ] ,
263- contactVertex = contact . vertex ,
264- offsetA = Vector . sub ( contactVertex , bodyA . position , tempA ) ,
265- offsetB = Vector . sub ( contactVertex , bodyB . position , tempB ) ,
266- velocityPointA = Vector . add ( bodyA . velocity , Vector . mult ( Vector . perp ( offsetA ) , bodyA . angularVelocity ) , tempC ) ,
267- velocityPointB = Vector . add ( bodyB . velocity , Vector . mult ( Vector . perp ( offsetB ) , bodyB . angularVelocity ) , tempD ) ,
268- relativeVelocity = Vector . sub ( velocityPointA , velocityPointB , tempE ) ,
269- normalVelocity = Vector . dot ( normal , relativeVelocity ) ;
270-
271- var tangentVelocity = Vector . dot ( tangent , relativeVelocity ) ,
272- tangentSpeed = Math . abs ( tangentVelocity ) ,
273- tangentVelocityDirection = Common . sign ( tangentVelocity ) ;
273+ contactVertex = contact . vertex ;
274+
275+ var offsetAX = contactVertex . x - bodyA . position . x ,
276+ offsetAY = contactVertex . y - bodyA . position . y ,
277+ offsetBX = contactVertex . x - bodyB . position . x ,
278+ offsetBY = contactVertex . y - bodyB . position . y ;
274279
275- // raw impulses
276- var normalImpulse = ( 1 + pair . restitution ) * normalVelocity ,
277- normalForce = Common . clamp ( pair . separation + normalVelocity , 0 , 1 ) * Resolver . _frictionNormalMultiplier ;
280+ var velocityPointAX = bodyAVelocity . x - offsetAY * bodyA . angularVelocity ,
281+ velocityPointAY = bodyAVelocity . y + offsetAX * bodyA . angularVelocity ,
282+ velocityPointBX = bodyBVelocity . x - offsetBY * bodyB . angularVelocity ,
283+ velocityPointBY = bodyBVelocity . y + offsetBX * bodyB . angularVelocity ;
284+
285+ var relativeVelocityX = velocityPointAX - velocityPointBX ,
286+ relativeVelocityY = velocityPointAY - velocityPointBY ;
287+
288+ var normalVelocity = normalX * relativeVelocityX + normalY * relativeVelocityY ,
289+ tangentVelocity = tangentX * relativeVelocityX + tangentY * relativeVelocityY ;
278290
279291 // coulomb friction
280- var tangentImpulse = tangentVelocity ,
281- maxFriction = Infinity ;
282-
283- if ( tangentSpeed > pair . friction * pair . frictionStatic * normalForce * timeScaleSquared ) {
284- maxFriction = tangentSpeed ;
285- tangentImpulse = Common . clamp (
286- pair . friction * tangentVelocityDirection * timeScaleSquared ,
287- - maxFriction , maxFriction
288- ) ;
292+ var normalOverlap = pair . separation + normalVelocity ;
293+ var normalForce = normalOverlap > 1 ? 1 : normalOverlap ;
294+ normalForce = normalOverlap < 0 ? 0 : normalForce ;
295+
296+ var frictionLimit = normalForce * friction ;
297+
298+ if ( tangentVelocity > frictionLimit || - tangentVelocity > frictionLimit ) {
299+ maxFriction = tangentVelocity > 0 ? tangentVelocity : - tangentVelocity ;
300+ tangentImpulse = pair . friction * ( tangentVelocity > 0 ? 1 : - 1 ) * timeScaleSquared ;
301+
302+ if ( tangentImpulse < - maxFriction ) {
303+ tangentImpulse = - maxFriction ;
304+ } else if ( tangentImpulse > maxFriction ) {
305+ tangentImpulse = maxFriction ;
306+ }
307+ } else {
308+ tangentImpulse = tangentVelocity ;
309+ maxFriction = NumberMaxValue ;
289310 }
290311
291- // modify impulses accounting for mass, inertia and offset
292- var oAcN = Vector . cross ( offsetA , normal ) ,
293- oBcN = Vector . cross ( offsetB , normal ) ,
294- share = contactShare / ( bodyA . inverseMass + bodyB . inverseMass + bodyA . inverseInertia * oAcN * oAcN + bodyB . inverseInertia * oBcN * oBcN ) ;
312+ // account for mass, inertia and contact offset
313+ var oAcN = offsetAX * normalY - offsetAY * normalX ,
314+ oBcN = offsetBX * normalY - offsetBY * normalX ,
315+ share = contactShare / ( inverseMassTotal + bodyA . inverseInertia * oAcN * oAcN + bodyB . inverseInertia * oBcN * oBcN ) ;
295316
296- normalImpulse *= share ;
317+ // raw impulses
318+ var normalImpulse = ( 1 + pair . restitution ) * normalVelocity * share ;
297319 tangentImpulse *= share ;
298320
299321 // handle high velocity and resting collisions separately
300- if ( normalVelocity < 0 && normalVelocity * normalVelocity > Resolver . _restingThresh * timeScaleSquared ) {
322+ if ( normalVelocity * normalVelocity > restingThresh && normalVelocity < 0 ) {
301323 // high normal velocity so clear cached contact normal impulse
302324 contact . normalImpulse = 0 ;
303325 } else {
304326 // solve resting collision constraints using Erin Catto's method (GDC08)
305327 // impulse constraint tends to 0
306328 var contactNormalImpulse = contact . normalImpulse ;
307- contact . normalImpulse = Math . min ( contact . normalImpulse + normalImpulse , 0 ) ;
329+ contact . normalImpulse += normalImpulse ;
330+ contact . normalImpulse = contact . normalImpulse < 0 ? contact . normalImpulse : 0 ;
308331 normalImpulse = contact . normalImpulse - contactNormalImpulse ;
309332 }
310333
311334 // handle high velocity and resting collisions separately
312- if ( tangentVelocity * tangentVelocity > Resolver . _restingThreshTangent * timeScaleSquared ) {
335+ if ( tangentVelocity * tangentVelocity > restingThreshTangent ) {
313336 // high tangent velocity so clear cached contact tangent impulse
314337 contact . tangentImpulse = 0 ;
315338 } else {
316339 // solve resting collision constraints using Erin Catto's method (GDC08)
317340 // tangent impulse tends to -tangentSpeed or +tangentSpeed
318341 var contactTangentImpulse = contact . tangentImpulse ;
319- contact . tangentImpulse = Common . clamp ( contact . tangentImpulse + tangentImpulse , - maxFriction , maxFriction ) ;
342+ contact . tangentImpulse += tangentImpulse ;
343+ if ( contact . tangentImpulse < - maxFriction ) contact . tangentImpulse = - maxFriction ;
344+ if ( contact . tangentImpulse > maxFriction ) contact . tangentImpulse = maxFriction ;
320345 tangentImpulse = contact . tangentImpulse - contactTangentImpulse ;
321346 }
322347
323348 // total impulse from contact
324- impulse . x = ( normal . x * normalImpulse ) + ( tangent . x * tangentImpulse ) ;
325- impulse . y = ( normal . y * normalImpulse ) + ( tangent . y * tangentImpulse ) ;
349+ var impulseX = normalX * normalImpulse + tangentX * tangentImpulse ,
350+ impulseY = normalY * normalImpulse + tangentY * tangentImpulse ;
326351
327352 // apply impulse from contact
328353 if ( ! ( bodyA . isStatic || bodyA . isSleeping ) ) {
329- bodyA . positionPrev . x += impulse . x * bodyA . inverseMass ;
330- bodyA . positionPrev . y += impulse . y * bodyA . inverseMass ;
331- bodyA . anglePrev += Vector . cross ( offsetA , impulse ) * bodyA . inverseInertia ;
354+ bodyA . positionPrev . x += impulseX * bodyA . inverseMass ;
355+ bodyA . positionPrev . y += impulseY * bodyA . inverseMass ;
356+ bodyA . anglePrev += ( offsetAX * impulseY - offsetAY * impulseX ) * bodyA . inverseInertia ;
332357 }
333358
334359 if ( ! ( bodyB . isStatic || bodyB . isSleeping ) ) {
335- bodyB . positionPrev . x -= impulse . x * bodyB . inverseMass ;
336- bodyB . positionPrev . y -= impulse . y * bodyB . inverseMass ;
337- bodyB . anglePrev -= Vector . cross ( offsetB , impulse ) * bodyB . inverseInertia ;
360+ bodyB . positionPrev . x -= impulseX * bodyB . inverseMass ;
361+ bodyB . positionPrev . y -= impulseY * bodyB . inverseMass ;
362+ bodyB . anglePrev -= ( offsetBX * impulseY - offsetBY * impulseX ) * bodyB . inverseInertia ;
338363 }
339364 }
340365 }
0 commit comments