text: module.exports = HingeConstraint;
  
  var Constraint = require('./Constraint');
  var PointToPointConstraint = require('./PointToPointConstraint');
  var RotationalEquation = require('../equations/RotationalEquation');
  var RotationalMotorEquation = require('../equations/RotationalMotorEquation');
  var ContactEquation = require('../equations/ContactEquation');
  var Vec3 = require('../math/Vec3');
  
  /**
   * Hinge constraint. Think of it as a door hinge. It tries to keep the door in the correct place and with the correct orientation.
   * @class HingeConstraint
   * @constructor
   * @author schteppe
   * @param {Body} bodyA
   * @param {Body} bodyB
   * @param {object} [options]
   * @param {Vec3} [options.pivotA] A point defined locally in bodyA. This defines the offset of axisA.
   * @param {Vec3} [options.axisA] An axis that bodyA can rotate around, defined locally in bodyA.
   * @param {Vec3} [options.pivotB]
   * @param {Vec3} [options.axisB]
   * @param {Number} [options.maxForce=1e6]
   * @extends PointToPointConstraint
   */
  function HingeConstraint(bodyA, bodyB, options){
      options = options || {};
      var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
      var pivotA = options.pivotA ? options.pivotA.clone() : new Vec3();
      var pivotB = options.pivotB ? options.pivotB.clone() : new Vec3();
  
      PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
  
      /**
       * Rotation axis, defined locally in bodyA.
       * @property {Vec3} axisA
       */
      var axisA = this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1,0,0);
      axisA.normalize();
  
      /**
       * Rotation axis, defined locally in bodyB.
       * @property {Vec3} axisB
       */
      var axisB = this.axisB = options.axisB ? options.axisB.clone() : new Vec3(1,0,0);
      axisB.normalize();
  
      /**
       * @property {RotationalEquation} rotationalEquation1
       */
      var r1 = this.rotationalEquation1 = new RotationalEquation(bodyA,bodyB,options);
  
      /**
       * @property {RotationalEquation} rotationalEquation2
       */
      var r2 = this.rotationalEquation2 = new RotationalEquation(bodyA,bodyB,options);
  
      /**
       * @property {RotationalMotorEquation} motorEquation
       */
      var motor = this.motorEquation = new RotationalMotorEquation(bodyA,bodyB,maxForce);
      motor.enabled = false; // Not enabled by default
  
      // Equations to be fed to the solver
      this.equations.push(
          r1, // rotational1
          r2, // rotational2
          motor
      );
  }
  HingeConstraint.prototype = new PointToPointConstraint();
  HingeConstraint.constructor = HingeConstraint;
  
  /**
   * @method enableMotor
   */
  HingeConstraint.prototype.enableMotor = function(){
      this.motorEquation.enabled = true;
  };
  
  /**
   * @method disableMotor
   */
  HingeConstraint.prototype.disableMotor = function(){
      this.motorEquation.enabled = false;
  };
  
  /**
   * @method setMotorSpeed
   * @param {number} speed
   */
  HingeConstraint.prototype.setMotorSpeed = function(speed){
      this.motorEquation.targetVelocity = speed;
  };
  
  /**
   * @method setMotorMaxForce
   * @param {number} maxForce
   */
  HingeConstraint.prototype.setMotorMaxForce = function(maxForce){
      this.motorEquation.maxForce = maxForce;
      this.motorEquation.minForce = -maxForce;
  };
  
  var HingeConstraint_update_tmpVec1 = new Vec3();
  var HingeConstraint_update_tmpVec2 = new Vec3();
  
  HingeConstraint.prototype.update = function(){
      var bodyA = this.bodyA,
          bodyB = this.bodyB,
          motor = this.motorEquation,
          r1 = this.rotationalEquation1,
          r2 = this.rotationalEquation2,
          worldAxisA = HingeConstraint_update_tmpVec1,
          worldAxisB = HingeConstraint_update_tmpVec2;
  
      var axisA = this.axisA;
      var axisB = this.axisB;
  
      PointToPointConstraint.prototype.update.call(this);
  
      // Get world axes
      bodyA.quaternion.vmult(axisA, worldAxisA);
      bodyB.quaternion.vmult(axisB, worldAxisB);
  
      worldAxisA.tangents(r1.axisA, r2.axisA);
      r1.axisB.copy(worldAxisB);
      r2.axisB.copy(worldAxisB);
  
      if(this.motorEquation.enabled){
          bodyA.quaternion.vmult(this.axisA, motor.axisA);
          bodyB.quaternion.vmult(this.axisB, motor.axisB);
      }
  };
  
  