topical media & game development

talk show tell print

#javascript-physics-js-box2d-dynamics-joints-b2PrismaticJoint.js / js



  /*
  * Copyright (c) 2006-2007 Erin Catto 
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked, and must not be
* misrepresented the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

// Linear constraint (point-to-line)
// d = p2 - p1 = x2 + r2 - x1 - r1
// C = dot(ay1, d)
// Cdot = dot(d, cross(w1, ay1)) + dot(ay1, v2 + cross(w2, r2) - v1 - cross(w1, r1))
//      = -dot(ay1, v1) - dot(cross(d + r1, ay1), w1) + dot(ay1, v2) + dot(cross(r2, ay1), v2)
// J = [-ay1 -cross(d+r1,ay1) ay1 cross(r2,ay1)]
//
// Angular constraint
// C = a2 - a1 + a_initial
// Cdot = w2 - w1
// J = [0 0 -1 0 0 1]

// Motor/Limit linear constraint
// C = dot(ax1, d)
// Cdot = = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2)
// J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)]

var b2PrismaticJoint = Class.create();
Object.extend(b2PrismaticJoint.prototype, b2Joint.prototype);
Object.extend(b2PrismaticJoint.prototype, 
{
        GetAnchor1: function(){
                var b1 = this.m_body1;
                //return b2Math.AddVV(b1.m_position, b2Math.b2MulMV(b1.m_R, this.m_localAnchor1));
                var tVec = new b2Vec2();
                tVec.SetV(this.m_localAnchor1);
                tVec.MulM(b1.m_R);
                tVec.Add(b1.m_position);
                return tVec;
        },
        GetAnchor2: function(){
                var b2 = this.m_body2;
                //return b2Math.AddVV(b2.m_position, b2Math.b2MulMV(b2.m_R, this.m_localAnchor2));
                var tVec = new b2Vec2();
                tVec.SetV(this.m_localAnchor2);
                tVec.MulM(b2.m_R);
                tVec.Add(b2.m_position);
                return tVec;
        },
        GetJointTranslation: function(){
                var b1 = this.m_body1;
                var b2 = this.m_body2;

                var tMat;

                //var r1 = b2Math.b2MulMV(b1.m_R, this.m_localAnchor1);
                tMat = b1.m_R;
                var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
                var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
                //var r2 = b2Math.b2MulMV(b2.m_R, this.m_localAnchor2);
                tMat = b2.m_R;
                var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
                var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
                //var p1 = b2Math.AddVV(b1.m_position , r1);
                var p1X = b1.m_position.x + r1X;
                var p1Y = b1.m_position.y + r1Y;
                //var p2 = b2Math.AddVV(b2.m_position , r2);
                var p2X = b2.m_position.x + r2X;
                var p2Y = b2.m_position.y + r2Y;
                //var d = b2Math.SubtractVV(p2, p1);
                var dX = p2X - p1X;
                var dY = p2Y - p1Y;
                //var ax1 = b2Math.b2MulMV(b1.m_R, this.m_localXAxis1);
                tMat = b1.m_R;
                var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
                var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;

                //var translation = b2Math.b2Dot(ax1, d);
                var translation = ax1X*dX + ax1Y*dY;
                return translation;
        },
        GetJointSpeed: function(){
                var b1 = this.m_body1;
                var b2 = this.m_body2;

                var tMat;

                //var r1 = b2Math.b2MulMV(b1.m_R, this.m_localAnchor1);
                tMat = b1.m_R;
                var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
                var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
                //var r2 = b2Math.b2MulMV(b2.m_R, this.m_localAnchor2);
                tMat = b2.m_R;
                var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
                var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
                //var p1 = b2Math.AddVV(b1.m_position , r1);
                var p1X = b1.m_position.x + r1X;
                var p1Y = b1.m_position.y + r1Y;
                //var p2 = b2Math.AddVV(b2.m_position , r2);
                var p2X = b2.m_position.x + r2X;
                var p2Y = b2.m_position.y + r2Y;
                //var d = b2Math.SubtractVV(p2, p1);
                var dX = p2X - p1X;
                var dY = p2Y - p1Y;
                //var ax1 = b2Math.b2MulMV(b1.m_R, this.m_localXAxis1);
                tMat = b1.m_R;
                var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
                var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;

                var v1 = b1.m_linearVelocity;
                var v2 = b2.m_linearVelocity;
                var w1 = b1.m_angularVelocity;
                var w2 = b2.m_angularVelocity;

                //var speed = b2Math.b2Dot(d, b2Math.b2CrossFV(w1, ax1)) + b2Math.b2Dot(ax1, b2Math.SubtractVV( b2Math.SubtractVV( b2Math.AddVV( v2 , b2Math.b2CrossFV(w2, r2)) , v1) , b2Math.b2CrossFV(w1, r1)));
                //var b2D = (dX*(-w1 * ax1Y) + dY*(w1 * ax1X));
                //var b2D2 = (ax1X * ((( v2.x + (-w2 * r2Y)) - v1.x) - (-w1 * r1Y)) + ax1Y * ((( v2.y + (w2 * r2X)) - v1.y) - (w1 * r1X)));
                var speed = (dX*(-w1 * ax1Y) + dY*(w1 * ax1X)) + (ax1X * ((( v2.x + (-w2 * r2Y)) - v1.x) - (-w1 * r1Y)) + ax1Y * ((( v2.y + (w2 * r2X)) - v1.y) - (w1 * r1X)));

                return speed;
        },
        GetMotorForce: function(invTimeStep){
                return invTimeStep * this.m_motorImpulse;
        },

        SetMotorSpeed: function(speed)
        {
                this.m_motorSpeed = speed;
        },

        SetMotorForce: function(force)
        {
                this.m_maxMotorForce = force;
        },

        GetReactionForce: function(invTimeStep)
        {
                var tImp = invTimeStep * this.m_limitImpulse;
                var tMat;

                //var ax1 = b2Math.b2MulMV(this.m_body1.m_R, this.m_localXAxis1);
                tMat = this.m_body1.m_R;
                var ax1X = tImp * (tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y);
                var ax1Y = tImp * (tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y);
                //var ay1 = b2Math.b2MulMV(this.m_body1.m_R, this.m_localYAxis1);
                var ay1X = tImp * (tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y);
                var ay1Y = tImp * (tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y);

                //return (invTimeStep * this.m_limitImpulse) * ax1 + (invTimeStep * this.m_linearImpulse) * ay1;

                return new b2Vec2(ax1X+ay1X, ax1Y+ay1Y);
        },

        GetReactionTorque: function(invTimeStep)
        {
                return invTimeStep * this.m_angularImpulse;
        },

        //--------------- Internals Below ----------------
  *
  * This software is provided 'as-is', without any express or implied
  * warranty.  In no event will the authors be held liable for any damages
  * arising from the use of this software.
  * Permission is granted to anyone to use this software for any purpose,
  * including commercial applications, and to alter it and redistribute it
  * freely, subject to the following restrictions:
  * 1. The origin of this software must not be misrepresented; you must not
  * claim that you wrote the original software. If you use this software
  * in a product, an acknowledgment in the product documentation would be
  * appreciated but is not required.
  * 2. Altered source versions must be plainly marked, and must not be
  * misrepresented the original software.
  * 3. This notice may not be removed or altered from any source distribution.
  */
  
  // Linear constraint (point-to-line)
  // d = p2 - p1 = x2 + r2 - x1 - r1
  // C = dot(ay1, d)
  // Cdot = dot(d, cross(w1, ay1)) + dot(ay1, v2 + cross(w2, r2) - v1 - cross(w1, r1))
  //      = -dot(ay1, v1) - dot(cross(d + r1, ay1), w1) + dot(ay1, v2) + dot(cross(r2, ay1), v2)
  // J = [-ay1 -cross(d+r1,ay1) ay1 cross(r2,ay1)]
  //
  // Angular constraint
  // C = a2 - a1 + a_initial
  // Cdot = w2 - w1
  // J = [0 0 -1 0 0 1]
  
  // Motor/Limit linear constraint
  // C = dot(ax1, d)
  // Cdot = = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2)
  // J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)]
  
  var b2PrismaticJoint = Class.create();
  Object.extend(b2PrismaticJoint.prototype, b2Joint.prototype);
  Object.extend(b2PrismaticJoint.prototype, 
  {
          GetAnchor1: function(){
                  var b1 = this.m_body1;
                  //return b2Math.AddVV(b1.m_position, b2Math.b2MulMV(b1.m_R, this.m_localAnchor1));
                  var tVec = new b2Vec2();
                  tVec.SetV(this.m_localAnchor1);
                  tVec.MulM(b1.m_R);
                  tVec.Add(b1.m_position);
                  return tVec;
          },
          GetAnchor2: function(){
                  var b2 = this.m_body2;
                  //return b2Math.AddVV(b2.m_position, b2Math.b2MulMV(b2.m_R, this.m_localAnchor2));
                  var tVec = new b2Vec2();
                  tVec.SetV(this.m_localAnchor2);
                  tVec.MulM(b2.m_R);
                  tVec.Add(b2.m_position);
                  return tVec;
          },
          GetJointTranslation: function(){
                  var b1 = this.m_body1;
                  var b2 = this.m_body2;
  
                  var tMat;
  
                  //var r1 = b2Math.b2MulMV(b1.m_R, this.m_localAnchor1);
                  tMat = b1.m_R;
                  var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
                  var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
                  //var r2 = b2Math.b2MulMV(b2.m_R, this.m_localAnchor2);
                  tMat = b2.m_R;
                  var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
                  var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
                  //var p1 = b2Math.AddVV(b1.m_position , r1);
                  var p1X = b1.m_position.x + r1X;
                  var p1Y = b1.m_position.y + r1Y;
                  //var p2 = b2Math.AddVV(b2.m_position , r2);
                  var p2X = b2.m_position.x + r2X;
                  var p2Y = b2.m_position.y + r2Y;
                  //var d = b2Math.SubtractVV(p2, p1);
                  var dX = p2X - p1X;
                  var dY = p2Y - p1Y;
                  //var ax1 = b2Math.b2MulMV(b1.m_R, this.m_localXAxis1);
                  tMat = b1.m_R;
                  var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
                  var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
  
                  //var translation = b2Math.b2Dot(ax1, d);
                  var translation = ax1X*dX + ax1Y*dY;
                  return translation;
          },
          GetJointSpeed: function(){
                  var b1 = this.m_body1;
                  var b2 = this.m_body2;
  
                  var tMat;
  
                  //var r1 = b2Math.b2MulMV(b1.m_R, this.m_localAnchor1);
                  tMat = b1.m_R;
                  var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
                  var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
                  //var r2 = b2Math.b2MulMV(b2.m_R, this.m_localAnchor2);
                  tMat = b2.m_R;
                  var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
                  var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
                  //var p1 = b2Math.AddVV(b1.m_position , r1);
                  var p1X = b1.m_position.x + r1X;
                  var p1Y = b1.m_position.y + r1Y;
                  //var p2 = b2Math.AddVV(b2.m_position , r2);
                  var p2X = b2.m_position.x + r2X;
                  var p2Y = b2.m_position.y + r2Y;
                  //var d = b2Math.SubtractVV(p2, p1);
                  var dX = p2X - p1X;
                  var dY = p2Y - p1Y;
                  //var ax1 = b2Math.b2MulMV(b1.m_R, this.m_localXAxis1);
                  tMat = b1.m_R;
                  var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
                  var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
  
                  var v1 = b1.m_linearVelocity;
                  var v2 = b2.m_linearVelocity;
                  var w1 = b1.m_angularVelocity;
                  var w2 = b2.m_angularVelocity;
  
                  //var speed = b2Math.b2Dot(d, b2Math.b2CrossFV(w1, ax1)) + b2Math.b2Dot(ax1, b2Math.SubtractVV( b2Math.SubtractVV( b2Math.AddVV( v2 , b2Math.b2CrossFV(w2, r2)) , v1) , b2Math.b2CrossFV(w1, r1)));
                  //var b2D = (dX*(-w1 * ax1Y) + dY*(w1 * ax1X));
                  //var b2D2 = (ax1X * ((( v2.x + (-w2 * r2Y)) - v1.x) - (-w1 * r1Y)) + ax1Y * ((( v2.y + (w2 * r2X)) - v1.y) - (w1 * r1X)));
                  var speed = (dX*(-w1 * ax1Y) + dY*(w1 * ax1X)) + (ax1X * ((( v2.x + (-w2 * r2Y)) - v1.x) - (-w1 * r1Y)) + ax1Y * ((( v2.y + (w2 * r2X)) - v1.y) - (w1 * r1X)));
  
                  return speed;
          },
          GetMotorForce: function(invTimeStep){
                  return invTimeStep * this.m_motorImpulse;
          },
  
          SetMotorSpeed: function(speed)
          {
                  this.m_motorSpeed = speed;
          },
  
          SetMotorForce: function(force)
          {
                  this.m_maxMotorForce = force;
          },
  
          GetReactionForce: function(invTimeStep)
          {
                  var tImp = invTimeStep * this.m_limitImpulse;
                  var tMat;
  
                  //var ax1 = b2Math.b2MulMV(this.m_body1.m_R, this.m_localXAxis1);
                  tMat = this.m_body1.m_R;
                  var ax1X = tImp * (tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y);
                  var ax1Y = tImp * (tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y);
                  //var ay1 = b2Math.b2MulMV(this.m_body1.m_R, this.m_localYAxis1);
                  var ay1X = tImp * (tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y);
                  var ay1Y = tImp * (tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y);
  
                  //return (invTimeStep * this.m_limitImpulse) * ax1 + (invTimeStep * this.m_linearImpulse) * ay1;
  
                  return new b2Vec2(ax1X+ay1X, ax1Y+ay1Y);
          },
  
          GetReactionTorque: function(invTimeStep)
          {
                  return invTimeStep * this.m_angularImpulse;
          },
  
          //--------------- Internals Below -------------------
  
          initialize: function(def){
                  // The constructor for b2Joint
                  // initialize instance variables for references
                  this.m_node1 = new b2JointNode();
                  this.m_node2 = new b2JointNode();
                  //
                  this.m_type = def.type;
                  this.m_prev = null;
                  this.m_next = null;
                  this.m_body1 = def.body1;
                  this.m_body2 = def.body2;
                  this.m_collideConnected = def.collideConnected;
                  this.m_islandFlag = false;
                  this.m_userData = def.userData;
                  //
  
                  // initialize instance variables for references
                  this.m_localAnchor1 = new b2Vec2();
                  this.m_localAnchor2 = new b2Vec2();
                  this.m_localXAxis1 = new b2Vec2();
                  this.m_localYAxis1 = new b2Vec2();
                  this.m_linearJacobian = new b2Jacobian();
                  this.m_motorJacobian = new b2Jacobian();
                  //
  
                  //super(def);
  
                  var tMat;
                  var tX;
                  var tY;
  
                  //this.m_localAnchor1 = b2Math.b2MulTMV(this.m_body1.m_R, b2Math.SubtractVV(def.anchorPoint , this.m_body1.m_position));
                  tMat = this.m_body1.m_R;
                  tX = (def.anchorPoint.x - this.m_body1.m_position.x);
                  tY = (def.anchorPoint.y - this.m_body1.m_position.y);
                  this.m_localAnchor1.Set((tX*tMat.col1.x + tY*tMat.col1.y), (tX*tMat.col2.x + tY*tMat.col2.y));
  
                  //this.m_localAnchor2 = b2Math.b2MulTMV(this.m_body2.m_R, b2Math.SubtractVV(def.anchorPoint , this.m_body2.m_position));
                  tMat = this.m_body2.m_R;
                  tX = (def.anchorPoint.x - this.m_body2.m_position.x);
                  tY = (def.anchorPoint.y - this.m_body2.m_position.y);
                  this.m_localAnchor2.Set((tX*tMat.col1.x + tY*tMat.col1.y), (tX*tMat.col2.x + tY*tMat.col2.y));
  
                  //this.m_localXAxis1 = b2Math.b2MulTMV(this.m_body1.m_R, def.axis);
                  tMat = this.m_body1.m_R;
                  tX = def.axis.x;
                  tY = def.axis.y;
                  this.m_localXAxis1.Set((tX*tMat.col1.x + tY*tMat.col1.y), (tX*tMat.col2.x + tY*tMat.col2.y));
  
                  //this.m_localYAxis1 = b2Math.b2CrossFV(1.0, this.m_localXAxis1);
                  this.m_localYAxis1.x = -this.m_localXAxis1.y;
                  this.m_localYAxis1.y = this.m_localXAxis1.x;
  
                  this.m_initialAngle = this.m_body2.m_rotation - this.m_body1.m_rotation;
  
                  this.m_linearJacobian.SetZero();
                  this.m_linearMass = 0.0;
                  this.m_linearImpulse = 0.0;
  
                  this.m_angularMass = 0.0;
                  this.m_angularImpulse = 0.0;
  
                  this.m_motorJacobian.SetZero();
                  this.m_motorMass = 0.0;
                  this.m_motorImpulse = 0.0;
                  this.m_limitImpulse = 0.0;
                  this.m_limitPositionImpulse = 0.0;
  
                  this.m_lowerTranslation = def.lowerTranslation;
                  this.m_upperTranslation = def.upperTranslation;
                  this.m_maxMotorForce = def.motorForce;
                  this.m_motorSpeed = def.motorSpeed;
                  this.m_enableLimit = def.enableLimit;
                  this.m_enableMotor = def.enableMotor;
          },
  
          PrepareVelocitySolver: function(){
                  var b1 = this.m_body1;
                  var b2 = this.m_body2;
  
                  var tMat;
  
                  // Compute the effective masses.
                  //b2Vec2 r1 = b2Mul(b1->m_R, this.m_localAnchor1);
                  tMat = b1.m_R;
                  var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
                  var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
                  //b2Vec2 r2 = b2Mul(b2->m_R, this.m_localAnchor2);
                  tMat = b2.m_R;
                  var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
                  var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
  
                  //float32 invMass1 = b1->m_invMass, invMass2 = b2->m_invMass;
                  var invMass1 = b1.m_invMass;
                  var invMass2 = b2.m_invMass;
                  //float32 invI1 = b1->m_invI, invI2 = b2->m_invI;
                  var invI1 = b1.m_invI;
                  var invI2 = b2.m_invI;
  
                  // Compute point to line constraint effective mass.
                  // J = [-ay1 -cross(d+r1,ay1) ay1 cross(r2,ay1)]
                  //b2Vec2 ay1 = b2Mul(b1->m_R, this.m_localYAxis1);
                  tMat = b1.m_R;
                  var ay1X = tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y;
                  var ay1Y = tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y;
                  //b2Vec2 e = b2->m_position + r2 - b1->m_position;
                  var eX = b2.m_position.x + r2X - b1.m_position.x;
                  var eY = b2.m_position.y + r2Y - b1.m_position.y;
  
                  //this.m_linearJacobian.Set(-ay1, -b2Math.b2Cross(e, ay1), ay1, b2Math.b2Cross(r2, ay1));
                  this.m_linearJacobian.linear1.x = -ay1X;
                  this.m_linearJacobian.linear1.y = -ay1Y;
                  this.m_linearJacobian.linear2.x = ay1X;
                  this.m_linearJacobian.linear2.y = ay1Y;
                  this.m_linearJacobian.angular1 = -(eX * ay1Y - eY * ay1X);
                  this.m_linearJacobian.angular2 = r2X * ay1Y - r2Y * ay1X;
  
                  this.m_linearMass =        invMass1 + invI1 * this.m_linearJacobian.angular1 * this.m_linearJacobian.angular1 +
                                                  invMass2 + invI2 * this.m_linearJacobian.angular2 * this.m_linearJacobian.angular2;
                  //b2Settings.b2Assert(this.m_linearMass > Number.MIN_VALUE);
                  this.m_linearMass = 1.0 / this.m_linearMass;
  
                  // Compute angular constraint effective mass.
                  this.m_angularMass = 1.0 / (invI1 + invI2);
  
                  // Compute motor and limit terms.
                  if (this.m_enableLimit || this.m_enableMotor)
                  {
                          // The motor and limit share a Jacobian and effective mass.
                          //b2Vec2 ax1 = b2Mul(b1->m_R, this.m_localXAxis1);
                          tMat = b1.m_R;
                          var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
                          var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
                          //this.m_motorJacobian.Set(-ax1, -b2Cross(e, ax1), ax1, b2Cross(r2, ax1));
                          this.m_motorJacobian.linear1.x = -ax1X; this.m_motorJacobian.linear1.y = -ax1Y;
                          this.m_motorJacobian.linear2.x = ax1X; this.m_motorJacobian.linear2.y = ax1Y;
                          this.m_motorJacobian.angular1 = -(eX * ax1Y - eY * ax1X);
                          this.m_motorJacobian.angular2 = r2X * ax1Y - r2Y * ax1X;
  
                          this.m_motorMass =        invMass1 + invI1 * this.m_motorJacobian.angular1 * this.m_motorJacobian.angular1 +
                                                          invMass2 + invI2 * this.m_motorJacobian.angular2 * this.m_motorJacobian.angular2;
                          //b2Settings.b2Assert(this.m_motorMass > Number.MIN_VALUE);
                          this.m_motorMass = 1.0 / this.m_motorMass;
  
                          if (this.m_enableLimit)
                          {
                                  //b2Vec2 d = e - r1;
                                  var dX = eX - r1X;
                                  var dY = eY - r1Y;
                                  //float32 jointTranslation = b2Dot(ax1, d);
                                  var jointTranslation = ax1X * dX + ax1Y * dY;
                                  if (b2Math.b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2.0 * b2Settings.b2_linearSlop)
                                  {
                                          this.m_limitState = b2Joint.e_equalLimits;
                                  }
                                  else if (jointTranslation <= this.m_lowerTranslation)
                                  {
                                          if (this.m_limitState != b2Joint.e_atLowerLimit)
                                          {
                                                  this.m_limitImpulse = 0.0;
                                          }
                                          this.m_limitState = b2Joint.e_atLowerLimit;
                                  }
                                  else if (jointTranslation >= this.m_upperTranslation)
                                  {
                                          if (this.m_limitState != b2Joint.e_atUpperLimit)
                                          {
                                                  this.m_limitImpulse = 0.0;
                                          }
                                          this.m_limitState = b2Joint.e_atUpperLimit;
                                  }
                                  else
                                  {
                                          this.m_limitState = b2Joint.e_inactiveLimit;
                                          this.m_limitImpulse = 0.0;
                                  }
                          }
                  }
  
                  if (this.m_enableMotor == false)
                  {
                          this.m_motorImpulse = 0.0;
                  }
  
                  if (this.m_enableLimit == false)
                  {
                          this.m_limitImpulse = 0.0;
                  }
  
                  if (b2World.s_enableWarmStarting)
                  {
                          //b2Vec2 P1 = this.m_linearImpulse * this.m_linearJacobian.linear1 + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear1;
                          var P1X = this.m_linearImpulse * this.m_linearJacobian.linear1.x + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear1.x;
                          var P1Y = this.m_linearImpulse * this.m_linearJacobian.linear1.y + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear1.y;
                          //b2Vec2 P2 = this.m_linearImpulse * this.m_linearJacobian.linear2 + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear2;
                          var P2X = this.m_linearImpulse * this.m_linearJacobian.linear2.x + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear2.x;
                          var P2Y = this.m_linearImpulse * this.m_linearJacobian.linear2.y + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.linear2.y;
                          //float32 L1 = this.m_linearImpulse * this.m_linearJacobian.angular1 - this.m_angularImpulse + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.angular1;
                          var L1 = this.m_linearImpulse * this.m_linearJacobian.angular1 - this.m_angularImpulse + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.angular1;
                          //float32 L2 = this.m_linearImpulse * this.m_linearJacobian.angular2 + this.m_angularImpulse + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.angular2;
                          var L2 = this.m_linearImpulse * this.m_linearJacobian.angular2 + this.m_angularImpulse + (this.m_motorImpulse + this.m_limitImpulse) * this.m_motorJacobian.angular2;
  
                          //b1->m_linearVelocity += invMass1 * P1;
                          b1.m_linearVelocity.x += invMass1 * P1X;
                          b1.m_linearVelocity.y += invMass1 * P1Y;
                          //b1->m_angularVelocity += invI1 * L1;
                          b1.m_angularVelocity += invI1 * L1;
  
                          //b2->m_linearVelocity += invMass2 * P2;
                          b2.m_linearVelocity.x += invMass2 * P2X;
                          b2.m_linearVelocity.y += invMass2 * P2Y;
                          //b2->m_angularVelocity += invI2 * L2;
                          b2.m_angularVelocity += invI2 * L2;
                  }
                  else
                  {
                          this.m_linearImpulse = 0.0;
                          this.m_angularImpulse = 0.0;
                          this.m_limitImpulse = 0.0;
                          this.m_motorImpulse = 0.0;
                  }
  
                  this.m_limitPositionImpulse = 0.0;
  
          },
  
          SolveVelocityConstraints: function(step){
                  var b1 = this.m_body1;
                  var b2 = this.m_body2;
  
                  var invMass1 = b1.m_invMass;
                  var invMass2 = b2.m_invMass;
                  var invI1 = b1.m_invI;
                  var invI2 = b2.m_invI;
  
                  var oldLimitImpulse;
  
                  // Solve linear constraint.
                  var linearCdot = this.m_linearJacobian.Compute(b1.m_linearVelocity, b1.m_angularVelocity, b2.m_linearVelocity, b2.m_angularVelocity);
                  var linearImpulse = -this.m_linearMass * linearCdot;
                  this.m_linearImpulse += linearImpulse;
  
                  //b1->m_linearVelocity += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1;
                  b1.m_linearVelocity.x += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.x;
                  b1.m_linearVelocity.y += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.y;
                  //b1->m_angularVelocity += invI1 * linearImpulse * this.m_linearJacobian.angular1;
                  b1.m_angularVelocity += invI1 * linearImpulse * this.m_linearJacobian.angular1;
  
                  //b2->m_linearVelocity += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2;
                  b2.m_linearVelocity.x += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.x;
                  b2.m_linearVelocity.y += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.y;
                  //b2.m_angularVelocity += invI2 * linearImpulse * this.m_linearJacobian.angular2;
                  b2.m_angularVelocity += invI2 * linearImpulse * this.m_linearJacobian.angular2;
  
                  // Solve angular constraint.
                  var angularCdot = b2.m_angularVelocity - b1.m_angularVelocity;
                  var angularImpulse = -this.m_angularMass * angularCdot;
                  this.m_angularImpulse += angularImpulse;
  
                  b1.m_angularVelocity -= invI1 * angularImpulse;
                  b2.m_angularVelocity += invI2 * angularImpulse;
  
                  // Solve linear motor constraint.
                  if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits)
                  {
                          var motorCdot = this.m_motorJacobian.Compute(b1.m_linearVelocity, b1.m_angularVelocity, b2.m_linearVelocity, b2.m_angularVelocity) - this.m_motorSpeed;
                          var motorImpulse = -this.m_motorMass * motorCdot;
                          var oldMotorImpulse = this.m_motorImpulse;
                          this.m_motorImpulse = b2Math.b2Clamp(this.m_motorImpulse + motorImpulse, -step.dt * this.m_maxMotorForce, step.dt * this.m_maxMotorForce);
                          motorImpulse = this.m_motorImpulse - oldMotorImpulse;
  
                          //b1.m_linearVelocity += (invMass1 * motorImpulse) * this.m_motorJacobian.linear1;
                          b1.m_linearVelocity.x += (invMass1 * motorImpulse) * this.m_motorJacobian.linear1.x;
                          b1.m_linearVelocity.y += (invMass1 * motorImpulse) * this.m_motorJacobian.linear1.y;
                          //b1.m_angularVelocity += invI1 * motorImpulse * this.m_motorJacobian.angular1;
                          b1.m_angularVelocity += invI1 * motorImpulse * this.m_motorJacobian.angular1;
  
                          //b2->m_linearVelocity += (invMass2 * motorImpulse) * this.m_motorJacobian.linear2;
                          b2.m_linearVelocity.x += (invMass2 * motorImpulse) * this.m_motorJacobian.linear2.x;
                          b2.m_linearVelocity.y += (invMass2 * motorImpulse) * this.m_motorJacobian.linear2.y;
                          //b2->m_angularVelocity += invI2 * motorImpulse * this.m_motorJacobian.angular2;
                          b2.m_angularVelocity += invI2 * motorImpulse * this.m_motorJacobian.angular2;
                  }
  
                  // Solve linear limit constraint.
                  if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
                  {
                          var limitCdot = this.m_motorJacobian.Compute(b1.m_linearVelocity, b1.m_angularVelocity, b2.m_linearVelocity, b2.m_angularVelocity);
                          var limitImpulse = -this.m_motorMass * limitCdot;
  
                          if (this.m_limitState == b2Joint.e_equalLimits)
                          {
                                  this.m_limitImpulse += limitImpulse;
                          }
                          else if (this.m_limitState == b2Joint.e_atLowerLimit)
                          {
                                  oldLimitImpulse = this.m_limitImpulse;
                                  this.m_limitImpulse = b2Math.b2Max(this.m_limitImpulse + limitImpulse, 0.0);
                                  limitImpulse = this.m_limitImpulse - oldLimitImpulse;
                          }
                          else if (this.m_limitState == b2Joint.e_atUpperLimit)
                          {
                                  oldLimitImpulse = this.m_limitImpulse;
                                  this.m_limitImpulse = b2Math.b2Min(this.m_limitImpulse + limitImpulse, 0.0);
                                  limitImpulse = this.m_limitImpulse - oldLimitImpulse;
                          }
  
                          //b1->m_linearVelocity += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1;
                          b1.m_linearVelocity.x += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.x;
                          b1.m_linearVelocity.y += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.y;
                          //b1->m_angularVelocity += invI1 * limitImpulse * this.m_motorJacobian.angular1;
                          b1.m_angularVelocity += invI1 * limitImpulse * this.m_motorJacobian.angular1;
  
                          //b2->m_linearVelocity += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2;
                          b2.m_linearVelocity.x += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.x;
                          b2.m_linearVelocity.y += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.y;
                          //b2->m_angularVelocity += invI2 * limitImpulse * this.m_motorJacobian.angular2;
                          b2.m_angularVelocity += invI2 * limitImpulse * this.m_motorJacobian.angular2;
                  }
          },
  
          SolvePositionConstraints: function(){
  
                  var limitC;
                  var oldLimitImpulse;
  
                  var b1 = this.m_body1;
                  var b2 = this.m_body2;
  
                  var invMass1 = b1.m_invMass;
                  var invMass2 = b2.m_invMass;
                  var invI1 = b1.m_invI;
                  var invI2 = b2.m_invI;
  
                  var tMat;
  
                  //b2Vec2 r1 = b2Mul(b1->m_R, this.m_localAnchor1);
                  tMat = b1.m_R;
                  var r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
                  var r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
                  //b2Vec2 r2 = b2Mul(b2->m_R, this.m_localAnchor2);
                  tMat = b2.m_R;
                  var r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
                  var r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
                  //b2Vec2 p1 = b1->m_position + r1;
                  var p1X = b1.m_position.x + r1X;
                  var p1Y = b1.m_position.y + r1Y;
                  //b2Vec2 p2 = b2->m_position + r2;
                  var p2X = b2.m_position.x + r2X;
                  var p2Y = b2.m_position.y + r2Y;
                  //b2Vec2 d = p2 - p1;
                  var dX = p2X - p1X;
                  var dY = p2Y - p1Y;
                  //b2Vec2 ay1 = b2Mul(b1->m_R, this.m_localYAxis1);
                  tMat = b1.m_R;
                  var ay1X = tMat.col1.x * this.m_localYAxis1.x + tMat.col2.x * this.m_localYAxis1.y;
                  var ay1Y = tMat.col1.y * this.m_localYAxis1.x + tMat.col2.y * this.m_localYAxis1.y;
  
                  // Solve linear (point-to-line) constraint.
                  //float32 linearC = b2Dot(ay1, d);
                  var linearC = ay1X*dX + ay1Y*dY;
                  // Prevent overly large corrections.
                  linearC = b2Math.b2Clamp(linearC, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
                  var linearImpulse = -this.m_linearMass * linearC;
  
                  //b1->m_position += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1;
                  b1.m_position.x += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.x;
                  b1.m_position.y += (invMass1 * linearImpulse) * this.m_linearJacobian.linear1.y;
                  //b1->m_rotation += invI1 * linearImpulse * this.m_linearJacobian.angular1;
                  b1.m_rotation += invI1 * linearImpulse * this.m_linearJacobian.angular1;
                  //b1->m_R.Set(b1->m_rotation);
                  //b2->m_position += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2;
                  b2.m_position.x += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.x;
                  b2.m_position.y += (invMass2 * linearImpulse) * this.m_linearJacobian.linear2.y;
                  b2.m_rotation += invI2 * linearImpulse * this.m_linearJacobian.angular2;
                  //b2->m_R.Set(b2->m_rotation);
  
                  var positionError = b2Math.b2Abs(linearC);
  
                  // Solve angular constraint.
                  var angularC = b2.m_rotation - b1.m_rotation - this.m_initialAngle;
                  // Prevent overly large corrections.
                  angularC = b2Math.b2Clamp(angularC, -b2Settings.b2_maxAngularCorrection, b2Settings.b2_maxAngularCorrection);
                  var angularImpulse = -this.m_angularMass * angularC;
  
                  b1.m_rotation -= b1.m_invI * angularImpulse;
                  b1.m_R.Set(b1.m_rotation);
                  b2.m_rotation += b2.m_invI * angularImpulse;
                  b2.m_R.Set(b2.m_rotation);
  
                  var angularError = b2Math.b2Abs(angularC);
  
                  // Solve linear limit constraint.
                  if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit)
                  {
  
                          //b2Vec2 r1 = b2Mul(b1->m_R, this.m_localAnchor1);
                          tMat = b1.m_R;
                          r1X = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
                          r1Y = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
                          //b2Vec2 r2 = b2Mul(b2->m_R, this.m_localAnchor2);
                          tMat = b2.m_R;
                          r2X = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
                          r2Y = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
                          //b2Vec2 p1 = b1->m_position + r1;
                          p1X = b1.m_position.x + r1X;
                          p1Y = b1.m_position.y + r1Y;
                          //b2Vec2 p2 = b2->m_position + r2;
                          p2X = b2.m_position.x + r2X;
                          p2Y = b2.m_position.y + r2Y;
                          //b2Vec2 d = p2 - p1;
                          dX = p2X - p1X;
                          dY = p2Y - p1Y;
                          //b2Vec2 ax1 = b2Mul(b1->m_R, this.m_localXAxis1);
                          tMat = b1.m_R;
                          var ax1X = tMat.col1.x * this.m_localXAxis1.x + tMat.col2.x * this.m_localXAxis1.y;
                          var ax1Y = tMat.col1.y * this.m_localXAxis1.x + tMat.col2.y * this.m_localXAxis1.y;
  
                          //float32 translation = b2Dot(ax1, d);
                          var translation = (ax1X*dX + ax1Y*dY);
                          var limitImpulse = 0.0;
  
                          if (this.m_limitState == b2Joint.e_equalLimits)
                          {
                                  // Prevent large angular corrections
                                  limitC = b2Math.b2Clamp(translation, -b2Settings.b2_maxLinearCorrection, b2Settings.b2_maxLinearCorrection);
                                  limitImpulse = -this.m_motorMass * limitC;
                                  positionError = b2Math.b2Max(positionError, b2Math.b2Abs(angularC));
                          }
                          else if (this.m_limitState == b2Joint.e_atLowerLimit)
                          {
                                  limitC = translation - this.m_lowerTranslation;
                                  positionError = b2Math.b2Max(positionError, -limitC);
  
                                  // Prevent large linear corrections and allow some slop.
                                  limitC = b2Math.b2Clamp(limitC + b2Settings.b2_linearSlop, -b2Settings.b2_maxLinearCorrection, 0.0);
                                  limitImpulse = -this.m_motorMass * limitC;
                                  oldLimitImpulse = this.m_limitPositionImpulse;
                                  this.m_limitPositionImpulse = b2Math.b2Max(this.m_limitPositionImpulse + limitImpulse, 0.0);
                                  limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
                          }
                          else if (this.m_limitState == b2Joint.e_atUpperLimit)
                          {
                                  limitC = translation - this.m_upperTranslation;
                                  positionError = b2Math.b2Max(positionError, limitC);
  
                                  // Prevent large linear corrections and allow some slop.
                                  limitC = b2Math.b2Clamp(limitC - b2Settings.b2_linearSlop, 0.0, b2Settings.b2_maxLinearCorrection);
                                  limitImpulse = -this.m_motorMass * limitC;
                                  oldLimitImpulse = this.m_limitPositionImpulse;
                                  this.m_limitPositionImpulse = b2Math.b2Min(this.m_limitPositionImpulse + limitImpulse, 0.0);
                                  limitImpulse = this.m_limitPositionImpulse - oldLimitImpulse;
                          }
  
                          //b1->m_position += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1;
                          b1.m_position.x += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.x;
                          b1.m_position.y += (invMass1 * limitImpulse) * this.m_motorJacobian.linear1.y;
                          //b1->m_rotation += invI1 * limitImpulse * this.m_motorJacobian.angular1;
                          b1.m_rotation += invI1 * limitImpulse * this.m_motorJacobian.angular1;
                          b1.m_R.Set(b1.m_rotation);
                          //b2->m_position += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2;
                          b2.m_position.x += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.x;
                          b2.m_position.y += (invMass2 * limitImpulse) * this.m_motorJacobian.linear2.y;
                          //b2->m_rotation += invI2 * limitImpulse * this.m_motorJacobian.angular2;
                          b2.m_rotation += invI2 * limitImpulse * this.m_motorJacobian.angular2;
                          b2.m_R.Set(b2.m_rotation);
                  }
  
                  return positionError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop;
  
          },
  
          m_localAnchor1: new b2Vec2(),
          m_localAnchor2: new b2Vec2(),
          m_localXAxis1: new b2Vec2(),
          m_localYAxis1: new b2Vec2(),
          m_initialAngle: null,
  
          m_linearJacobian: new b2Jacobian(),
          m_linearMass: null,
          m_linearImpulse: null,
  
          m_angularMass: null,
          m_angularImpulse: null,
  
          m_motorJacobian: new b2Jacobian(),
          m_motorMass: null,
          m_motorImpulse: null,
          m_limitImpulse: null,
          m_limitPositionImpulse: null,
  
          m_lowerTranslation: null,
          m_upperTranslation: null,
          m_maxMotorForce: null,
          m_motorSpeed: null,
  
          m_enableLimit: null,
          m_enableMotor: null,
          m_limitState: 0});
  
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.