---
title: "From Wildlife Video to 49-Bone WebGL2 Rigs: How Field Notes 01 Works"
slug: "reverse-engineering-49-bone-motion-rigs"
date: "2026-10-18"
author: "Taylor Amarel"
category: "3D Skeletal Animation & Biomechanics"
reading_time: "9 min read"
canonical_url: "https://blog.tayloramarel.com/posts/reverse-engineering-49-bone-motion-rigs.html"
markdown_url: "https://blog.tayloramarel.com/posts/reverse-engineering-49-bone-motion-rigs.md"
paper_pdf: "https://papers.tayloramarel.com/With_vs_Without_Baltor_Single_File_3D_Fox_Survival_Game_Animations_and_LongForm_Prompts_2026.pdf"
evaluation_portal: "https://compare.baltor.ai/motion"
summary: "Extracting spine waves, footfall phase locks, and inverse kinematics from reference motion into a zero-dependency browser runtime."
---

# From Wildlife Video to 49-Bone WebGL2 Rigs: How Field Notes 01 Works

**By Taylor Amarel** · 2026-10-18 · 3D Skeletal Animation & Biomechanics · 9 min read  
*Related Paper:* [https://papers.tayloramarel.com/With_vs_Without_Baltor_Single_File_3D_Fox_Survival_Game_Animations_and_LongForm_Prompts_2026.pdf](https://papers.tayloramarel.com/With_vs_Without_Baltor_Single_File_3D_Fox_Survival_Game_Animations_and_LongForm_Prompts_2026.pdf) · *Live Benchmark:* [https://compare.baltor.ai/motion](https://compare.baltor.ai/motion)

---

When you prompt an unassisted language model to animate a four-legged animal in Three.js or WebGL, you get the same output almost every time: five primitive boxes or cylinders for the torso and legs, driven by a single out-of-phase sine wave (`legFL.rotation.x = Math.sin(t); legFR.rotation.x = -Math.sin(t);`). The spine stays as stiff as a wooden plank, the paws skate across the ground because horizontal velocity is decoupled from stride length, and the knees bend in the wrong anatomical direction. To show what happens when an agent harness grounds motion in real biomechanical observations and a 49-bone skeletal rig, we built **Field Notes 01** and the **2x2 Motion Microscope** ([demos.baltor.ai/foxglade-motion](https://demos.baltor.ai/foxglade-motion) and [compare.baltor.ai/motion](https://compare.baltor.ai/motion)).

This article walks through our four-stage pipeline for reverse-engineering natural quadruped locomotion from wildlife reference video into a zero-dependency 60 FPS WebGL2 procedural animation engine.

### Stage 1: Extracting 17-Joint RTMPose Trajectories from Wildlife Video

Rather than asking an LLM to guess how a red fox (*Vulpes vulpes*) moves, Part 1 (Observation) of our harness starts with real reference footage of a red fox transitioning from an alert walk to a diagonal trot and a full rotary gallop. Using an AP-10K animal pose estimation model (RTMPose-m trained on 17 quadruped anatomical landmarks: nose, eyes, root of neck, shoulders, elbows/wrists, hips, stifles/hocks, paws, and tail base), we extract 2D frame-by-frame keypoint trajectories normalized by torso length (withers-to-pelvis distance).

Raw frame-by-frame pose detector outputs contain high-frequency jitter around occluded rear paws. We pass the raw 17-joint trajectories through a 3rd-order Savitzky-Golay filter to obtain smooth position, velocity, and acceleration curves, and then extract three invariant biomechanical parameters across gait speeds:

  - **Hildebrand Footfall Phase Offsets (`phi_i in [0, 1)`) and Duty Factors (`beta`):** The exact fraction of the stride cycle each paw spends in stance phase (planted on the ground) versus swing phase (lifted forward), plus the phase lag of Front-Right (FR), Hind-Left (HL), and Hind-Right (HR) relative to Front-Left (FL).
  - **Sagittal Spine Flexion-Extension Harmonic:** During a rotary gallop, a fox's lumbar and thoracic spine flexes deeply when the hind legs gather under the belly and extends by up to 24 degrees when the forelegs reach forward. Without this sagittal spine wave, high-speed running looks mechanical and truncated.
  - **Multi-Link Tail Phase Propagation:** The tail acts as a dynamic angular-momentum counterbalance during sharp turns and leaps, following a traveling sinusoidal wave where each distal tail bone lags its parent by `delta_phi = 0.65 radians`.

### Stage 2: Continuous Hildebrand Gait Blending Without Foot Skating

A real fox does not snap discontinuously between static animation clips. As ground speed `v` increases from `0.0 m/s` to `9.5 m/s`, both the stride frequency `f(v)` and the inter-limb phase vector shift continuously:

  - **Four-Beat Walk (`0.2 - 2.2 m/s`, duty factor `beta = 0.68`):** Lateral sequence `[FL: 0.00, HL: 0.25, FR: 0.50, HR: 0.75]`. At least two or three paws remain planted on the terrain at every instant.
  - **Two-Beat Diagonal Trot (`2.2 - 5.2 m/s`, duty factor `beta = 0.48`):** Diagonal pairs move in phase lock `[FL: 0.00, FR: 0.50, HL: 0.50, HR: 0.00]` with a brief suspension phase.
  - **Rotary Gallop / Bound (`5.2 - 9.5 m/s`, duty factor `beta = 0.34`):** Lead and trail forelimbs strike in rapid succession `[FL: 0.00, FR: 0.14]`, followed by aerial suspension and hindlimb drive `[HL: 0.52, HR: 0.66]` accompanied by full sagittal spine flexion.

To eliminate foot skating completely, the horizontal foot target displacement during the stance phase (`0 <= p < beta`) is locked directly to the integral of ground speed over stance duration, while the swing phase (`beta <= p < 1`) follows a cycloidal arc of height `h_step` with a forward ankle pitch kick on liftoff.

### Empirical Comparison: 4-View Motion Microscope Metrics

In our **2x2 Motion Microscope** ([demos.baltor.ai/foxglade-motion](https://demos.baltor.ai/foxglade-motion)), we render four synchronized orthographic and perspective viewports (Side Sagittal Profile, Top Dorsal Spine View, Front Stride Alignment, and 3/4 Interactive Orbit with live bone-angle telemetry) and compare four progressively richer harness rigs:

| Animation Rig Arm (compare.baltor.ai/motion) | Active Joint DOFs | Foot Skate Error (cm / stride) | Sagittal Spine / Tail Energy | Slope Paw Plant Accuracy | Human Realism Win Rate (Blind A/B) |
| --- | --- | --- | --- | --- | --- |
| Arm M0: Raw LLM Sine-Wave Boxes | 4 (1-DOF stiff limbs) | 41.8 cm (Severe Skate) | 0.0 deg (Rigid Plank) | 12.0% (Clips hills) | 4.5% |
| Arm M1: Static GLB Clip Loop Only | 49 bones (Fixed clip) | 19.4 cm (Speed mismatch) | 11.2 deg (Unblended) | 28.5% (No terrain IK) | 22.0% |
| Arm M2: Hildebrand Phase + Spine Wave | 49 bones + procedural spine | 2.1 cm | 22.8 deg (Harmonic lock) | 64.0% (Root pitch only) | 78.5% |
| Arm M3: Full Field Notes 01 (RTMPose + 2-Bone IK) | 49 bones + 4-Limb IK + Fur | 0.3 cm (Phase-Locked) | 24.1 deg + Banking | 99.2% (Barycentric IK) | 95.5% |

### Stage 3 & 4: Two-Bone Analytical Limb IK and Traveling Tail Harmonics

How do we drive a 49-bone CC0 `SkinnedMesh` rig in Three.js at 60 FPS without shipping a heavy external physics engine? First, we cache rest-pose local quaternions and bone lengths for every vertebra, neck joint, tail segment, and limb chain (`upper_arm -> fore_arm -> hand -> paw`). Second, on every frame, we compute the terrain height under each of the four paws, solve a fast analytical Law-of-Cosines two-bone Inverse Kinematics (IK) system for the shoulder/hip and elbow/hock angles, and layer additive sagittal flexion and banking twists across the spine and tail:

```
export function solveQuadrupedLimbAndSpineStep(rig, gaitState, terrainSampler, dt) {
  const { speed, turnRate, phase } = gaitState;
  const gallopBlend = Math.min(1.0, Math.max(0.0, (speed - 4.2) / 3.5));
  const dutyFactor = 0.66 - 0.30 * gallopBlend;

  // 1. Sagittal spine wave (flexes on hind gather, extends on fore reach)
  const spineWave = Math.sin(phase * Math.PI * 2.0) * (0.06 + 0.18 * gallopBlend);
  rig.spineBones.forEach((bone, i) => {
    const segPhase = phase * Math.PI * 2.0 - i * 0.42;
    bone.rotation.x = bone.userData.restRx + Math.sin(segPhase) * spineWave;
    bone.rotation.z = bone.userData.restRz - turnRate * 0.14; // Centripetal bank
  });

  // 2. Five-segment traveling tail counterbalance wave
  rig.tailBones.forEach((tailBone, idx) => {
    const lag = phase * Math.PI * 2.0 - idx * 0.65;
    tailBone.rotation.x = tailBone.userData.restRx + Math.cos(lag) * (0.12 + 0.15 * gallopBlend);
    tailBone.rotation.y = tailBone.userData.restRy + Math.sin(lag) * 0.16 - turnRate * 0.22;
  });

  // 3. Per-limb Hildebrand stance/swing trajectory + Law-of-Cosines 2-Bone IK
  for (const limb of rig.limbs) {
    const p = (phase + limb.phaseOffset) % 1.0;
    const isStance = p < dutyFactor;
    const u = isStance ? (p / dutyFactor) : ((p - dutyFactor) / (1.0 - dutyFactor));
    const strideX = isStance
      ? (0.5 - u) * limb.strideLength
      : (-0.5 + u) * limb.strideLength;
    const liftY = isStance ? 0.0 : Math.sin(u * Math.PI) * limb.stepHeight;

    const worldTarget = limb.computeWorldFootTarget(strideX, liftY, terrainSampler);
    applyTwoBoneLawOfCosinesIK(limb.upperBone, limb.lowerBone, limb.pawBone, worldTarget);
  }
}
```

### Inspect the Live 49-Bone Rig and Field Notes

By packaging the RTMPose trajectory priors, Hildebrand phase tables, and 2-bone IK solver into a reusable component on our `skeletal_locomotion_3d` engine slot, any downstream scene can instantiate a natural, terrain-grounded quadruped in 12 lines of code instead of asking an LLM to reinvent biomechanics in a single prompt. Open [Field Notes 01 & the 2x2 Motion Microscope (demos.baltor.ai/foxglade-motion)](https://demos.baltor.ai/foxglade-motion) or compare Without vs. With Baltor side by side at [compare.baltor.ai/motion](https://compare.baltor.ai/motion).
