Physics

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. Set entityB = JOINT_WORLD to 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. When entityB === JOINT_WORLD, localAnchorB is 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";
import { v3_set } from "@woosh/meep-engine/src/core/geom/vec3/v3_set.js";

const joint = new Joint();              // default: ball-socket
joint.entityA = linkA;
joint.entityB = linkB;
v3_set(joint.localAnchorA, 0, 0, -0.3, 0);     // bottom of A
v3_set(joint.localAnchorB, 0, 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:

HelperDOFsUse for
asBallSocket() (default)3 linear locked, 3 angular freechains, ropes, pendulums
asHinge(axis)3 linear + 2 angular locked, 1 angular freedoors, wheels, elbows
asPrismatic(axis)2 linear + 3 angular locked, 1 linear freesliders, pistons, lifts
asWeld()all 6 lockedrigidly fuse two bodies
asConeTwist(twistLo, twistHi, swingY, swingZ?)3 linear locked, 3 angular limitedragdoll shoulders / hips

For hinges and sliders, orient localBasisA / localBasisB so the free frame axis is the one you want. Anchors are three-element Float64Arrays; basis quaternions are four-element arrays in [x, y, z, w] order. Use v3_set for anchors and v4_set (from src/core/geom/vec4/v4_set.js) for bases, or copy an existing indexed vector with .set(vector).

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;
v3_set(pivot.localAnchorA, 0, 0, 1, 0);        // top of the bob, in its frame
v3_set(pivot.localAnchorB, 0, 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