topical media & game development

talk show tell print

#javascript-physics-js-box2d-dynamics-joints-b2GearJoint.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.
*/

var b2GearJoint = Class.create();
Object.extend(b2GearJoint.prototype, b2Joint.prototype);
Object.extend(b2GearJoint.prototype, 
{
        GetAnchor1: function(){
                //return this.m_body1.m_position + b2MulMV(this.m_body1.m_R, this.m_localAnchor1);
                var tMat = this.m_body1.m_R;
                return new b2Vec2(        this.m_body1.m_position.x + (tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y),
                                                        this.m_body1.m_position.y + (tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y));
        },
        GetAnchor2: function(){
                //return this.m_body2->m_position + b2Mul(this.m_body2->m_R, this.m_localAnchor2);
                var tMat = this.m_body2.m_R;
                return new b2Vec2(        this.m_body2.m_position.x + (tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y),
                                                        this.m_body2.m_position.y + (tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y));
        },

        GetReactionForce: function(invTimeStep){
                //b2Vec2 F(0.0f, 0.0f);
                return new b2Vec2();
        },
        GetReactionTorque: function(invTimeStep){
                return 0.0;
        },

        GetRatio: function(){
                return this.m_ratio;
        },

        //--------------- 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_groundAnchor1 = new b2Vec2();
                this.m_groundAnchor2 = new b2Vec2();
                this.m_localAnchor1 = new b2Vec2();
                this.m_localAnchor2 = new b2Vec2();
                this.m_J = new b2Jacobian();
                //

                // parent constructor
                //super(def);

                //b2Settings.b2Assert(def.joint1.m_type == b2Joint.e_revoluteJoint || def.joint1.m_type == b2Joint.e_prismaticJoint);
                //b2Settings.b2Assert(def.joint2.m_type == b2Joint.e_revoluteJoint || def.joint2.m_type == b2Joint.e_prismaticJoint);
                //b2Settings.b2Assert(def.joint1.m_body1.IsStatic());
                //b2Settings.b2Assert(def.joint2.m_body1.IsStatic());

                this.m_revolute1 = null;
                this.m_prismatic1 = null;
                this.m_revolute2 = null;
                this.m_prismatic2 = null;

                var coordinate1;
                var coordinate2;

                this.m_ground1 = def.joint1.m_body1;
                this.m_body1 = def.joint1.m_body2;
                if (def.joint1.m_type == b2Joint.e_revoluteJoint)
                {
                        this.m_revolute1 = def.joint1;
                        this.m_groundAnchor1.SetV( this.m_revolute1.m_localAnchor1 );
                        this.m_localAnchor1.SetV( this.m_revolute1.m_localAnchor2 );
                        coordinate1 = this.m_revolute1.GetJointAngle();
                }
                else
                {
                        this.m_prismatic1 = def.joint1;
                        this.m_groundAnchor1.SetV( this.m_prismatic1.m_localAnchor1 );
                        this.m_localAnchor1.SetV( this.m_prismatic1.m_localAnchor2 );
                        coordinate1 = this.m_prismatic1.GetJointTranslation();
                }

                this.m_ground2 = def.joint2.m_body1;
                this.m_body2 = def.joint2.m_body2;
                if (def.joint2.m_type == b2Joint.e_revoluteJoint)
                {
                        this.m_revolute2 = def.joint2;
                        this.m_groundAnchor2.SetV( this.m_revolute2.m_localAnchor1 );
                        this.m_localAnchor2.SetV( this.m_revolute2.m_localAnchor2 );
                        coordinate2 = this.m_revolute2.GetJointAngle();
                }
                else
                {
                        this.m_prismatic2 = def.joint2;
                        this.m_groundAnchor2.SetV( this.m_prismatic2.m_localAnchor1 );
                        this.m_localAnchor2.SetV( this.m_prismatic2.m_localAnchor2 );
                        coordinate2 = this.m_prismatic2.GetJointTranslation();
                }

                this.m_ratio = def.ratio;

                this.m_constant = coordinate1 + this.m_ratio * coordinate2;

                this.m_impulse = 0.0;

        },

        PrepareVelocitySolver: function(){
                var g1 = this.m_ground1;
                var g2 = this.m_ground2;
                var b1 = this.m_body1;
                var b2 = this.m_body2;

                // temp vars
                var ugX;
                var ugY;
                var rX;
                var rY;
                var tMat;
                var tVec;
                var crug;

                var K = 0.0;
                this.m_J.SetZero();

                if (this.m_revolute1)
                {
                        this.m_J.angular1 = -1.0;
                        K += b1.m_invI;
                }
                else
                {
                        //b2Vec2 ug = b2MulMV(g1->m_R, this.m_prismatic1->m_localXAxis1);
                        tMat = g1.m_R;
                        tVec = this.m_prismatic1.m_localXAxis1;
                        ugX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                        ugY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                        //b2Vec2 r = b2MulMV(b1->m_R, this.m_localAnchor1);
                        tMat = b1.m_R;
                        rX = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
                        rY = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;

                        //var crug = b2Cross(r, ug);
                        crug = rX * ugY - rY * ugX;
                        //this.m_J.linear1 = -ug;
                        this.m_J.linear1.Set(-ugX, -ugY);
                        this.m_J.angular1 = -crug;
                        K += b1.m_invMass + b1.m_invI * crug * crug;
                }

                if (this.m_revolute2)
                {
                        this.m_J.angular2 = -this.m_ratio;
                        K += this.m_ratio * this.m_ratio * b2.m_invI;
        
  *
  * 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.
  */
  
  var b2GearJoint = Class.create();
  Object.extend(b2GearJoint.prototype, b2Joint.prototype);
  Object.extend(b2GearJoint.prototype, 
  {
          GetAnchor1: function(){
                  //return this.m_body1.m_position + b2MulMV(this.m_body1.m_R, this.m_localAnchor1);
                  var tMat = this.m_body1.m_R;
                  return new b2Vec2(        this.m_body1.m_position.x + (tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y),
                                                          this.m_body1.m_position.y + (tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y));
          },
          GetAnchor2: function(){
                  //return this.m_body2->m_position + b2Mul(this.m_body2->m_R, this.m_localAnchor2);
                  var tMat = this.m_body2.m_R;
                  return new b2Vec2(        this.m_body2.m_position.x + (tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y),
                                                          this.m_body2.m_position.y + (tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y));
          },
  
          GetReactionForce: function(invTimeStep){
                  //b2Vec2 F(0.0f, 0.0f);
                  return new b2Vec2();
          },
          GetReactionTorque: function(invTimeStep){
                  return 0.0;
          },
  
          GetRatio: function(){
                  return this.m_ratio;
          },
  
          //--------------- 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_groundAnchor1 = new b2Vec2();
                  this.m_groundAnchor2 = new b2Vec2();
                  this.m_localAnchor1 = new b2Vec2();
                  this.m_localAnchor2 = new b2Vec2();
                  this.m_J = new b2Jacobian();
                  //
  
                  // parent constructor
                  //super(def);
  
                  //b2Settings.b2Assert(def.joint1.m_type == b2Joint.e_revoluteJoint || def.joint1.m_type == b2Joint.e_prismaticJoint);
                  //b2Settings.b2Assert(def.joint2.m_type == b2Joint.e_revoluteJoint || def.joint2.m_type == b2Joint.e_prismaticJoint);
                  //b2Settings.b2Assert(def.joint1.m_body1.IsStatic());
                  //b2Settings.b2Assert(def.joint2.m_body1.IsStatic());
  
                  this.m_revolute1 = null;
                  this.m_prismatic1 = null;
                  this.m_revolute2 = null;
                  this.m_prismatic2 = null;
  
                  var coordinate1;
                  var coordinate2;
  
                  this.m_ground1 = def.joint1.m_body1;
                  this.m_body1 = def.joint1.m_body2;
                  if (def.joint1.m_type == b2Joint.e_revoluteJoint)
                  {
                          this.m_revolute1 = def.joint1;
                          this.m_groundAnchor1.SetV( this.m_revolute1.m_localAnchor1 );
                          this.m_localAnchor1.SetV( this.m_revolute1.m_localAnchor2 );
                          coordinate1 = this.m_revolute1.GetJointAngle();
                  }
                  else
                  {
                          this.m_prismatic1 = def.joint1;
                          this.m_groundAnchor1.SetV( this.m_prismatic1.m_localAnchor1 );
                          this.m_localAnchor1.SetV( this.m_prismatic1.m_localAnchor2 );
                          coordinate1 = this.m_prismatic1.GetJointTranslation();
                  }
  
                  this.m_ground2 = def.joint2.m_body1;
                  this.m_body2 = def.joint2.m_body2;
                  if (def.joint2.m_type == b2Joint.e_revoluteJoint)
                  {
                          this.m_revolute2 = def.joint2;
                          this.m_groundAnchor2.SetV( this.m_revolute2.m_localAnchor1 );
                          this.m_localAnchor2.SetV( this.m_revolute2.m_localAnchor2 );
                          coordinate2 = this.m_revolute2.GetJointAngle();
                  }
                  else
                  {
                          this.m_prismatic2 = def.joint2;
                          this.m_groundAnchor2.SetV( this.m_prismatic2.m_localAnchor1 );
                          this.m_localAnchor2.SetV( this.m_prismatic2.m_localAnchor2 );
                          coordinate2 = this.m_prismatic2.GetJointTranslation();
                  }
  
                  this.m_ratio = def.ratio;
  
                  this.m_constant = coordinate1 + this.m_ratio * coordinate2;
  
                  this.m_impulse = 0.0;
  
          },
  
          PrepareVelocitySolver: function(){
                  var g1 = this.m_ground1;
                  var g2 = this.m_ground2;
                  var b1 = this.m_body1;
                  var b2 = this.m_body2;
  
                  // temp vars
                  var ugX;
                  var ugY;
                  var rX;
                  var rY;
                  var tMat;
                  var tVec;
                  var crug;
  
                  var K = 0.0;
                  this.m_J.SetZero();
  
                  if (this.m_revolute1)
                  {
                          this.m_J.angular1 = -1.0;
                          K += b1.m_invI;
                  }
                  else
                  {
                          //b2Vec2 ug = b2MulMV(g1->m_R, this.m_prismatic1->m_localXAxis1);
                          tMat = g1.m_R;
                          tVec = this.m_prismatic1.m_localXAxis1;
                          ugX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                          ugY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                          //b2Vec2 r = b2MulMV(b1->m_R, this.m_localAnchor1);
                          tMat = b1.m_R;
                          rX = tMat.col1.x * this.m_localAnchor1.x + tMat.col2.x * this.m_localAnchor1.y;
                          rY = tMat.col1.y * this.m_localAnchor1.x + tMat.col2.y * this.m_localAnchor1.y;
  
                          //var crug = b2Cross(r, ug);
                          crug = rX * ugY - rY * ugX;
                          //this.m_J.linear1 = -ug;
                          this.m_J.linear1.Set(-ugX, -ugY);
                          this.m_J.angular1 = -crug;
                          K += b1.m_invMass + b1.m_invI * crug * crug;
                  }
  
                  if (this.m_revolute2)
                  {
                          this.m_J.angular2 = -this.m_ratio;
                          K += this.m_ratio * this.m_ratio * b2.m_invI;
                  }
                  else
                  {
                          //b2Vec2 ug = b2Mul(g2->m_R, this.m_prismatic2->m_localXAxis1);
                          tMat = g2.m_R;
                          tVec = this.m_prismatic2.m_localXAxis1;
                          ugX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                          ugY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                          //b2Vec2 r = b2Mul(b2->m_R, this.m_localAnchor2);
                          tMat = b2.m_R;
                          rX = tMat.col1.x * this.m_localAnchor2.x + tMat.col2.x * this.m_localAnchor2.y;
                          rY = tMat.col1.y * this.m_localAnchor2.x + tMat.col2.y * this.m_localAnchor2.y;
                          //float32 crug = b2Cross(r, ug);
                          crug = rX * ugY - rY * ugX;
                          //this.m_J.linear2 = -this.m_ratio * ug;
                          this.m_J.linear2.Set(-this.m_ratio*ugX, -this.m_ratio*ugY);
                          this.m_J.angular2 = -this.m_ratio * crug;
                          K += this.m_ratio * this.m_ratio * (b2.m_invMass + b2.m_invI * crug * crug);
                  }
  
                  // Compute effective mass.
                  //b2Settings.b2Assert(K > 0.0);
                  this.m_mass = 1.0 / K;
  
                  // Warm starting.
                  //b1.m_linearVelocity += b1.m_invMass * this.m_impulse * this.m_J.linear1;
                  b1.m_linearVelocity.x += b1.m_invMass * this.m_impulse * this.m_J.linear1.x;
                  b1.m_linearVelocity.y += b1.m_invMass * this.m_impulse * this.m_J.linear1.y;
                  b1.m_angularVelocity += b1.m_invI * this.m_impulse * this.m_J.angular1;
                  //b2.m_linearVelocity += b2.m_invMass * this.m_impulse * this.m_J.linear2;
                  b2.m_linearVelocity.x += b2.m_invMass * this.m_impulse * this.m_J.linear2.x;
                  b2.m_linearVelocity.y += b2.m_invMass * this.m_impulse * this.m_J.linear2.y;
                  b2.m_angularVelocity += b2.m_invI * this.m_impulse * this.m_J.angular2;
          },
  
          SolveVelocityConstraints: function(step){
                  var b1 = this.m_body1;
                  var b2 = this.m_body2;
  
                  var Cdot = this.m_J.Compute(        b1.m_linearVelocity, b1.m_angularVelocity,
                                                                                  b2.m_linearVelocity, b2.m_angularVelocity);
  
                  var impulse = -this.m_mass * Cdot;
                  this.m_impulse += impulse;
  
                  b1.m_linearVelocity.x += b1.m_invMass * impulse * this.m_J.linear1.x;
                  b1.m_linearVelocity.y += b1.m_invMass * impulse * this.m_J.linear1.y;
                  b1.m_angularVelocity  += b1.m_invI * impulse * this.m_J.angular1;
                  b2.m_linearVelocity.x += b2.m_invMass * impulse * this.m_J.linear2.x;
                  b2.m_linearVelocity.y += b2.m_invMass * impulse * this.m_J.linear2.y;
                  b2.m_angularVelocity  += b2.m_invI * impulse * this.m_J.angular2;
          },
  
          SolvePositionConstraints: function(){
                  var linearError = 0.0;
  
                  var b1 = this.m_body1;
                  var b2 = this.m_body2;
  
                  var coordinate1;
                  var coordinate2;
                  if (this.m_revolute1)
                  {
                          coordinate1 = this.m_revolute1.GetJointAngle();
                  }
                  else
                  {
                          coordinate1 = this.m_prismatic1.GetJointTranslation();
                  }
  
                  if (this.m_revolute2)
                  {
                          coordinate2 = this.m_revolute2.GetJointAngle();
                  }
                  else
                  {
                          coordinate2 = this.m_prismatic2.GetJointTranslation();
                  }
  
                  var C = this.m_constant - (coordinate1 + this.m_ratio * coordinate2);
  
                  var impulse = -this.m_mass * C;
  
                  b1.m_position.x += b1.m_invMass * impulse * this.m_J.linear1.x;
                  b1.m_position.y += b1.m_invMass * impulse * this.m_J.linear1.y;
                  b1.m_rotation += b1.m_invI * impulse * this.m_J.angular1;
                  b2.m_position.x += b2.m_invMass * impulse * this.m_J.linear2.x;
                  b2.m_position.y += b2.m_invMass * impulse * this.m_J.linear2.y;
                  b2.m_rotation += b2.m_invI * impulse * this.m_J.angular2;
                  b1.m_R.Set(b1.m_rotation);
                  b2.m_R.Set(b2.m_rotation);
  
                  return linearError < b2Settings.b2_linearSlop;
          },
  
          m_ground1: null,
          m_ground2: null,
  
          // One of these is NULL.
          m_revolute1: null,
          m_prismatic1: null,
  
          // One of these is NULL.
          m_revolute2: null,
          m_prismatic2: null,
  
          m_groundAnchor1: new b2Vec2(),
          m_groundAnchor2: new b2Vec2(),
  
          m_localAnchor1: new b2Vec2(),
          m_localAnchor2: new b2Vec2(),
  
          m_J: new b2Jacobian(),
  
          m_constant: null,
          m_ratio: null,
  
          // Effective mass
          m_mass: null,
  
          // Impulse for accumulation/warm starting.
          m_impulse: null});
  
  


(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.