feat(pipeline): grow skirt and hair bone chains for a costume that has none
Miku shipped with 0 cloth chains against Taila's 35, so her twin tails hung off her skull like a helmet. Nothing downstream could fix it: the spring solver simulates cloth BONES, and a garment with none is welded to whatever body bone it was weighted to. Every auto-rigged model is in that state, and her source was an unrigged mesh. tools/cloth_bones.py builds them, which is the job a technical artist does by hand on a model like this. It finds the geometry by MATERIAL SLOT — the artist already answered which surface is hair, and on a joined mesh (what the auto-rig leaves behind) the slot is the only separation left. Hair is split into connected islands, because a strand is a connected piece of surface and clustering by position would merge two ponytails passing near each other. A skirt is split into radial wedges instead, because a skirt is ONE connected surface and islands would return the whole thing as a single piece — the bell-shaped failure. Each clump gets a polyline fitted down its middle by binning vertices by distance and taking centroids, so the chain follows the piece's own curve rather than cutting the corner on a bend, and vertices are re-weighted onto it while the first 22% keeps its original body weight so the scalp stays on the skull. On Miku: 19 chains, 57 bones from one `hair` slot. Sidecar 0 -> 19 chains. Idle stability 0.007-0.018 deg/frame. Mesh intact, verified by render. Opt-in, via `pipeline.py --grow-cloth`, and run before the retarget so describe_rig() finds the chains by name exactly as it would an artist's. Known limits, recorded in the skill: it cannot find a garment sharing a material with the body (Miku's skirt is on her `body` slot, so she got hair and no skirt), and grown chains are a fallback — an artist's chains carry intent that no geometric fit recovers. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4559a1adc3
commit
7892669319
@@ -42,6 +42,10 @@ python tools/pipeline.py --uid <uid> --name <name>
|
||||
|
||||
# From an unrigged mesh — auto-rigs, and accepts the quality loss
|
||||
python tools/pipeline.py --input <mesh.glb> --name <name>
|
||||
|
||||
# Rigged (or auto-rigged) but with NO skirt/hair bones — grow them, or the
|
||||
# costume is welded solid and the spring solver has nothing to simulate
|
||||
python tools/pipeline.py --input <model.glb> --name <name> --rigged --grow-cloth
|
||||
```
|
||||
|
||||
Then, once, so Godot sees the new files:
|
||||
@@ -64,6 +68,7 @@ Blender is required (`BLENDER_PATH`, or auto-found under
|
||||
| Fix unlit/emissive materials | `tools/gltf_fix.py` | Textures surviving import at all |
|
||||
| Resolve bone ROLES, not names | `tools/rig_map.py` | The model's own skeleton |
|
||||
| Rebuild parenting | `retarget.py::rebuild_hierarchy` | Limbs/cloth following the hips |
|
||||
| Grow cloth chains (opt-in) | `tools/cloth_bones.py` | A costume that has no bones being able to move at all |
|
||||
| Subdivide cloth panels | `retarget.py::subdivide_cloth_panels` | A skirt being able to bend at all |
|
||||
| Retarget clips as rest-relative deltas | `retarget.py::retarget_clip` | Limbs not being twisted by foreign bone roll |
|
||||
| Leave cosmetic bones unkeyed | `export_optimize_animation_keep_anim_armature=False` | Physics owning the cloth |
|
||||
@@ -79,6 +84,8 @@ is a list of things that cost a debugging cycle to learn.
|
||||
- **`references/separation.md`** — body vs. garments vs. hair: what must stay
|
||||
separate, how cloth chains are detected and classed, why cloth is never
|
||||
skinned to a leg, and the ZZZ-convention mapping.
|
||||
- **`references/growing-cloth-bones.md`** — what to do when the source has no
|
||||
skirt or hair bones: how the chains are fitted to the geometry and re-weighted.
|
||||
- **`references/rigging.md`** — role resolution, hierarchy rebuild, cloth panel
|
||||
subdivision, twist bones, joint helpers, the retarget maths.
|
||||
- **`references/cloth-and-hair.md`** — the position-based spring solver, its
|
||||
|
||||
Reference in New Issue
Block a user