cannon-es-control
Version:
A lightweight 3D physics engine written in JavaScript with control system tools
131 lines (110 loc) • 3.8 kB
text/typescript
import { PointToPointConstraint } from '../constraints/PointToPointConstraint'
import { ConeEquation } from '../equations/ConeEquation'
import { RotationalEquation } from '../equations/RotationalEquation'
import { Vec3 } from '../math/Vec3'
import type { Body } from '../objects/Body'
export type ConeTwistConstraintOptions = ConstructorParameters<typeof ConeTwistConstraint>[2]
/**
* A Cone Twist constraint, useful for ragdolls.
*/
export class ConeTwistConstraint extends PointToPointConstraint {
/**
* The axis direction for the constraint of the body A.
*/
axisA: Vec3
/**
* The axis direction for the constraint of the body B.
*/
axisB: Vec3
/**
* The aperture angle of the cone.
*/
angle: number
/**
* The twist angle of the joint.
*/
twistAngle: number
coneEquation: ConeEquation
twistEquation: RotationalEquation
constructor(
bodyA: Body,
bodyB: Body,
options: {
/**
* The pivot point for bodyA.
*/
pivotA?: Vec3
/**
* The pivot point for bodyB.
*/
pivotB?: Vec3
/**
* The axis direction for the constraint of the body A.
*/
axisA?: Vec3
/**
* The axis direction for the constraint of the body B.
*/
axisB?: Vec3
/**
* The aperture angle of the cone.
* @default 0
*/
angle?: number
/**
* The twist angle of the joint.
* @default 0
*/
twistAngle?: number
/**
* The maximum force that should be applied to constrain the bodies.
* @default 1e6
*/
maxForce?: number
/**
* Wether to collide the connected bodies or not.
* @default false
*/
collideConnected?: boolean
} = {}
) {
const maxForce = typeof options.maxForce !== 'undefined' ? options.maxForce : 1e6
// Set pivot point in between
const pivotA = options.pivotA ? options.pivotA.clone() : new Vec3()
const pivotB = options.pivotB ? options.pivotB.clone() : new Vec3()
super(bodyA, pivotA, bodyB, pivotB, maxForce)
this.axisA = options.axisA ? options.axisA.clone() : new Vec3()
this.axisB = options.axisB ? options.axisB.clone() : new Vec3()
this.collideConnected = !!options.collideConnected
this.angle = typeof options.angle !== 'undefined' ? options.angle : 0
const c = (this.coneEquation = new ConeEquation(bodyA, bodyB, options))
const t = (this.twistEquation = new RotationalEquation(bodyA, bodyB, options))
this.twistAngle = typeof options.twistAngle !== 'undefined' ? options.twistAngle : 0
// Make the cone equation push the bodies toward the cone axis, not outward
c.maxForce = 0
c.minForce = -maxForce
// Make the twist equation add torque toward the initial position
t.maxForce = 0
t.minForce = -maxForce
this.equations.push(c, t)
}
update(): void {
const bodyA = this.bodyA
const bodyB = this.bodyB
const cone = this.coneEquation
const twist = this.twistEquation
super.update()
// Update the axes to the cone constraint
bodyA.vectorToWorldFrame(this.axisA, cone.axisA)
bodyB.vectorToWorldFrame(this.axisB, cone.axisB)
// Update the world axes in the twist constraint
this.axisA.tangents(twist.axisA, twist.axisA)
bodyA.vectorToWorldFrame(twist.axisA, twist.axisA)
this.axisB.tangents(twist.axisB, twist.axisB)
bodyB.vectorToWorldFrame(twist.axisB, twist.axisB)
cone.angle = this.angle
twist.maxAngle = this.twistAngle
}
}
const ConeTwistConstraint_update_tmpVec1 = new Vec3()
const ConeTwistConstraint_update_tmpVec2 = new Vec3()