Skip to content

Commit

Permalink
added Body.prototype.applyLocalForce and .applyLocalImpulse, fixes sc…
Browse files Browse the repository at this point in the history
  • Loading branch information
schteppe committed Dec 22, 2014
1 parent 35c49bf commit dc5a82b
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
46 changes: 46 additions & 0 deletions src/objects/Body.js
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,29 @@ Body.prototype.applyForce = function(force,worldPoint){
this.torque.vadd(rotForce,this.torque);
};

/**
* Apply force to a local point in the body.
* @method applyLocalForce
* @param {Vec3} force The force vector to apply, defined locally in the body frame.
* @param {Vec3} localPoint A local point in the body to apply the force on.
*/
var Body_applyLocalForce_worldForce = new Vec3();
var Body_applyLocalForce_worldPoint = new Vec3();
Body.prototype.applyLocalForce = function(localForce, localPoint){
if(this.type !== Body.DYNAMIC){
return;
}

var worldForce = Body_applyLocalForce_worldForce;
var worldPoint = Body_applyLocalForce_worldPoint;

// Transform the force vector to world space
this.vectorToWorldFrame(localForce, worldForce);
this.pointToWorldFrame(localPoint, worldPoint);

this.applyForce(worldForce, worldPoint);
};

/**
* Apply impulse to a world point. This could for example be a point on the Body surface. An impulse is a force added to a body during a short period of time (impulse = force * time). Impulses will be added to Body.velocity and Body.angularVelocity.
* @method applyImpulse
Expand Down Expand Up @@ -678,6 +701,29 @@ Body.prototype.applyImpulse = function(impulse, worldPoint){
this.angularVelocity.vadd(rotVelo, this.angularVelocity);
};

/**
* Apply locally-defined impulse to a local point in the body.
* @method applyLocalImpulse
* @param {Vec3} force The force vector to apply, defined locally in the body frame.
* @param {Vec3} localPoint A local point in the body to apply the force on.
*/
var Body_applyLocalImpulse_worldImpulse = new Vec3();
var Body_applyLocalImpulse_worldPoint = new Vec3();
Body.prototype.applyLocalImpulse = function(localImpulse, localPoint){
if(this.type !== Body.DYNAMIC){
return;
}

var worldImpulse = Body_applyLocalImpulse_worldImpulse;
var worldPoint = Body_applyLocalImpulse_worldPoint;

// Transform the force vector to world space
this.vectorToWorldFrame(localImpulse, worldImpulse);
this.pointToWorldFrame(localPoint, worldPoint);

this.applyImpulse(worldImpulse, worldPoint);
};

/**
* Should be called whenever you change the body mass.
* @method updateMassProperties
Expand Down
68 changes: 68 additions & 0 deletions test/Body.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,72 @@ module.exports = {

test.done();
},

applyForce : function(test){
var sphereShape = new Sphere(1);
var body = new Body({
mass: 1,
shape: sphereShape
});

var worldPoint = new Vec3(1,0,0);
var forceVector = new Vec3(0,1,0);
body.applyForce(forceVector, worldPoint);
test.deepEqual(body.force, forceVector);
test.deepEqual(body.torque, new Vec3(0,0,1));

test.done();
},

applyLocalForce : function(test){
var sphereShape = new Sphere(1);
var body = new Body({
mass: 1,
shape: sphereShape
});
body.quaternion.setFromAxisAngle(new Vec3(1, 0, 0), Math.PI / 2);

var localPoint = new Vec3(1,0,0);
var localForceVector = new Vec3(0,1,0);
body.applyLocalForce(localForceVector, localPoint);
test.ok(body.force.almostEquals(new Vec3(0,0,1))); // The force is rotated to world space

test.done();
},

applyImpulse : function(test){
var sphereShape = new Sphere(1);
var body = new Body({
mass: 1,
shape: sphereShape
});

var f = 1000;
var dt = 1 / 60;
var worldPoint = new Vec3(0,0,0);
var impulse = new Vec3(f*dt,0,0);
body.applyImpulse(impulse, worldPoint);

test.ok(body.velocity.almostEquals(new Vec3(f*dt,0,0)));

test.done();
},

applyLocalImpulse : function(test){
var sphereShape = new Sphere(1);
var body = new Body({
mass: 1,
shape: sphereShape
});
body.quaternion.setFromAxisAngle(new Vec3(1, 0, 0), Math.PI / 2);

var f = 1000;
var dt = 1 / 60;
var localPoint = new Vec3(1,0,0);
var localImpulseVector = new Vec3(0,f*dt,0);
body.applyLocalImpulse(localImpulseVector, localPoint);
test.ok(body.velocity.almostEquals(new Vec3(0,0,f*dt))); // The force is rotated to world space

test.done();
},
};

0 comments on commit dc5a82b

Please sign in to comment.