Joints
Connecting bodies with the Joint constraint — ball-sockets, hinges, sliders, welds, and world anchors.
A Joint connects two bodies — or a body and the world — and removes degrees of freedom between them. One configurable constraint expresses the whole joint taxonomy: it has six independent degrees of freedom (3 linear, 3 angular), each of which can be locked, free, limited, sprung, or motorised. The named helpers below pick the right combination for you.
Anatomy
A joint holds an anchor frame on each body coincident according to its per-DOF rules:
entityA/entityB— the two bodies. SetentityB = JOINT_WORLDto anchor body A to a fixed point in the world instead of a second body.localAnchorA/localAnchorB— the anchor point on each body, in that body’s local frame. WhenentityB === JOINT_WORLD,localAnchorBis a world coordinate.localBasisA/localBasisB— the orientation of the joint’s reference frame on each body (unit quaternions, identity by default). The locked/free/limited axes are this frame’s axes — so for a hinge you orient the frame so its free axis is the hinge axis.
Register a joint with the PhysicsSystem once both bodies exist; remove it with unlink_joint:
import { Joint, JOINT_WORLD } from "@woosh/meep-engine/src/engine/physics/ecs/Joint.js";
const joint = new Joint(); // default: ball-socket
joint.entityA = linkA;
joint.entityB = linkB;
joint.localAnchorA.set(0, -0.3, 0); // bottom of A
joint.localAnchorB.set(0, 0.3, 0); // top of B
physics.link_joint(joint);
Joint types
Each helper configures the six DOFs and returns the joint, so you can chain. They’re the standard joints expressed as DOF patterns:
| Helper | DOFs | Use for |
|---|---|---|
asBallSocket() (default) | 3 linear locked, 3 angular free | chains, ropes, pendulums |
asHinge(axis) | 3 linear + 2 angular locked, 1 angular free | doors, wheels, elbows |
asPrismatic(axis) | 2 linear + 3 angular locked, 1 linear free | sliders, pistons, lifts |
asWeld() | all 6 locked | rigidly fuse two bodies |
asConeTwist(twistLo, twistHi, swingY, swingZ?) | 3 linear locked, 3 angular limited | ragdoll shoulders / hips |
For hinges and sliders, orient localBasisA / localBasisB so the free frame axis is the one you want.
Anchoring to the world
entityB = JOINT_WORLD pins body A to a fixed world point. A pendulum is one ball-socket to the world:
const pivot = new Joint();
pivot.entityA = bob;
pivot.entityB = JOINT_WORLD;
pivot.localAnchorA.set(0, 1, 0); // top of the bob, in its frame
pivot.localAnchorB.set(0, 5, 0); // fixed world point to hang from
physics.link_joint(pivot);
Chains
Wire a column of bodies anchor-to-anchor — bottom of each link to the top of the next — and pin the first to the world, and you have a rope or chain. The solver runs extra iterations on joints (physics.jointIterations) so impulses propagate the length of the chain in a single tick. See the Jointed chains example, which hangs four of them and sweeps a kinematic log through.
Beyond locked DOFs
Locking and freeing DOFs covers the rigid joints above. The same Joint also gives each DOF a limit, spring, or motor — end-stops, suspension, powered hinges. Those live on the Constraints page.
Where to go next
- Constraints — per-DOF limits, springs, and motors on a joint.
- Rigid bodies — the bodies a joint connects.
- Jointed chains — a live demo built on ball-socket joints.