verlet-constraint
Version:
a single constraint, useful in a verlet system
70 lines (59 loc) • 2.34 kB
JavaScript
module.exports = function(vec) {
var delta = vec.create()
var scaled = vec.create()
function Constraint(points, opt) {
if (!points || points.length !== 2)
throw new Error('two points must be specified for the constraint')
if (!points[0].position || !points[1].position)
throw new Error('must specify verlet-point or similar, with { position }')
this.points = points
this.stiffness = 1.0
if (opt && typeof opt.stiffness === 'number')
this.stiffness = opt.stiffness
if (opt && typeof opt.restingDistance === 'number')
this.restingDistance = opt.restingDistance
else
this.restingDistance = vec.distance(this.points[0].position, this.points[1].position)
}
Constraint.prototype.solve = function() {
//distance formula
var p1 = this.points[0],
p2 = this.points[1],
p1vec = p1.position,
p2vec = p2.position,
p1mass = typeof p1.mass === 'number' ? p1.mass : 1,
p2mass = typeof p2.mass === 'number' ? p2.mass : 1
vec.sub(delta, p1vec, p2vec)
var d = Math.sqrt(vec.dot(delta, delta))
//ratio for resting distance
var restingRatio = d===0 ? this.restingDistance : (this.restingDistance - d) / d
var scalarP1,
scalarP2
//handle zero mass a little differently
if (p1mass == 0 && p2mass == 0) {
scalarP1 = 0
scalarP2 = 0
} else if (p1mass == 0 && p2mass > 0) {
scalarP1 = 0
scalarP2 = this.stiffness
} else if (p1mass > 0 && p2mass == 0) {
scalarP1 = this.stiffness
scalarP2 = 0
} else {
//invert mass quantities
var im1 = 1.0 / p1mass
var im2 = 1.0 / p2mass
scalarP1 = (im1 / (im1 + im2)) * this.stiffness
scalarP2 = this.stiffness - scalarP1
}
//push/pull based on mass
vec.scale(scaled, delta, scalarP1 * restingRatio)
vec.add(p1vec, p1vec, scaled)
vec.scale(scaled, delta, scalarP2 * restingRatio)
vec.sub(p2vec, p2vec, scaled)
return d
}
return function(p1, p2, opt) {
return new Constraint(p1, p2, opt)
}
}