cannon-es-control
Version:
A lightweight 3D physics engine written in JavaScript with control system tools
91 lines (75 loc) • 2.73 kB
text/typescript
import { Constraint } from '../constraints/Constraint'
import { ContactEquation } from '../equations/ContactEquation'
import { Vec3 } from '../math/Vec3'
import type { Body } from '../objects/Body'
/**
* Connects two bodies at given offset points.
* @example
* const bodyA = new Body({ mass: 1 })
* const bodyB = new Body({ mass: 1 })
* bodyA.position.set(-1, 0, 0)
* bodyB.position.set(1, 0, 0)
* bodyA.addShape(shapeA)
* bodyB.addShape(shapeB)
* world.addBody(bodyA)
* world.addBody(bodyB)
* const localPivotA = new Vec3(1, 0, 0)
* const localPivotB = new Vec3(-1, 0, 0)
* const constraint = new PointToPointConstraint(bodyA, localPivotA, bodyB, localPivotB)
* world.addConstraint(constraint)
*/
export class PointToPointConstraint extends Constraint {
/**
* Pivot, defined locally in bodyA.
*/
pivotA: Vec3
/**
* Pivot, defined locally in bodyB.
*/
pivotB: Vec3
equationX: ContactEquation
equationY: ContactEquation
equationZ: ContactEquation
/**
* @param pivotA The point relative to the center of mass of bodyA which bodyA is constrained to.
* @param bodyB Body that will be constrained in a similar way to the same point as bodyA. We will therefore get a link between bodyA and bodyB. If not specified, bodyA will be constrained to a static point.
* @param pivotB The point relative to the center of mass of bodyB which bodyB is constrained to.
* @param maxForce The maximum force that should be applied to constrain the bodies.
*/
constructor(
bodyA: Body,
pivotA = new Vec3(),
bodyB: Body,
pivotB = new Vec3(),
maxForce = 1e6
) {
super(bodyA, bodyB)
this.pivotA = pivotA.clone()
this.pivotB = pivotB.clone()
const x = (this.equationX = new ContactEquation(bodyA, bodyB))
const y = (this.equationY = new ContactEquation(bodyA, bodyB))
const z = (this.equationZ = new ContactEquation(bodyA, bodyB))
// Equations to be fed to the solver
this.equations.push(x, y, z)
// Make the equations bidirectional
x.minForce = y.minForce = z.minForce = -maxForce
x.maxForce = y.maxForce = z.maxForce = maxForce
x.ni.set(1, 0, 0)
y.ni.set(0, 1, 0)
z.ni.set(0, 0, 1)
}
update(): void {
const bodyA = this.bodyA
const bodyB = this.bodyB
const x = this.equationX
const y = this.equationY
const z = this.equationZ
// Rotate the pivots to world space
bodyA.quaternion.vmult(this.pivotA, x.ri)
bodyB.quaternion.vmult(this.pivotB, x.rj)
y.ri.copy(x.ri)
y.rj.copy(x.rj)
z.ri.copy(x.ri)
z.rj.copy(x.rj)
}
}