d1030def4e
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>
422 lines
19 KiB
HTML
422 lines
19 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Ariki — How We Make Clothes in Marvelous Designer</title>
|
||
<style>
|
||
:root {
|
||
color-scheme: dark;
|
||
--ink: #f4efe6;
|
||
--muted: #a9a396;
|
||
--gold: #d9a66c;
|
||
--aqua: #72d5cb;
|
||
--rose: #e08585;
|
||
--line: rgba(255,255,255,.12);
|
||
--panel: rgba(18, 24, 27, .92);
|
||
}
|
||
* { box-sizing: border-box; }
|
||
body {
|
||
margin: 0;
|
||
padding: 2rem clamp(1rem, 4vw, 3rem) 5rem;
|
||
color: var(--ink);
|
||
background:
|
||
radial-gradient(circle at 90% 0%, rgba(67,139,132,.22), transparent 28rem),
|
||
#0b1113;
|
||
font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
|
||
line-height: 1.6;
|
||
}
|
||
.eyebrow {
|
||
color: var(--gold);
|
||
font: 700 .75rem/1 ui-monospace, Menlo, monospace;
|
||
letter-spacing: .14em;
|
||
text-transform: uppercase;
|
||
}
|
||
h1 {
|
||
margin: .4rem 0 1.2rem;
|
||
font-size: clamp(2rem, 5vw, 3.6rem);
|
||
letter-spacing: -.04em;
|
||
line-height: 1.05;
|
||
max-width: 20ch;
|
||
}
|
||
h2 {
|
||
margin: 3rem 0 .8rem;
|
||
font-size: 1.25rem;
|
||
color: var(--aqua);
|
||
letter-spacing: -.01em;
|
||
}
|
||
h3 { margin: 1.8rem 0 .5rem; font-size: 1rem; color: var(--gold); }
|
||
p { max-width: 60rem; margin: 0 0 1rem; }
|
||
p.lede { color: var(--muted); font-size: 1.1rem; max-width: 56rem; margin: 0 0 1.5rem; }
|
||
ul, ol { max-width: 60rem; padding-left: 1.2rem; }
|
||
li { margin: .35rem 0; }
|
||
a { color: var(--aqua); }
|
||
code {
|
||
font: .88em/1.4 ui-monospace, Menlo, monospace;
|
||
background: rgba(255,255,255,.07);
|
||
padding: .12em .4em;
|
||
border-radius: .3rem;
|
||
}
|
||
strong { color: #fff; }
|
||
.wrap {
|
||
overflow-x: auto;
|
||
border: 1px solid var(--line);
|
||
border-radius: 1rem;
|
||
background: var(--panel);
|
||
margin: 1rem 0 1.5rem;
|
||
}
|
||
table { width: 100%; border-collapse: collapse; min-width: 640px; font-size: .92rem; }
|
||
th, td { padding: .8rem 1rem; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
|
||
th {
|
||
color: var(--gold);
|
||
font: 700 .7rem/1.2 ui-monospace, Menlo, monospace;
|
||
letter-spacing: .08em;
|
||
text-transform: uppercase;
|
||
background: rgba(0,0,0,.25);
|
||
}
|
||
tr:last-child td { border-bottom: 0; }
|
||
.num { font: .9rem ui-monospace, Menlo, monospace; color: var(--aqua); white-space: nowrap; }
|
||
figure { margin: 1.5rem 0; }
|
||
figure img {
|
||
max-width: 100%;
|
||
height: auto;
|
||
border: 1px solid var(--line);
|
||
border-radius: 1rem;
|
||
display: block;
|
||
background: #111;
|
||
}
|
||
figcaption { color: var(--muted); font-size: .88rem; margin-top: .6rem; max-width: 52rem; }
|
||
.shots { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); gap: 1.5rem; }
|
||
.shots figure { margin: 0; }
|
||
.flow {
|
||
border: 1px solid var(--line);
|
||
border-radius: 1rem;
|
||
background: var(--panel);
|
||
padding: 1.2rem 1.4rem;
|
||
overflow-x: auto;
|
||
margin: 1rem 0 1.5rem;
|
||
}
|
||
.flow pre {
|
||
margin: 0;
|
||
font: .82rem/1.7 ui-monospace, Menlo, monospace;
|
||
color: var(--ink);
|
||
white-space: pre;
|
||
}
|
||
.callout {
|
||
border-left: 3px solid var(--gold);
|
||
background: rgba(217,166,108,.08);
|
||
padding: .9rem 1.2rem;
|
||
border-radius: 0 .6rem .6rem 0;
|
||
margin: 1.2rem 0;
|
||
max-width: 60rem;
|
||
}
|
||
.callout.warn { border-left-color: var(--rose); background: rgba(224,133,133,.09); }
|
||
.callout p:last-child { margin-bottom: 0; }
|
||
.meta { color: var(--muted); font-size: .85rem; border-top: 1px solid var(--line); margin-top: 3.5rem; padding-top: 1.2rem; }
|
||
hr { border: 0; border-top: 1px solid var(--line); margin: 3rem 0 0; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<p class="eyebrow">Ariki · Clothing lane · For humans</p>
|
||
<h1>How we make clothes in Marvelous Designer</h1>
|
||
|
||
<p class="lede">
|
||
We build Ariki's garments as <strong>real sewn cloth</strong> — flat pattern pieces, stitched
|
||
along seams, dropped onto Lena's actual game body and simulated until they hang. Nothing is
|
||
sculpted by hand. This page explains what we've made, how the process runs, and the things
|
||
that took us a long time to learn.
|
||
</p>
|
||
|
||
<figure>
|
||
<img src="../tools/tailor/screenshots/lena_kapahaka_outfit_v3.png"
|
||
alt="Lena in a red, black and white tāniko bodice with a flax-coloured piupiu skirt, arms out in T-pose.">
|
||
<figcaption>
|
||
The kapa haka outfit, v3 — a tāniko-patterned pari (bodice) over a piupiu (flax skirt), draped
|
||
on the game body inside Marvelous Designer. Both the tāniko diamonds and the flax strand
|
||
banding are textures we generated from reference photos, not painted by hand.
|
||
</figcaption>
|
||
</figure>
|
||
|
||
<h2>The short version</h2>
|
||
|
||
<p>
|
||
Clothing runs on a two-stage lane. Marvelous Designer is the <strong>upstream</strong> half — it
|
||
answers "what is this garment, and what shape is it on <em>our</em> body?" A headless Blender
|
||
pipeline is the <strong>downstream</strong> half — it answers "how does the game wear it?"
|
||
They meet at a garment mesh.
|
||
</p>
|
||
|
||
<div class="flow"><pre>reference photo ──▶ [ MARVELOUS DESIGNER ] ──▶ garment mesh (FBX/OBJ)
|
||
or concept draft · drape · texture 1.2k–4.7k verts, already fitted
|
||
measure · screenshot + .zprj editable source
|
||
│
|
||
▼
|
||
[ clothing/garment_pipeline.py — headless Blender ]
|
||
census · prepare · fit · reduce · skin · export
|
||
│
|
||
▼
|
||
ariki-game/assets/quaternius/outfits/<set>/
|
||
per-slot GLB on the shared 65-bone skeleton</pre></div>
|
||
|
||
<p>
|
||
The upstream half needs a human to start each session. The downstream half is fully automatic.
|
||
</p>
|
||
|
||
<figure>
|
||
<img src="../clothing/kapahaka_ingame_dance_2026-07-31.png"
|
||
alt="The same tāniko bodice and piupiu skirt on an animated character in the game's clothing test bed.">
|
||
<figcaption>
|
||
The same two garments after the downstream half, worn in-game in the Clothing Test Bed and
|
||
playing an animation. Note the piupiu clipping through the left thigh — that is the kind of
|
||
defect the downstream <code>fit</code> stage's clearance shell exists to prevent, and it is
|
||
why we review in the test bed rather than trusting the MD render.
|
||
</figcaption>
|
||
</figure>
|
||
|
||
<h2>How a garment actually gets made</h2>
|
||
|
||
<p>Six steps. Every one of them produces numbers that the next one is checked against.</p>
|
||
|
||
<h3>1 · Take the reference apart</h3>
|
||
<p>
|
||
Before drafting anything, the reference image is deconstructed into a worksheet: which body slot
|
||
each piece belongs to, where it's anchored, where its edges should sit in metres, and how much
|
||
ease (slack) it needs. Every downstream number traces back to a row of that worksheet. Skipping
|
||
this step is how early garments shipped <strong>4–14 cm off target</strong>.
|
||
</p>
|
||
|
||
<h3>2 · Draft from Lena's measurements, not a size chart</h3>
|
||
<p>
|
||
Lena is stylized. Her card reads roughly <span class="num">108 – 67 – 109 cm</span> with
|
||
<span class="num">72 cm</span> thighs on a <span class="num">178 cm</span> frame. Real-world
|
||
size charts produce clothes that simply do not fit her. The measurements are extracted straight
|
||
off the game mesh by a script that slices it at known heights
|
||
(<code>tools/tailor/measure_body.py</code>), so they describe the body the game actually renders.
|
||
</p>
|
||
|
||
<h3>3 · Build from blocks, not freehand</h3>
|
||
<p>
|
||
We have parametric <em>blocks</em> — a fitted top, an A-line skirt, a strand/fringe skirt — that
|
||
turn worksheet numbers into a runnable pattern. You give it the band height, hem height and ease;
|
||
it emits the panel outlines, the seam pairing and the arrangement rules with the known fixes
|
||
already baked in. Hand-typing point lists is how the early mistakes happened.
|
||
</p>
|
||
|
||
<h3>4 · Drape it on the body</h3>
|
||
<p>
|
||
The flat panels get arrangement points on the avatar (shoulders, waist, skirt front/back), then
|
||
the cloth simulates onto her. The sequence matters more than the settings:
|
||
</p>
|
||
<ul>
|
||
<li><strong>Stiffen the fabric for the whole settle, relax only at the end.</strong> Soft cloth
|
||
from frame zero rolls into a bunch at the waist.</li>
|
||
<li><strong>Apply waist elastic mid-settle, never from the start.</strong> Elastic applied before
|
||
the cloth has wrapped cinches the garment off one hip.</li>
|
||
<li><strong>Bottoms stay up by tension, not elastic</strong> — cut the waist smaller than the hips
|
||
and let the fabric stretch hold it.</li>
|
||
<li><strong>One garment per scene.</strong> A second garment, even frozen, grabs and inverts the
|
||
new one. Outfits are assembled at the very end from finished pieces.</li>
|
||
</ul>
|
||
|
||
<h3>5 · Judge the fit by numbers, not by eye</h3>
|
||
<div class="callout">
|
||
<p>
|
||
This is the step that was missing at the start, and it matters most. Early drapes were accepted
|
||
because they <em>looked like clothing</em>. They were bunched around the middle.
|
||
</p>
|
||
</div>
|
||
<p>
|
||
Now every drape is measured. A script (<code>qc_placement.py</code>) reads the render, separates
|
||
background from skin from garment, calibrates pixels-to-metres off Lena's known 1.777 m height,
|
||
and reports where each garment band's top and bottom actually sit — against a target table pulled
|
||
from the reference photo. For the kapa haka outfit that table was: pari top at
|
||
<span class="num">1.31 m ±3 cm</span> (above the bust), pari hem and piupiu waist at
|
||
<span class="num">1.05 m ±3 cm</span>, piupiu hem at <span class="num">0.45 m ±4 cm</span>
|
||
(below the knee). We iterate until it's inside tolerance.
|
||
</p>
|
||
<p>
|
||
Every shipped garment also gets a screenshot committed to
|
||
<code>tools/tailor/screenshots/</code>, front <em>and</em> back. That's how the work gets reviewed
|
||
without anyone opening Marvelous Designer.
|
||
</p>
|
||
|
||
<h3>6 · Export four ways</h3>
|
||
<div class="wrap">
|
||
<table>
|
||
<thead><tr><th>File</th><th>Why we keep it</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><code>.zprj</code></td><td>The editable source of truth. Opens in MD normally. Regenerating a variant from this always beats re-authoring.</td></tr>
|
||
<tr><td><code>.fbx</code></td><td>What the downstream Blender pipeline consumes.</td></tr>
|
||
<tr><td><code>.obj</code></td><td>Plain-text backup, and the only reliable way to measure the mesh (see below).</td></tr>
|
||
<tr><td><code>.zpac</code></td><td>For assembling multi-piece outfits later.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<h2>The unusual part: we drive MD with code</h2>
|
||
|
||
<p>
|
||
Marvelous Designer has an embedded Python API. We wrote a small plugin that opens a socket inside
|
||
MD (<code>TinqsMDBridge</code>), so a script on the outside can send it commands — create these
|
||
panels, sew this edge to that one, simulate 250 frames, render the viewport to a PNG.
|
||
</p>
|
||
<p>
|
||
<strong>The whole method is a vision loop</strong>: draft, drape, render, look at the image,
|
||
measure it, adjust, repeat. That's what makes it possible to iterate a garment dozens of times in
|
||
an afternoon.
|
||
</p>
|
||
|
||
<div class="callout warn">
|
||
<p>
|
||
<strong>Two things to know if you're sitting at the machine.</strong> MD's embedded Python
|
||
can't run in the background, so the bridge takes over the main thread: <strong>a human has to
|
||
click Plugin → TinqsMDBridge to start a session</strong>, and <strong>MD's window freezes for
|
||
the whole session</strong> — "Not Responding" is normal, not a crash. Ending the session with
|
||
<code>python tools/md_bridge.py --stop</code> gives the UI straight back. If you want to look at
|
||
the model yourself, we stop the session first.
|
||
</p>
|
||
</div>
|
||
|
||
<p>
|
||
None of this locks the work up. The <code>.zprj</code> files are ordinary MD projects — open them,
|
||
edit patterns, re-drape, re-export by hand any time. The bridge is just how the automation drives
|
||
the same buttons.
|
||
</p>
|
||
|
||
<h2>What we've made so far</h2>
|
||
|
||
<p>
|
||
Authored on and after 2026-07-30. Vertex counts are the exported garment mesh.
|
||
</p>
|
||
|
||
<div class="wrap">
|
||
<table>
|
||
<thead><tr><th>Garment</th><th>What it is</th><th>Versions</th><th class="num">Verts</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Tee</td><td>First test — fitted top block</td><td>v1</td><td class="num">2,335</td></tr>
|
||
<tr><td>Skirt</td><td>First test — A-line block, the most forgiving garment</td><td>v1</td><td class="num">1,988</td></tr>
|
||
<tr><td>Pari</td><td>Kapa haka bodice, tāniko pattern</td><td>v1 → v4</td><td class="num">1,406</td></tr>
|
||
<tr><td>Piupiu</td><td>Kapa haka flax skirt, strand block</td><td>v1 → v3</td><td class="num">3,022</td></tr>
|
||
<tr><td>Cape</td><td>Shoulder garment</td><td>v1, v2</td><td class="num">4,664</td></tr>
|
||
<tr><td>Kapa haka outfit</td><td>Pari + piupiu assembled together</td><td>v1 → v3</td><td class="num">—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="callout">
|
||
<p>
|
||
<strong>Our own garments are far cheaper than downloaded ones.</strong> These export at
|
||
<span class="num">1.2k–4.7k</span> verts. The downloaded MD dress the clothing pipeline was
|
||
first piloted on was <span class="num">2.49 million</span> verts / 110 MB. So the brutal
|
||
<em>reduce</em> stage downstream is mostly unnecessary for our work — and because they were
|
||
draped on the real game body, they arrive already fitted.
|
||
</p>
|
||
</div>
|
||
|
||
<h2>Textiles do more work than tailoring</h2>
|
||
|
||
<p>
|
||
For traditional wear, garment identity lives in the <strong>pattern</strong>, not the cut. Kapa
|
||
haka, Mexica and Pacific garments are largely rectangles and simple blocks. So we model the shape
|
||
simply and spend the effort on the cloth: <code>taniko.png</code> (concentric woven diamonds) and
|
||
<code>piupiu.png</code> (flax strands with geometric banding) are both generated procedurally from
|
||
reference photos, and both are reusable.
|
||
</p>
|
||
<p>
|
||
One non-obvious control: in MD, <strong>a PNG's DPI sets its physical size on the cloth</strong>.
|
||
1024 px at 54.2 dpi is 480 mm of fabric. You tile a motif by changing the DPI, not by scaling the
|
||
image.
|
||
</p>
|
||
|
||
<h2>Things that cost us hours</h2>
|
||
|
||
<div class="wrap">
|
||
<table>
|
||
<thead><tr><th>What happens</th><th>Why</th></tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>The garment drapes <strong>upside-down over her head</strong> and tangles</td>
|
||
<td>In MD's 2D pattern window, <strong>y+ is UP in 3D</strong>. Panels drafted y-down come out inverted. It looks exactly like a seam bug and isn't — seven iterations were lost to this once.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>A strapless top <strong>slides down to the underbust</strong></td>
|
||
<td>Cloth falls to the narrowest catch. MD doesn't simulate <em>putting a garment on</em> — it materialises the cloth where you arranged it. Add straps; it fixes placement and coverage at once.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>The garment <strong>slides off the shoulders</strong> or twists partly inside out</td>
|
||
<td>Seam pairing. Panels drafted as identical copies offset sideways are <em>not</em> mirrored, and need the opposite flip setting from mirrored ones.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Everything in the scene <strong>changes colour at once</strong></td>
|
||
<td>Fabric slot 0 is the shared default. Colouring it dyes every garment. Always add a new fabric.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>A defect ships because <strong>nobody saw the back</strong></td>
|
||
<td>MD's snapshot camera has no rear view at all — bottom, front, ¾, sides, top, and that's it. Four separate defects shipped through this blind spot before we started using turntable renders for the back.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>A busy texture <strong>hides folds and inside-out panels</strong></td>
|
||
<td>Judge shape with the texture off: cloth renders white on its front face and grey on its back, so a grey patch seen from outside is inside out and a white streak is a fold.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="callout">
|
||
<p>
|
||
<strong>The one diagnostic that unsticks everything:</strong> render the scene right after
|
||
arranging the panels but with <em>zero</em> simulation frames. That shows where the cloth
|
||
actually starts, before physics muddies the picture. Reach for it the moment a drape
|
||
misbehaves.
|
||
</p>
|
||
</div>
|
||
|
||
<h2>What doesn't work yet</h2>
|
||
|
||
<ul>
|
||
<li>
|
||
<strong>Trousers and shorts are unsolved.</strong> Two-panel construction with a crotch notch
|
||
twists every time — fabric can't thread between Lena's touching thighs, and every seam
|
||
configuration has been tried. The next idea is four panels arranged on the per-leg points, so
|
||
the cloth starts already wrapped around each thigh.
|
||
</li>
|
||
<li>
|
||
<strong>The placement measurement is honest but crude.</strong> It counts the body's baked-in
|
||
underwear and the floor shadow as garment. Fine for band positions; needs per-garment colour
|
||
masks when precision matters.
|
||
</li>
|
||
<li>
|
||
<strong>MD's AI Image Generator and EveryWear are GUI-only</strong> — they can't be scripted, so
|
||
they're outside this workflow entirely.
|
||
</li>
|
||
</ul>
|
||
|
||
<h2>Where everything lives</h2>
|
||
|
||
<div class="wrap">
|
||
<table>
|
||
<thead><tr><th>Path</th><th>What's there</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><code>tools/tailor/</code></td><td>The garment workshop: per-garment recipes, the parametric blocks, Lena's measurement card, QC scripts, generated textures, and every shipped <code>.zprj</code>/<code>.fbx</code>/<code>.obj</code></td></tr>
|
||
<tr><td><code>tools/tailor/screenshots/</code></td><td>The review renders — start here to see what exists</td></tr>
|
||
<tr><td><code>tools/md_bridge.py</code> + <code>tools/md_bridge/</code></td><td>The socket bridge into MD, and a dump of MD's real API surface (688 functions, introspected — the published docs are thin and several signatures in them are wrong)</td></tr>
|
||
<tr><td><code>clothing/</code></td><td>The downstream half: garment mesh → game-ready skinned GLB</td></tr>
|
||
<tr><td><code>.claude/skills/marvelous-designer/</code></td><td>The full operating playbook, written for whoever (or whatever) is driving</td></tr>
|
||
<tr><td><code>.agents/wiki/architecture/clothing-lane.md</code></td><td>How the two halves fit together</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<hr>
|
||
<p class="meta">
|
||
Animation repo · <code>.humans/marvelous-designer.html</code> · written 2026-08-06.<br>
|
||
Everything here was learned by doing it, and verified against Marvelous Designer 2026 Personal on
|
||
the PC. If a detail here disagrees with the playbook in
|
||
<code>.claude/skills/marvelous-designer/</code>, the playbook is the source of truth — this page
|
||
is the explanation, not the spec.
|
||
</p>
|
||
|
||
</body>
|
||
</html>
|