var vec2 = require('../math/vec2'); module.exports = Spring; function Spring(bodyA, bodyB, options){ options = options || { } ; this.restLength = typeof (options.restLength) == "number"? options.restLength: 1; this.stiffness = options.stiffness || 100; this.damping = options.damping || 1; this.bodyA = bodyA; this.bodyB = bodyB; this.localAnchorA = vec2.fromValues(0, 0); this.localAnchorB = vec2.fromValues(0, 0); if (options.localAnchorA) vec2.copy(this.localAnchorA, options.localAnchorA); if (options.localAnchorB) vec2.copy(this.localAnchorB, options.localAnchorB); if (options.worldAnchorA) this.setWorldAnchorA(options.worldAnchorA); if (options.worldAnchorB) this.setWorldAnchorB(options.worldAnchorB); } ; Spring.prototype.setWorldAnchorA = function (worldAnchorA){ this.bodyA.toLocalFrame(this.localAnchorA, worldAnchorA); } ; Spring.prototype.setWorldAnchorB = function (worldAnchorB){ this.bodyB.toLocalFrame(this.localAnchorB, worldAnchorB); } ; Spring.prototype.getWorldAnchorA = function (result){ this.bodyA.toWorldFrame(result, this.localAnchorA); } ; Spring.prototype.getWorldAnchorB = function (result){ this.bodyB.toWorldFrame(result, this.localAnchorB); } ; var applyForce_r = vec2.create(), applyForce_r_unit = vec2.create(), applyForce_u = vec2.create(), applyForce_f = vec2.create(), applyForce_worldAnchorA = vec2.create(), applyForce_worldAnchorB = vec2.create(), applyForce_ri = vec2.create(), applyForce_rj = vec2.create(), applyForce_tmp = vec2.create(); Spring.prototype.applyForce = function (){ var k = this.stiffness, d = this.damping, l = this.restLength, bodyA = this.bodyA, bodyB = this.bodyB, r = applyForce_r, r_unit = applyForce_r_unit, u = applyForce_u, f = applyForce_f, tmp = applyForce_tmp; var worldAnchorA = applyForce_worldAnchorA, worldAnchorB = applyForce_worldAnchorB, ri = applyForce_ri, rj = applyForce_rj; this.getWorldAnchorA(worldAnchorA); this.getWorldAnchorB(worldAnchorB); vec2.sub(ri, worldAnchorA, bodyA.position); vec2.sub(rj, worldAnchorB, bodyB.position); vec2.sub(r, worldAnchorB, worldAnchorA); var rlen = vec2.len(r); vec2.normalize(r_unit, r); vec2.sub(u, bodyB.velocity, bodyA.velocity); vec2.crossZV(tmp, bodyB.angularVelocity, rj); vec2.add(u, u, tmp); vec2.crossZV(tmp, bodyA.angularVelocity, ri); vec2.sub(u, u, tmp); vec2.scale(f, r_unit, - k * (rlen - l) - d * vec2.dot(u, r_unit)); vec2.sub(bodyA.force, bodyA.force, f); vec2.add(bodyB.force, bodyB.force, f); var ri_x_f = vec2.crossLength(ri, f); var rj_x_f = vec2.crossLength(rj, f); bodyA.angularForce -= ri_x_f; bodyB.angularForce += rj_x_f; } ;