Two pieces of work.
1. Keep milestones, not steps. Staged NN_*.py lanes were saving a full
~80 MB .blend per attempt, so Lena's lane reached 3.0 GB of which 2.2 GB
was 30 .blend files -- five snapshots to land one crotch fix, five more
for the bra. The .py recipes are the real history; the blends are cache.
- .agents/rules/working-files.md: four-tier policy (KEEP / MASTER /
SCRATCH / UNKNOWN) + how to work a lane.
- tools/prune_lane.py: classifies a lane and prunes the scratch tier.
Dry-run by default. Reads a per-lane .lanekeep manifest, flags
binaries byte-identical to a registered original (canonical name
always survives a duplicate pair), and never auto-deletes a .blend
with no step script beside it -- those cannot be rebuilt.
- .gitignore: scratch patterns can never be committed.
Dry run on characters/female/lena_nude reports 2.3 GB reclaimable.
Not applied -- that lane had a live Blender session at the time.
2. .humans/marvelous-designer.html: how we author garments in Marvelous
Designer, written for people rather than agents -- the six-step process,
what has been made, the traps that cost hours, and what is still
unsolved. Matches the .humans/ HTML convention in ariki-game.
Also committing the docs the AGENTS.md knowledge map and the new page
reference, so they are not dangling: the clothing-lane architecture page,
the marvelous-designer skill, and the two screenshots the page embeds.
characters/ is deliberately untracked and stays that way -- it holds GBs of
blends and GLBs, and .gitattributes does not LFS-track .blend.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 KiB
Deconstruction — taking a reference apart like a tailor
Companion to ../SKILL.md. That file is drafting/draping doctrine; this file is
the step before it: how to read a clothing image (or description) and take the
garment apart into pieces our MD lane can actually build. Skipping this step is
how garments shipped 4–14 cm off their own targets — the drafting was fine, the
analysis had never been written down.
The output is a worksheet of numbers, not geometry. Panel point lists come
last, and mostly from tools/tailor/blocks.py, not by hand.
0. The worksheet (output contract)
Fill this in full before asking for a bridge session. Every number the drape and QC stages use traces back to a row here.
| # | Item | Feeds |
|---|---|---|
| 1 | Slot split — which separate garments is this outfit? | one config per garment |
| 2 | Per garment: class + block choice | blocks.py function |
| 3 | Anchoring — what holds it up | construction + arrangement |
| 4 | Placement targets — each edge's z ± tol vs landmarks | expect.bands (gate G1) |
| 5 | Edge circumference + ease table | panel widths, taper |
| 6 | Piece list + seam plan | md.panels / md.seams |
| 7 | Textile plan — what is texture, not geometry | texture generation |
| 8 | Fabric read — weight/stiffness | .zfab choice + sim recipe |
| 9 | Risks — unsolved/untested features | scope call before starting |
blocks.py turns rows 2–5 into a config skeleton (md block + expect.bands)
in one call. If no block fits, hand-draft under tooling.md §3 rules (named
landmarks, computed line indices) — never freehand a point list.
1. Split the outfit into garments by slot
The game wears per-slot parts (Body, Legs, …) and MD drapes one garment per scene — a second garment, even frozen, grabs and inverts the new one. So a "dress over leggings with a belt" reference is three worksheets, three configs, three drape sessions. Decide the split first:
- One garment per clothing slot it occupies. A dress is one garment (Body slot, or whatever slot spans it) even though it covers both regions.
- Belts, sashes, armbands: texture if flat against the host garment; separate garment only if they hang or swing.
- Outfit photos are assembled at the end from finished
.zpacs (SKILL.md "Outfit assembly") — never co-draped.
2. Anchoring — decide what holds it up before what it looks like
Anchoring determines construction more than silhouette does. MD materialises cloth at the arrangement point and does not simulate donning, so nothing "slides into place".
| What the image shows | Anchor | Construction consequence |
|---|---|---|
| Straps, sleeves, or a shoulder line | shoulder-hung | bodice block; straps reach shoulder_z or the garment settles at the underbust |
| Strapless top | (unreliable) | add straps anyway — a tube slides to the narrowest catch; straps also cover the body's baked-in bra straps |
| Skirt/trousers at waist or hip | waist tension | cut the waist smaller than the hips (0.90–0.92 × hip circ) and let stretch hold it; elastic only mid-settle, never frame 0 |
| Light/gappy garment (strands, fringe, open weave) | arrangement itself | arrangement height is the placement — a light band stays exactly where arranged |
Always check what the anchor must cover: the target body has baked-in
underwear, and any neckline or scoop that drops below it reads as the garment
failing. Check the back neckline explicitly — the reference photo almost
never shows it, ExportSnapshot3D cannot show it (tooling.md §1.1), and that
blind spot has shipped defects. If the image doesn't show the back, decide the
back (scoop depth, coverage) and write it on the worksheet rather than letting it
default.
3. Read the seams, then discard most of them
A real tailor's deconstruction finds every seam. Ours finds them and then collapses almost all of them, because the MD lane sews whole edges only, has no darts, and garment identity for our targets is mostly textiles (SKILL.md). Translation table:
| Feature in the image | Our move |
|---|---|
| Side seams, shoulder seams | keep — these are the block's real seams |
| Darts (bust, waist) | no darts. Taper the panel side edges + stretch ease carries the shaping |
| Princess seams, yokes | collapse into the panel; if visible, draw them in the texture |
| Waistband | merge into the panel top; separate band only for strand/fringe skirts |
| Set-in sleeves | untested — no sleeve block yet; treat as scope risk (row 9) |
| Collars, hoods | untested/unsolved — same |
| Trousers/shorts crotch | unsolved (failure catalogue); next approach is 4 panels on the per-leg points |
| Plackets, buttons, zips, pockets, topstitching | texture, always |
| Gathers, pleats, ruffles | texture unless the silhouette depends on them |
| Fringe / strands / fur edge | teeth cut into the panel outline (comb panel), never partial seams |
| Belt/sash flat against the garment | texture |
The test for "geometry or texture?": does it change the silhouette or the edge positions? If not, it's texture.
4. Placement targets — numbers before points
Extract where every garment edge sits before drafting anything. This is the step that was skipped when shipped garments landed 3.9–14 cm off targets that existed only as prose.
Landmark card for the current body (tools/tailor/lena_measurements.json,
regenerate per body with measure_body.py; metres, floor = 0):
| Landmark | z | Landmark | z |
|---|---|---|---|
| top of head | 1.777 | hip (widest) / crotch | 0.946 |
| neck base | 1.457 | thigh | 0.865 |
| shoulder | 1.397 | knee | 0.517 |
| chest (bust) | 1.264 | ankle | 0.106 |
| waist | 1.089 |
Method, per garment edge (top of band, hem, waistline…):
- Find the edge in the image relative to the two nearest visible landmarks (e.g. "hem lands mid-thigh, about ⅓ of the knee→hip span above the knee").
- Interpolate a z from the card. The body is stylized — always place against these landmarks, never against real-world garment-length conventions.
- Assign a tolerance: ±3 cm for fitted edges, ±4 cm for free-hanging hems.
- Write the rows into
expect.bands— gate G1 measures every drape against them from then on.
Sanity anchor (proven): a pari band 1.31→1.05 m and piupiu 1.05→0.45 m came from exactly this read of the kapa haka reference.
5. Ease — how much bigger than the body
For each horizontal edge, the panel width comes from the body circumference at that z plus ease. Interpolate circumference linearly between the card's (z, circ) pairs — neck 0.392, chest 1.083, waist 0.675, hip 1.095 — and never interpolate below the hip (the legs bifurcate; a slice there measures nonsense).
| Fit read from the image | Total ease | Proven case |
|---|---|---|
| Snug / bandeau / activewear | +15–20 mm | pari: 1100 vs 1083 bust |
| Regular fitted top | +90–100 mm | tee: 1180 vs 1083 bust |
| Loose / drapey | +150 mm and up | (untested above ~150) |
| Bottoms waist edge | negative: 0.90–0.92 × hip circ | piupiu: 1000 vs 1095 hip |
Bottoms are the inversion to internalise: the waist edge is cut smaller than the hips it must pass over, because tension is the anchor (§2).
6. Vertical spans are 1:1
Pattern millimetres map 1:1 to world metres — drape shrinkage is negligible for our fabrics. So:
- panel cloth height =
(top_z − hem_z) × 1000 - a shoulder-hung garment's straps must reach the shoulder: total panel height
=
(shoulder_z − hem_z) × 1000, and the front scoop depth is what's left between strap top and the visible band top:scoop = panel_h − (band_top_z − hem_z) × 1000.
Proof this math is the real one: it reproduces all three shipped garments — tee 480 (shoulder 1.397 → hip-ish hem 0.917), pari 350/scoop 105 (shoulder → waist 1.05, band top 1.30), piupiu 600 (1.05 → 0.45).
7. Blocks — what we can build today
| Garment class | Block | Status |
|---|---|---|
| Tank / tee / fitted bodice / bandeau-with-straps | blocks.fitted_top |
proven (tee, pari) |
| A-line / straight skirt | blocks.aline_skirt |
proven (skirt, piupiu v2) |
| Strand / fringe skirt (piupiu, hula, fur trim) | blocks.strand_skirt |
proven construction (comb outline), parameters per garment |
| Dress | fitted_top + skirt geometry in one panel pair |
untested — try taper-through-waist first |
| Trousers / shorts | — | unsolved; next: 4 panels on Leg_Front_L/R, Leg_Back_L/R |
| Sleeves, collars, hoods | — | untested; scope risk |
| Capes / cloaks / rectangles (traditional wear) | plain panels | rectangles + blocks; identity is the textile |
Every block bakes in the expensive discoveries — seam parity for identical-offset panels, the arrangement-x rules per point family, bodice taper, tension waists, strengthen/relax sim recipes — so prefer a block over a hand-typed point list even when the block needs post-editing. Generate, then edit the config, not the other way round.
8. Textiles carry the identity
For traditional wear especially (kapa haka, Mexica, Pacific), the garment reads
as itself because of the textile, not the cut. Spend the effort there:
generate the pattern procedurally (PIL), set physical size via DPI
(dpi = px / (mm / 25.4)), and keep the generator script — motifs recur.
Model the shape as simply as the silhouette allows.
9. Fabric read → sim plan
From the image, judge weight and stiffness, then pick levers (tooling.md §4):
- Stiffness ladder (
.zfabpresets):V2_Woven_Canvas_1<V2_Woven_Denim_1<V2_Non-Fabric_Tyvek_1.fabric_apihas no physics setters — the.zfabis the stiffness choice. - Fully-sewn sides → strengthen through the whole settle, relax at the end. Under-constrained (half-sewn sides, thin straps) → don't strengthen (it rotates the garment); remove surplus cloth instead.
- Light/gappy →
SetParticleDistanceOfPattern~20 mm and remember §2: arrangement height is placement. - Skin-tight →
SetAddlThicknessCollisiona few mm before the settle.
10. Worked example — the kapa haka reference, as this method
What was done by trial and error in 2026-07-30/31, restated as the worksheet:
| Row | Pari (bodice) | Piupiu (skirt) |
|---|---|---|
| Slot | Body | Legs |
| Class/block | bandeau → fitted_top |
strand skirt → strand_skirt (v2 shipped as aline_skirt) |
| Anchoring | photo shows strapless → straps anyway (covers bra straps, fixes height) | waist tension, 1000 vs 1095 hip; light strands → arrangement = placement |
| Targets | band top 1.31 ±0.03, hem 1.05 ±0.03 | waist 1.05 ±0.03, hem 0.45 ±0.04 (below knee) |
| Ease | snug: +17 mm over bust | waist 0.91 × hip |
| Seam plan | shoulders + sides; scoop/armholes in outline | band side edges only; strands are outline teeth |
| Textile | tāniko band → generated taniko.png, DPI-sized to span once |
flax strands + geometric banding → piupiu.png |
| Fabric | default sim fabric, strengthen full settle | default, strengthen + (v3) elastic mid-settle |
| Risks | back neckline never visible in photo — decided, then verified via turntable | hem vs leg-swing envelope (skirt bones downstream) |
The lesson the example carries: nothing in the finished configs is a guess.
Every number is a worksheet row, and every worksheet row is checkable — by G1
against the render, or by GetLineLength against the drafted panel.