API Docs for: 0.6.1
Show:

File: src/objects/Spring.js

  1. var Vec3 = require('../math/Vec3');
  2.  
  3. module.exports = Spring;
  4.  
  5. /**
  6. * A spring, connecting two bodies.
  7. *
  8. * @class Spring
  9. * @constructor
  10. * @param {Body} bodyA
  11. * @param {Body} bodyB
  12. * @param {Object} [options]
  13. * @param {number} [options.restLength] A number > 0. Default: 1
  14. * @param {number} [options.stiffness] A number >= 0. Default: 100
  15. * @param {number} [options.damping] A number >= 0. Default: 1
  16. * @param {Vec3} [options.worldAnchorA] Where to hook the spring to body A, in world coordinates.
  17. * @param {Vec3} [options.worldAnchorB]
  18. * @param {Vec3} [options.localAnchorA] Where to hook the spring to body A, in local body coordinates.
  19. * @param {Vec3} [options.localAnchorB]
  20. */
  21. function Spring(bodyA,bodyB,options){
  22. options = options || {};
  23.  
  24. /**
  25. * Rest length of the spring.
  26. * @property restLength
  27. * @type {number}
  28. */
  29. this.restLength = typeof(options.restLength) === "number" ? options.restLength : 1;
  30.  
  31. /**
  32. * Stiffness of the spring.
  33. * @property stiffness
  34. * @type {number}
  35. */
  36. this.stiffness = options.stiffness || 100;
  37.  
  38. /**
  39. * Damping of the spring.
  40. * @property damping
  41. * @type {number}
  42. */
  43. this.damping = options.damping || 1;
  44.  
  45. /**
  46. * First connected body.
  47. * @property bodyA
  48. * @type {Body}
  49. */
  50. this.bodyA = bodyA;
  51.  
  52. /**
  53. * Second connected body.
  54. * @property bodyB
  55. * @type {Body}
  56. */
  57. this.bodyB = bodyB;
  58.  
  59. /**
  60. * Anchor for bodyA in local bodyA coordinates.
  61. * @property localAnchorA
  62. * @type {Vec3}
  63. */
  64. this.localAnchorA = new Vec3();
  65.  
  66. /**
  67. * Anchor for bodyB in local bodyB coordinates.
  68. * @property localAnchorB
  69. * @type {Vec3}
  70. */
  71. this.localAnchorB = new Vec3();
  72.  
  73. if(options.localAnchorA){
  74. this.localAnchorA.copy(options.localAnchorA);
  75. }
  76. if(options.localAnchorB){
  77. this.localAnchorB.copy(options.localAnchorB);
  78. }
  79. if(options.worldAnchorA){
  80. this.setWorldAnchorA(options.worldAnchorA);
  81. }
  82. if(options.worldAnchorB){
  83. this.setWorldAnchorB(options.worldAnchorB);
  84. }
  85. }
  86.  
  87. /**
  88. * Set the anchor point on body A, using world coordinates.
  89. * @method setWorldAnchorA
  90. * @param {Vec3} worldAnchorA
  91. */
  92. Spring.prototype.setWorldAnchorA = function(worldAnchorA){
  93. this.bodyA.pointToLocalFrame(worldAnchorA,this.localAnchorA);
  94. };
  95.  
  96. /**
  97. * Set the anchor point on body B, using world coordinates.
  98. * @method setWorldAnchorB
  99. * @param {Vec3} worldAnchorB
  100. */
  101. Spring.prototype.setWorldAnchorB = function(worldAnchorB){
  102. this.bodyB.pointToLocalFrame(worldAnchorB,this.localAnchorB);
  103. };
  104.  
  105. /**
  106. * Get the anchor point on body A, in world coordinates.
  107. * @method getWorldAnchorA
  108. * @param {Vec3} result The vector to store the result in.
  109. */
  110. Spring.prototype.getWorldAnchorA = function(result){
  111. this.bodyA.pointToWorldFrame(this.localAnchorA,result);
  112. };
  113.  
  114. /**
  115. * Get the anchor point on body B, in world coordinates.
  116. * @method getWorldAnchorB
  117. * @param {Vec3} result The vector to store the result in.
  118. */
  119. Spring.prototype.getWorldAnchorB = function(result){
  120. this.bodyB.pointToWorldFrame(this.localAnchorB,result);
  121. };
  122.  
  123. var applyForce_r = new Vec3(),
  124. applyForce_r_unit = new Vec3(),
  125. applyForce_u = new Vec3(),
  126. applyForce_f = new Vec3(),
  127. applyForce_worldAnchorA = new Vec3(),
  128. applyForce_worldAnchorB = new Vec3(),
  129. applyForce_ri = new Vec3(),
  130. applyForce_rj = new Vec3(),
  131. applyForce_ri_x_f = new Vec3(),
  132. applyForce_rj_x_f = new Vec3(),
  133. applyForce_tmp = new Vec3();
  134.  
  135. /**
  136. * Apply the spring force to the connected bodies.
  137. * @method applyForce
  138. */
  139. Spring.prototype.applyForce = function(){
  140. var k = this.stiffness,
  141. d = this.damping,
  142. l = this.restLength,
  143. bodyA = this.bodyA,
  144. bodyB = this.bodyB,
  145. r = applyForce_r,
  146. r_unit = applyForce_r_unit,
  147. u = applyForce_u,
  148. f = applyForce_f,
  149. tmp = applyForce_tmp;
  150.  
  151. var worldAnchorA = applyForce_worldAnchorA,
  152. worldAnchorB = applyForce_worldAnchorB,
  153. ri = applyForce_ri,
  154. rj = applyForce_rj,
  155. ri_x_f = applyForce_ri_x_f,
  156. rj_x_f = applyForce_rj_x_f;
  157.  
  158. // Get world anchors
  159. this.getWorldAnchorA(worldAnchorA);
  160. this.getWorldAnchorB(worldAnchorB);
  161.  
  162. // Get offset points
  163. worldAnchorA.vsub(bodyA.position,ri);
  164. worldAnchorB.vsub(bodyB.position,rj);
  165.  
  166. // Compute distance vector between world anchor points
  167. worldAnchorB.vsub(worldAnchorA,r);
  168. var rlen = r.norm();
  169. r_unit.copy(r);
  170. r_unit.normalize();
  171.  
  172. // Compute relative velocity of the anchor points, u
  173. bodyB.velocity.vsub(bodyA.velocity,u);
  174. // Add rotational velocity
  175.  
  176. bodyB.angularVelocity.cross(rj,tmp);
  177. u.vadd(tmp,u);
  178. bodyA.angularVelocity.cross(ri,tmp);
  179. u.vsub(tmp,u);
  180.  
  181. // F = - k * ( x - L ) - D * ( u )
  182. r_unit.mult(-k*(rlen-l) - d*u.dot(r_unit), f);
  183.  
  184. // Add forces to bodies
  185. bodyA.force.vsub(f,bodyA.force);
  186. bodyB.force.vadd(f,bodyB.force);
  187.  
  188. // Angular force
  189. ri.cross(f,ri_x_f);
  190. rj.cross(f,rj_x_f);
  191. bodyA.torque.vsub(ri_x_f,bodyA.torque);
  192. bodyB.torque.vadd(rj_x_f,bodyB.torque);
  193. };
  194.