Tap a leg in the scene to focus it. The faint blue chain is stage 1 (folded to the right length); the solid leg is stage 2 (that fold aimed at the diamond target).
This page is about one idea for single-chain inverse kinematics — placing the end of a jointed chain (a foot) on a target — from a 2026 thread by Kiaran Ritchie. Instead of solving the whole positional problem at once, split it in two:
- Length. Configure the chain's internal joints so the straight-line distance from the root (hip) to the end (foot) equals the distance from the hip to the target. Direction does not matter yet — the objective is a single number.
- Direction. Rotate the whole solved chain about its root so its hip→foot vector points at the target. One rigid rotation, applied at the base.
If the chain can reach the target distance, and then that reach is aimed at the target, the foot lands on the target. A coupled 2-D problem becomes a scalar reach followed by one rotation.
Stage 1 — solve the length
The length stage asks only: make |foot − hip| = |target − hip|. Here each leg has three
segments and folds by a single curl angle shared across its joints — a uniform arc. As the curl
increases the foot folds in, so the reach decreases monotonically; as it straightens, the
reach grows to the sum of the segment lengths. That makes the length solve a one-dimensional, monotone
root-find: bisect the curl until the squared reach meets the squared target distance. No
derivative, and — because it compares squared lengths — no square root in the loop.
A target nearer than the most-folded pose or farther than full extension is outside the reachable interval; the solver clamps to the nearest end and flags it (the foot turns red and detaches from the ground). Shorten the legs below and watch the feet start to clamp on the deeper ground.
Stage 2 — aim the chain
Now the chain has the right reach but points the wrong way. The fix is a single rotation about the hip that
turns the current hip→foot direction onto the hip→target direction. In this side view the chain bends
in one plane, so that "from-to" rotation is exact and needs no trigonometry: with the solved end vector
E and the target vector D, the rotation's cosine is (E·D)/(|E||D|) and
its sine is (E×D)/(|E||D|) — one dot, one cross, normalised once. Baking that rotation into every
joint gives the final pose. Turn on "show the two stages": the faint blue
chain is the length-only pose before aiming; the solid leg is it after the single hip rotation.
per-leg solve, live from wasm memory · curl is the stage-1 answer, aim is the stage-2 rotation
Why it can look natural
All the gross aiming happens in one rotation at the base joint — the hip or shoulder. That is how many animal limbs move: a ball-like hip swings the whole leg, and the segments past it mostly shape the reach. Watch the spider: the feet are pinned to the ground while the body rides over them, and each leg's big motion is a swing at the hip, not a thrash of the lower joints.
The body also carries its weight: it pitches to lean into the ground's grade and rocks with a subtle step-synced sway and bob, rather than gliding along as a level slab. Because the hips ride on the body, every leg re-solves as it leans — the constant small adjustment you see is the IK keeping each planted foot exactly where it was put.
What the spider is doing
The body walks at a constant speed; a distance-based gait keeps two alternating groups of legs (a diagonal tetrapod) stepping so the body is always supported. A planted foot stays fixed on the terrain in the world while the body moves — that is what stretches the chain and gives the IK something to solve — and a swinging foot arcs to its next foothold, lifting just high enough to clear whatever is between (so it steps over a riser or block). The ground is rough on purpose: flat treads with vertical risers (stair steps) plus a few sharp flat-topped obstacles — still a pure, seamless-looping function of x (it stores nothing). Every foothold sits at a different height, so each leg reaches a different distance and folds to a different shape.
The rig follows a real spider: the legs mount on the cephalothorax (front) — the big abdomen behind carries none — and each leg arches up to a high knee then tapers to a thin foot, because the legs are longer than the reach and the length stage folds them. The middle legs are drawn shorter, as they would foreshorten pointing sideways in a real spider.
The feet always land on the surface and the body always rides clear of the ground beneath it — checked by a sweep over the whole terrain (see the tests). The length+direction solve isn't collision-aware, so a lower leg can dip into a step; the ground is drawn in front of the legs, so — as in any side-scroller — that dip is simply hidden, and a leg is never seen under the ground.
tunables · all integer subcells (256 = one cell). Shrink segment length to force clamping; raise stride for longer steps.
How it is built (and what is real)
Everything in the scene is computed in integer fixed point inside a small WebAssembly module — no floats until the GPU, which is float hardware. Angles index a baked Q14 cosine table; positions are subcells; the only square roots are the handful used to normalise an aim and to report a length. The simulation is fully separate from rendering and wasm, so the solver runs natively under test with no browser or GPU. The numbers in the table above are read straight out of the module's memory each frame.
This is the method specialised to the plane, which is what makes the two stages so clean: the internal pose is one scalar and the aim is one angle. The full 3-D method generalises both — the "from-to" becomes a quaternion, and a bend-plane / pole vector chooses among the many internal poses that hit a given reach (here that choice is the fixed bend side per leg). It is a solver architecture, strongest for limb-like, root-dominant chains; long necks, spines and contact-rich cases need more on top.
Built to the rules in data-oriented-design.md. Source: ik.c · gait.c · sim.c · render.c · terrain.c · wasm.c · test.c · README.