cannon-es-control
Version:
A lightweight 3D physics engine written in JavaScript with control system tools
95 lines (79 loc) • 3.23 kB
text/typescript
import { PointToPointConstraint } from '../constraints/PointToPointConstraint'
import { RotationalEquation } from '../equations/RotationalEquation'
import { Vec3 } from '../math/Vec3'
import type { Body } from '../objects/Body'
import type { RotationalMotorEquation } from '../equations/RotationalMotorEquation'
export type LockConstraintOptions = ConstructorParameters<typeof LockConstraint>[2]
/**
* Lock constraint. Will remove all degrees of freedom between the bodies.
*/
export class LockConstraint extends PointToPointConstraint {
xA: Vec3
xB: Vec3
yA: Vec3
yB: Vec3
zA: Vec3
zB: Vec3
rotationalEquation1: RotationalEquation
rotationalEquation2: RotationalEquation
rotationalEquation3: RotationalEquation
motorEquation?: RotationalMotorEquation
constructor(
bodyA: Body,
bodyB: Body,
options: {
/**
* The maximum force that should be applied to constrain the bodies.
* @default 1e6
*/
maxForce?: number
} = {}
) {
const maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6
// Set pivot point in between
const pivotA = new Vec3()
const pivotB = new Vec3()
const halfWay = new Vec3()
bodyA.position.vadd(bodyB.position, halfWay)
halfWay.scale(0.5, halfWay)
bodyB.pointToLocalFrame(halfWay, pivotB)
bodyA.pointToLocalFrame(halfWay, pivotA)
// The point-to-point constraint will keep a point shared between the bodies
super(bodyA, pivotA, bodyB, pivotB, maxForce)
// Store initial rotation of the bodies as unit vectors in the local body spaces
this.xA = bodyA.vectorToLocalFrame(Vec3.UNIT_X)
this.xB = bodyB.vectorToLocalFrame(Vec3.UNIT_X)
this.yA = bodyA.vectorToLocalFrame(Vec3.UNIT_Y)
this.yB = bodyB.vectorToLocalFrame(Vec3.UNIT_Y)
this.zA = bodyA.vectorToLocalFrame(Vec3.UNIT_Z)
this.zB = bodyB.vectorToLocalFrame(Vec3.UNIT_Z)
// ...and the following rotational equations will keep all rotational DOF's in place
const r1 = (this.rotationalEquation1 = new RotationalEquation(bodyA, bodyB, options))
const r2 = (this.rotationalEquation2 = new RotationalEquation(bodyA, bodyB, options))
const r3 = (this.rotationalEquation3 = new RotationalEquation(bodyA, bodyB, options))
this.equations.push(r1, r2, r3)
}
/**
* update
*/
update(): void {
const bodyA = this.bodyA
const bodyB = this.bodyB
const motor = this.motorEquation
const r1 = this.rotationalEquation1
const r2 = this.rotationalEquation2
const r3 = this.rotationalEquation3
const worldAxisA = LockConstraint_update_tmpVec1
const worldAxisB = LockConstraint_update_tmpVec2
super.update()
// These vector pairs must be orthogonal
bodyA.vectorToWorldFrame(this.xA, r1.axisA)
bodyB.vectorToWorldFrame(this.yB, r1.axisB)
bodyA.vectorToWorldFrame(this.yA, r2.axisA)
bodyB.vectorToWorldFrame(this.zB, r2.axisB)
bodyA.vectorToWorldFrame(this.zA, r3.axisA)
bodyB.vectorToWorldFrame(this.xB, r3.axisB)
}
}
const LockConstraint_update_tmpVec1 = new Vec3()
const LockConstraint_update_tmpVec2 = new Vec3()