Skip to content

Commit

Permalink
changed Body.prototype.applyForce to use a relative point Added .appl…
Browse files Browse the repository at this point in the history
…yLocalForce.
  • Loading branch information
schteppe committed Apr 4, 2015
1 parent 379a809 commit 28494c1
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 32 deletions.
66 changes: 37 additions & 29 deletions src/objects/Body.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ Body.prototype.updateSolveMassProperties = function(){
/**
* Set the total density of the body
* @method setDensity
* @param {number} density
*/
Body.prototype.setDensity = function(density) {
var totalArea = this.getArea();
Expand All @@ -475,6 +476,7 @@ Body.prototype.getArea = function() {
/**
* Get the AABB from the body. The AABB is updated if necessary.
* @method getAABB
* @return {AABB} The AABB instance (this.aabb)
*/
Body.prototype.getAABB = function(){
if(this.aabbNeedsUpdate){
Expand All @@ -487,7 +489,7 @@ var shapeAABB = new AABB(),
tmp = vec2.create();

/**
* Updates the AABB of the Body
* Updates the AABB of the Body, and set .aabbNeedsUpdate = false.
* @method updateAABB
*/
Body.prototype.updateAABB = function() {
Expand Down Expand Up @@ -520,8 +522,7 @@ Body.prototype.updateAABB = function() {
};

/**
* Update the bounding radius of the body. Should be done if any of the shapes
* are changed.
* Update the bounding radius of the body (this.boundingRadius). Should be done if any of the shape dimensions or positions are changed.
* @method updateBoundingRadius
*/
Body.prototype.updateBoundingRadius = function(){
Expand Down Expand Up @@ -575,9 +576,9 @@ Body.prototype.addShape = function(shape,offset,angle){
offset = vec2.fromValues(0,0);
}

this.shapes .push(shape);
this.shapes.push(shape);
this.shapeOffsets.push(offset);
this.shapeAngles .push(angle);
this.shapeAngles.push(angle);
this.updateMassProperties();
this.updateBoundingRadius();

Expand All @@ -587,8 +588,8 @@ Body.prototype.addShape = function(shape,offset,angle){
/**
* Remove a shape
* @method removeShape
* @param {Shape} shape
* @return {Boolean} True if the shape was found and removed, else false.
* @param {Shape} shape
* @return {Boolean} True if the shape was found and removed, else false.
*/
Body.prototype.removeShape = function(shape){
var idx = this.shapes.indexOf(shape);
Expand Down Expand Up @@ -658,24 +659,42 @@ Body.prototype.updateMassProperties = function(){
var Body_applyForce_r = vec2.create();

/**
* Apply force to a world point. This could for example be a point on the RigidBody surface. Applying force this way will add to Body.force and Body.angularForce.
* Apply force to a point relative to the center of mass of the body. This could for example be a point on the RigidBody surface. Applying force this way will add to Body.force and Body.angularForce. If relativePoint is zero, the force will be applied directly on the center of mass, and the torque produced will be zero.
* @method applyForce
* @param {Array} force The force to add.
* @param {Array} worldPoint A world point to apply the force on.
* @param {Array} [relativePoint] A world point to apply the force on.
*/
Body.prototype.applyForce = function(force,worldPoint){
// Compute point position relative to the body center
var r = Body_applyForce_r;
vec2.sub(r,worldPoint,this.position);
Body.prototype.applyForce = function(force, relativePoint){

// Add linear force
vec2.add(this.force,this.force,force);
vec2.add(this.force, this.force, force);

// Compute produced rotational force
var rotForce = vec2.crossLength(r,force);
if(relativePoint){

// Compute produced rotational force
var rotForce = vec2.crossLength(relativePoint,force);

// Add rotational force
this.angularForce += rotForce;
}
};

// Add rotational force
this.angularForce += rotForce;
/**
* Apply force to a body-local point.
* @method applyForceLocal
* @param {Array} localForce The force vector to add, oriented in local body space.
* @param {Array} localPoint A point relative to the body in world space. If not given, it is set to zero and all of the impulse will be excerted on the center of mass.
*/
var Body_applyForce_forceWorld = vec2.create();
var Body_applyForce_pointWorld = vec2.create();
var Body_applyForce_pointLocal = vec2.create();
Body.prototype.applyForceLocal = function(localForce, localPoint){
localPoint = localPoint || Body_applyForce_pointLocal;
var worldForce = Body_applyForce_forceWorld;
var worldPoint = Body_applyForce_pointWorld;
this.vectorToWorldFrame(worldForce, localForce);
this.vectorToWorldFrame(worldPoint, localPoint);
this.applyForce(worldForce, worldPoint);
};

/**
Expand Down Expand Up @@ -995,17 +1014,6 @@ Body.prototype.sleepTick = function(time, dontSleep, dt){
}
};

Body.prototype.getVelocityFromPosition = function(store, timeStep){
store = store || vec2.create();
vec2.sub(store, this.position, this.previousPosition);
vec2.scale(store, store, 1/timeStep);
return store;
};

Body.prototype.getAngularVelocityFromPosition = function(timeStep){
return (this.angle - this.previousAngle) / timeStep;
};

/**
* Check if the body is overlapping another body. Note that this method only works if the body was added to a World and if at least one step was taken.
* @method overlaps
Expand Down
56 changes: 53 additions & 3 deletions test/objects/Body.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,59 @@ exports.applyDamping = function(test){
test.done();
};

exports.applyForce = function(test){
// STUB
test.done();
exports.applyForce = {
withPoint: function(test){
var body = new Body({ mass: 1, position: [2,3] });
var force = [0,1];
var point = [1,0];

body.applyForce(force, point);
test.equal(body.force[0], 0);
test.equal(body.force[1], 1);
test.equal(body.angularForce, 1); // [1,0,0] cross [0,1,0] is [0,0,1]

test.done();
},
withoutPoint: function(test){
var body = new Body({ mass: 1, position: [2,3] });
var force = [0,1];

body.applyForce(force);
test.equal(body.force[0], 0);
test.equal(body.force[1], 1);
test.equal(body.angularForce, 0);

test.done();
},
};

exports.applyForceLocal = {
withPoint: function(test){
var bodyA = new Body({
mass: 1,
position: [2,3],
angle: Math.PI // rotated 180 degrees
});
bodyA.addShape(new Circle(1));
bodyA.applyForceLocal([-1,0],[0,1]);
test.ok(bodyA.angularForce > 0);
test.ok(bodyA.force[0] > 0);
test.ok(Math.abs(bodyA.force[1]) < 0.001);
test.done();
},
withoutPoint: function(test){
var bodyA = new Body({
mass: 1,
position: [2,3],
angle: Math.PI // rotated 180 degrees
});
bodyA.addShape(new Circle(1));
bodyA.applyForceLocal([-1,0]);
test.equal(bodyA.angularForce, 0);
test.ok(bodyA.force[0] > 0);
test.ok(Math.abs(bodyA.force[1]) < 0.001);
test.done();
}
};

exports.applyImpulse = {
Expand Down

0 comments on commit 28494c1

Please sign in to comment.