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
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.
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.
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.
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)
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]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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
capture.pydrives the page in headless Firefox.viewer.jsreplaces 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.measure.pyfits our own rig to each tick. It renders the model (model.pyis a port ofLimbBend/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.fit.pysmooths each channel over the loop, grounds the emote and writes keyframes.--symmetricremoves 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), pluscompare.py,overlay.pyandsymmetry.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