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) } }