File: src/equations/ContactEquation.js
module.exports = ContactEquation;
var Equation = require('./Equation');
var Vec3 = require('../math/Vec3');
var Mat3 = require('../math/Mat3');
/**
* Contact/non-penetration constraint equation
* @class ContactEquation
* @constructor
* @author schteppe
* @param {Body} bodyA
* @param {Body} bodyB
* @extends Equation
*/
function ContactEquation(bodyA, bodyB, maxForce){
maxForce = typeof(maxForce) !== 'undefined' ? maxForce : 1e6;
Equation.call(this, bodyA, bodyB, 0, maxForce);
/**
* @property restitution
* @type {Number}
*/
this.restitution = 0.0; // "bounciness": u1 = -e*u0
/**
* World-oriented vector that goes from the center of bi to the contact point.
* @property {Vec3} ri
*/
this.ri = new Vec3();
/**
* World-oriented vector that starts in body j position and goes to the contact point.
* @property {Vec3} rj
*/
this.rj = new Vec3();
/**
* Contact normal, pointing out of body i.
* @property {Vec3} ni
*/
this.ni = new Vec3();
}
ContactEquation.prototype = new Equation();
ContactEquation.prototype.constructor = ContactEquation;
var ContactEquation_computeB_temp1 = new Vec3(); // Temp vectors
var ContactEquation_computeB_temp2 = new Vec3();
var ContactEquation_computeB_temp3 = new Vec3();
ContactEquation.prototype.computeB = function(h){
var a = this.a,
b = this.b,
bi = this.bi,
bj = this.bj,
ri = this.ri,
rj = this.rj,
rixn = ContactEquation_computeB_temp1,
rjxn = ContactEquation_computeB_temp2,
vi = bi.velocity,
wi = bi.angularVelocity,
fi = bi.force,
taui = bi.torque,
vj = bj.velocity,
wj = bj.angularVelocity,
fj = bj.force,
tauj = bj.torque,
penetrationVec = ContactEquation_computeB_temp3,
GA = this.jacobianElementA,
GB = this.jacobianElementB,
n = this.ni;
// Caluclate cross products
ri.cross(n,rixn);
rj.cross(n,rjxn);
// g = xj+rj -(xi+ri)
// G = [ -ni -rixn ni rjxn ]
n.negate(GA.spatial);
rixn.negate(GA.rotational);
GB.spatial.copy(n);
GB.rotational.copy(rjxn);
// Calculate the penetration vector
penetrationVec.copy(bj.position);
penetrationVec.vadd(rj,penetrationVec);
penetrationVec.vsub(bi.position,penetrationVec);
penetrationVec.vsub(ri,penetrationVec);
var g = n.dot(penetrationVec);
// Compute iteration
var ePlusOne = this.restitution + 1;
var GW = ePlusOne * vj.dot(n) - ePlusOne * vi.dot(n) + wj.dot(rjxn) - wi.dot(rixn);
var GiMf = this.computeGiMf();
var B = - g * a - GW * b - h*GiMf;
return B;
};
var ContactEquation_getImpactVelocityAlongNormal_vi = new Vec3();
var ContactEquation_getImpactVelocityAlongNormal_vj = new Vec3();
var ContactEquation_getImpactVelocityAlongNormal_xi = new Vec3();
var ContactEquation_getImpactVelocityAlongNormal_xj = new Vec3();
var ContactEquation_getImpactVelocityAlongNormal_relVel = new Vec3();
/**
* Get the current relative velocity in the contact point.
* @method getImpactVelocityAlongNormal
* @return {number}
*/
ContactEquation.prototype.getImpactVelocityAlongNormal = function(){
var vi = ContactEquation_getImpactVelocityAlongNormal_vi;
var vj = ContactEquation_getImpactVelocityAlongNormal_vj;
var xi = ContactEquation_getImpactVelocityAlongNormal_xi;
var xj = ContactEquation_getImpactVelocityAlongNormal_xj;
var relVel = ContactEquation_getImpactVelocityAlongNormal_relVel;
this.bi.position.vadd(this.ri, xi);
this.bj.position.vadd(this.rj, xj);
this.bi.getVelocityAtWorldPoint(xi, vi);
this.bj.getVelocityAtWorldPoint(xj, vj);
vi.vsub(vj, relVel);
return this.ni.dot(relVel);
};