UNPKG

cannon

Version:

A lightweight 3D physics engine written in JavaScript.

136 lines (108 loc) 3.81 kB
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); };