Skip to content

Commit

Permalink
added Constraint base class
Browse files Browse the repository at this point in the history
  • Loading branch information
schteppe committed Feb 16, 2013
1 parent 123ce91 commit 94455d5
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 133 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ CONSTRAINTS = src/constraints/Equation.js \
src/constraints/ContactEquation.js \
src/constraints/FrictionEquation.js \
src/constraints/RotationalEquation.js \
src/constraints/Constraint.js \
src/constraints/DistanceConstraint.js \
src/constraints/RotationalConstraint.js \
src/constraints/RotationalMotorEquation.js \
src/constraints/HingeConstraint.js \
src/constraints/PointToPointConstraint.js
Expand Down
143 changes: 77 additions & 66 deletions build/cannon.js
Original file line number Diff line number Diff line change
Expand Up @@ -4030,8 +4030,8 @@ CANNON.World.prototype.step = function(dt){
for(var i=0, Nconstraints=constraints.length; i!==Nconstraints; i++){
var c = constraints[i];
c.update();
for(var name in c.equations){
var eq = c.equations[name];
for(var j=0, Neq=c.equations.length; j!==Neq; j++){
var eq = c.equations[j];
solver.addEquation(eq);
}
}
Expand Down Expand Up @@ -5445,7 +5445,31 @@ CANNON.RotationalEquation.prototype.addToWlambda = function(deltalambda){
bj.wlambda.vadd(I.vmult(nixnj).mult(deltalambda),bj.wlambda);
}
};
/*global CANNON:true */

/**
* @class CANNON.Constraint
* @brief Constraint base class
* @author schteppe
* @param CANNON.RigidBody bodyA
* @param CANNON.Vec3 pivotA A point defined locally in bodyA. This defines the offset of axisA.
* @param CANNON.Vec3 axisA an axis that bodyA can rotate around.
* @param CANNON.RigidBody bodyB
* @param CANNON.Vec3 pivotB
* @param CANNON.Vec3 axisB
* @param float maxForce
*/
CANNON.Constraint = function(bodyA,bodyB){
// Equations to be fed to the solver
this.equations = [];
this.bodyA = bodyA;
this.bodyB = bodyB;
};

// Update constraint
CANNON.Constraint.prototype.update = function(){
throw new Error("method update() not implmemented in this Constraint subclass!");
};/**
* @class CANNON.DistanceConstraint
* @brief Constrains two bodies to be at a constant distance from each other.
* @author schteppe
Expand All @@ -5455,15 +5479,17 @@ CANNON.RotationalEquation.prototype.addToWlambda = function(deltalambda){
* @param float maxForce
*/
CANNON.DistanceConstraint = function(bodyA,bodyB,distance,maxForce){
CANNON.Constraint.call(this,bodyA,bodyB);

if(typeof(maxForce)=="undefined" )
maxForce = 1e6;

// Equations to be fed to the solver
var eqs = this.equations = {
normal: new CANNON.ContactEquation(bodyA,bodyB),
};
var eqs = this.equations = [
new CANNON.ContactEquation(bodyA,bodyB), // Just in the normal direction
];

var normal = eqs.normal;
var normal = eqs[0];

normal.minForce = -maxForce;
normal.maxForce = maxForce;
Expand All @@ -5478,36 +5504,7 @@ CANNON.DistanceConstraint = function(bodyA,bodyB,distance,maxForce){
normal.ni.mult( -distance*0.5,normal.rj);
};
};
/*global CANNON:true */

/**
* @class CANNON.RotationalEquation
* @brief Rotational constraint. Works to keep the local vectors orthogonal to each other.
* @author schteppe
* @param CANNON.RigidBody bj
* @param CANNON.Vec3 localVectorInBodyA
* @param CANNON.RigidBody bi
* @param CANNON.Vec3 localVectorInBodyB
* @param float maxForce
*/
CANNON.RotationalConstraint = function(bodyA, localVectorInBodyA, bodyB, localVectorInBodyB, maxForce){
maxForce = maxForce || 1e6;
// Equations to be fed to the solver
var eqs = this.equations = {
rotational: new CANNON.RotationalEquation(bodyA,bodyB),
};

var eq = eqs.rotational;

eq.minForce = -maxForce;
eq.maxForce = maxForce;

// Update
this.update = function(){
bodyA.quaternion.vmult(localVectorInBodyA, eq.ni);
bodyB.quaternion.vmult(localVectorInBodyB, eq.nj);
};
};
CANNON.DistanceConstraint.prototype = new CANNON.Constraint();
/**
* @class CANNON.RotationalMotorEquation
* @brief Rotational motor constraint. Works to keep the relative angular velocity of the bodies to a given value
Expand Down Expand Up @@ -5656,23 +5653,31 @@ CANNON.RotationalMotorEquation.prototype.addToWlambda = function(deltalambda){
* @param float maxForce
*/
CANNON.HingeConstraint = function(bodyA, pivotA, axisA, bodyB, pivotB, axisB, maxForce){
CANNON.Constraint.call(this,bodyA,bodyB);

maxForce = maxForce || 1e6;
var that = this;
// Equations to be fed to the solver
// @todo should be an ordinary array for faster indexing when adding to solver
var eqs = this.equations = {
rotational1: new CANNON.RotationalEquation(bodyA,bodyB),
rotational2: new CANNON.RotationalEquation(bodyA,bodyB),
p2pNormal: new CANNON.ContactEquation(bodyA,bodyB),
p2pTangent1: new CANNON.ContactEquation(bodyA,bodyB),
p2pTangent2: new CANNON.ContactEquation(bodyA,bodyB),
};

var r1 = eqs.rotational1;
var r2 = eqs.rotational2;
var normal = eqs.p2pNormal;
var t1 = eqs.p2pTangent1;
var t2 = eqs.p2pTangent2;
var eqs = this.equations = [
new CANNON.RotationalEquation(bodyA,bodyB), // rotational1
new CANNON.RotationalEquation(bodyA,bodyB), // rotational2
new CANNON.ContactEquation(bodyA,bodyB), // p2pNormal
new CANNON.ContactEquation(bodyA,bodyB), // p2pTangent1
new CANNON.ContactEquation(bodyA,bodyB), // p2pTangent2
];

this.getRotationalEquation1 = function(){ return eqs[0]; };
this.getRotationalEquation2 = function(){ return eqs[1]; };
this.getPointToPointEquation1 = function(){ return eqs[2]; };
this.getPointToPointEquation2 = function(){ return eqs[3]; };
this.getPointToPointEquation3 = function(){ return eqs[4]; };

var r1 = this.getRotationalEquation1();
var r2 = this.getRotationalEquation2();
var normal = this.getPointToPointEquation1();
var t1 = this.getPointToPointEquation2();
var t2 = this.getPointToPointEquation3();
var motor; // not activated by default

t1.minForce = t2.minForce = normal.minForce = -maxForce;
t1.maxForce = t2.maxForce = normal.maxForce = maxForce;
Expand All @@ -5694,14 +5699,16 @@ CANNON.HingeConstraint = function(bodyA, pivotA, axisA, bodyB, pivotB, axisB, ma
this.motorMaxForce = maxForce;
this.enableMotor = function(){
if(!motorEnabled){
eqs.motor = new CANNON.RotationalMotorEquation(bodyA,bodyB,maxForce);
motor = new CANNON.RotationalMotorEquation(bodyA,bodyB,maxForce);
eqs.push(motor);
motorEnabled = true;
}
};
this.disableMotor = function(){
if(motorEnabled){
motorEnabled = false;
delete eqs.motor;
motor = null;
eqs.pop();
}
};

Expand Down Expand Up @@ -5731,15 +5738,15 @@ CANNON.HingeConstraint = function(bodyA, pivotA, axisA, bodyB, pivotB, axisB, ma
bodyB.quaternion.vmult(axisB, r2.nj);

if(motorEnabled){
bodyA.quaternion.vmult(axisA,eqs.motor.axisA);
bodyB.quaternion.vmult(axisB,eqs.motor.axisB);
eqs.motor.targetVelocity = that.motorTargetVelocity;
eqs.motor.maxForce = that.motorMaxForce;
eqs.motor.minForce = that.motorMinForce;
bodyA.quaternion.vmult(axisA,motor.axisA);
bodyB.quaternion.vmult(axisB,motor.axisB);
motor.targetVelocity = that.motorTargetVelocity;
motor.maxForce = that.motorMaxForce;
motor.minForce = that.motorMinForce;
}
};
};
/*global CANNON:true */
CANNON.HingeConstraint.prototype = new CANNON.Constraint();/*global CANNON:true */

/**
* @class CANNON.PointToPointConstraint
Expand All @@ -5750,18 +5757,21 @@ CANNON.HingeConstraint = function(bodyA, pivotA, axisA, bodyB, pivotB, axisB, ma
* @param CANNON.Body bodyB Body that will be constrained in a similar way to the same point as bodyA. We will therefore get sort of a link between bodyA and bodyB. If not specified, bodyA will be constrained to a static point.
* @param CANNON.Vec3 pivotB See pivotA.
* @param float maxForce The maximum force that should be applied to constrain the bodies.
* @extends CANNON.Constraint
*/
CANNON.PointToPointConstraint = function(bodyA,pivotA,bodyB,pivotB,maxForce){
CANNON.Constraint.call(this,bodyA,bodyB);

// Equations to be fed to the solver
var eqs = this.equations = {
normal: new CANNON.ContactEquation(bodyA,bodyB),
tangent1: new CANNON.ContactEquation(bodyA,bodyB),
tangent2: new CANNON.ContactEquation(bodyA,bodyB),
};
var eqs = this.equations = [
new CANNON.ContactEquation(bodyA,bodyB), // Normal
new CANNON.ContactEquation(bodyA,bodyB), // Tangent2
new CANNON.ContactEquation(bodyA,bodyB), // Tangent2
];

var normal = eqs.normal;
var t1 = eqs.tangent1;
var t2 = eqs.tangent2;
var normal = eqs[0];
var t1 = eqs[1];
var t2 = eqs[2];

t1.minForce = t2.minForce = normal.minForce = -maxForce;
t1.maxForce = t2.maxForce = normal.maxForce = maxForce;
Expand All @@ -5780,6 +5790,7 @@ CANNON.PointToPointConstraint = function(bodyA,pivotA,bodyB,pivotB,maxForce){
normal.rj.copy(t2.rj);
};
};
CANNON.PointToPointConstraint.prototype = new CANNON.Constraint();
if (typeof module !== 'undefined') {
// export for node
module.exports = CANNON;
Expand Down
4 changes: 2 additions & 2 deletions build/cannon.min.js

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions src/constraints/Constraint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*global CANNON:true */

/**
* @class CANNON.Constraint
* @brief Constraint base class
* @author schteppe
* @param CANNON.RigidBody bodyA
* @param CANNON.Vec3 pivotA A point defined locally in bodyA. This defines the offset of axisA.
* @param CANNON.Vec3 axisA an axis that bodyA can rotate around.
* @param CANNON.RigidBody bodyB
* @param CANNON.Vec3 pivotB
* @param CANNON.Vec3 axisB
* @param float maxForce
*/
CANNON.Constraint = function(bodyA,bodyB){
// Equations to be fed to the solver
this.equations = [];
this.bodyA = bodyA;
this.bodyB = bodyB;
};

// Update constraint
CANNON.Constraint.prototype.update = function(){
throw new Error("method update() not implmemented in this Constraint subclass!");
};
11 changes: 7 additions & 4 deletions src/constraints/DistanceConstraint.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@
* @param float maxForce
*/
CANNON.DistanceConstraint = function(bodyA,bodyB,distance,maxForce){
CANNON.Constraint.call(this,bodyA,bodyB);

if(typeof(maxForce)=="undefined" )
maxForce = 1e6;

// Equations to be fed to the solver
var eqs = this.equations = {
normal: new CANNON.ContactEquation(bodyA,bodyB),
};
var eqs = this.equations = [
new CANNON.ContactEquation(bodyA,bodyB), // Just in the normal direction
];

var normal = eqs.normal;
var normal = eqs[0];

normal.minForce = -maxForce;
normal.maxForce = maxForce;
Expand All @@ -31,3 +33,4 @@ CANNON.DistanceConstraint = function(bodyA,bodyB,distance,maxForce){
normal.ni.mult( -distance*0.5,normal.rj);
};
};
CANNON.DistanceConstraint.prototype = new CANNON.Constraint();
51 changes: 31 additions & 20 deletions src/constraints/HingeConstraint.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,31 @@
* @param float maxForce
*/
CANNON.HingeConstraint = function(bodyA, pivotA, axisA, bodyB, pivotB, axisB, maxForce){
CANNON.Constraint.call(this,bodyA,bodyB);

maxForce = maxForce || 1e6;
var that = this;
// Equations to be fed to the solver
// @todo should be an ordinary array for faster indexing when adding to solver
var eqs = this.equations = {
rotational1: new CANNON.RotationalEquation(bodyA,bodyB),
rotational2: new CANNON.RotationalEquation(bodyA,bodyB),
p2pNormal: new CANNON.ContactEquation(bodyA,bodyB),
p2pTangent1: new CANNON.ContactEquation(bodyA,bodyB),
p2pTangent2: new CANNON.ContactEquation(bodyA,bodyB),
};
var eqs = this.equations = [
new CANNON.RotationalEquation(bodyA,bodyB), // rotational1
new CANNON.RotationalEquation(bodyA,bodyB), // rotational2
new CANNON.ContactEquation(bodyA,bodyB), // p2pNormal
new CANNON.ContactEquation(bodyA,bodyB), // p2pTangent1
new CANNON.ContactEquation(bodyA,bodyB), // p2pTangent2
];

this.getRotationalEquation1 = function(){ return eqs[0]; };
this.getRotationalEquation2 = function(){ return eqs[1]; };
this.getPointToPointEquation1 = function(){ return eqs[2]; };
this.getPointToPointEquation2 = function(){ return eqs[3]; };
this.getPointToPointEquation3 = function(){ return eqs[4]; };

var r1 = eqs.rotational1;
var r2 = eqs.rotational2;
var normal = eqs.p2pNormal;
var t1 = eqs.p2pTangent1;
var t2 = eqs.p2pTangent2;
var r1 = this.getRotationalEquation1();
var r2 = this.getRotationalEquation2();
var normal = this.getPointToPointEquation1();
var t1 = this.getPointToPointEquation2();
var t2 = this.getPointToPointEquation3();
var motor; // not activated by default

t1.minForce = t2.minForce = normal.minForce = -maxForce;
t1.maxForce = t2.maxForce = normal.maxForce = maxForce;
Expand All @@ -51,14 +59,16 @@ CANNON.HingeConstraint = function(bodyA, pivotA, axisA, bodyB, pivotB, axisB, ma
this.motorMaxForce = maxForce;
this.enableMotor = function(){
if(!motorEnabled){
eqs.motor = new CANNON.RotationalMotorEquation(bodyA,bodyB,maxForce);
motor = new CANNON.RotationalMotorEquation(bodyA,bodyB,maxForce);
eqs.push(motor);
motorEnabled = true;
}
};
this.disableMotor = function(){
if(motorEnabled){
motorEnabled = false;
delete eqs.motor;
motor = null;
eqs.pop();
}
};

Expand Down Expand Up @@ -88,11 +98,12 @@ CANNON.HingeConstraint = function(bodyA, pivotA, axisA, bodyB, pivotB, axisB, ma
bodyB.quaternion.vmult(axisB, r2.nj);

if(motorEnabled){
bodyA.quaternion.vmult(axisA,eqs.motor.axisA);
bodyB.quaternion.vmult(axisB,eqs.motor.axisB);
eqs.motor.targetVelocity = that.motorTargetVelocity;
eqs.motor.maxForce = that.motorMaxForce;
eqs.motor.minForce = that.motorMinForce;
bodyA.quaternion.vmult(axisA,motor.axisA);
bodyB.quaternion.vmult(axisB,motor.axisB);
motor.targetVelocity = that.motorTargetVelocity;
motor.maxForce = that.motorMaxForce;
motor.minForce = that.motorMinForce;
}
};
};
CANNON.HingeConstraint.prototype = new CANNON.Constraint();
Loading

0 comments on commit 94455d5

Please sign in to comment.