Add a tool that measures emotes from a store's 3D preview #6

Merged
selimaj-dev merged 1 commits from capture-poc into master 2026-09-29 14:59:41 +00:00
Owner

Adds tools/capture, a Python tool that turns an emote shown in a store's 3D skin viewer into Emotecraft JSON our loader reads. The twerk in saturnclientmc/common#10 was made with it.

How it works

  1. capture.py drives the page in headless Firefox. viewer.js replaces the page's clock, so every tick (50 ms) is taken from 10 fixed cameras at the same moment, with a transparent background. A skin we have the texture of goes on the model: a preset, or any username via Mojang.
  2. measure.py fits our own rig to each tick. It renders the model (model.py is a port of LimbBend/PoseApplier, matching Java to 2e-6) and scores outline distance plus colour, with CMA-ES on all cores. It uses a staged first tick, back-to-front twins (flip.py) and anatomy priors. For whole loops it adds rounds held near the loop's smoothed curve, so drift can't build up.
  3. fit.py smooths each channel over the loop, grounds the emote and writes keyframes. --symmetric removes left/right lopsidedness (symmetry.py).

It only measures pixels; it never reads the page's animation data.

Checks: check_port.py (Python port vs the Java classes), synth_test.py (a known answer: our own twerk test animation rendered as a fake capture), plus compare.py, overlay.py and symmetry.py.

Limits (in the README): about 45 min per loop, a keyframe on nearly every tick, and rigs unlike ours only fit approximately. Extreme poses can still land in a wrong answer on the first tick (the synthetic 80° lean does). The real twerk fits at every tick.

🤖 Generated with Claude Code

Adds `tools/capture`, a Python tool that turns an emote shown in a store's 3D skin viewer into Emotecraft JSON our loader reads. The twerk in saturnclientmc/common#10 was made with it. **How it works** 1. `capture.py` drives the page in headless Firefox. `viewer.js` replaces the page's clock, so every tick (50 ms) is taken from 10 fixed cameras at the same moment, with a transparent background. A skin we have the texture of goes on the model: a preset, or any username via Mojang. 2. `measure.py` fits our own rig to each tick. It renders the model (`model.py` is a port of `LimbBend`/`PoseApplier`, matching Java to 2e-6) and scores outline distance plus colour, with CMA-ES on all cores. It uses a staged first tick, back-to-front twins (`flip.py`) and anatomy priors. For whole loops it adds rounds held near the loop's smoothed curve, so drift can't build up. 3. `fit.py` smooths each channel over the loop, grounds the emote and writes keyframes. `--symmetric` removes left/right lopsidedness (`symmetry.py`). It only measures pixels; it never reads the page's animation data. **Checks:** `check_port.py` (Python port vs the Java classes), `synth_test.py` (a known answer: our own twerk test animation rendered as a fake capture), plus `compare.py`, `overlay.py` and `symmetry.py`. **Limits** (in the README): about 45 min per loop, a keyframe on nearly every tick, and rigs unlike ours only fit approximately. Extreme poses can still land in a wrong answer on the first tick (the synthetic 80° lean does). The real twerk fits at every tick. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
selimaj-dev added 1 commit 2026-09-29 14:55:22 +00:00
tools/capture drives a store page's skin viewer in headless Firefox, stepping its clock one tick at
a time and taking every tick from ten fixed cameras. It then fits our own rig to the frames by
rendering the model (a Python port of LimbBend and PoseApplier) and matching outlines and colours,
and writes the result as Emotecraft JSON. It measures pixels only and never reads the page's
animation data. The README covers the steps, the checks and the limits.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
selimaj-dev merged commit 0518a2793a into master 2026-09-29 14:59:41 +00:00
selimaj-dev deleted branch capture-poc 2026-09-29 14:59:46 +00:00
Sign in to join this conversation.