Files
zwitschi f6bb2b1de3
Full build / Import + headless tests (push) Successful in 41s
Full build / Full desktop build + optional release (push) Skipped
Prepare the modular part intake: inventory, extract, verify, join and the part contract
2026-11-06 18:54:08 +01:00
..

Quaternius modular parts

Build inputs for outfit, hair and accessory variety. Committed like the three whole-body sources, so build works from a fresh checkout without the upstream pack.

Where they come from

The upstream Ultimate Modular Characters pack is distributed as a Google Drive folder (https://drive.google.com/drive/folders/1USAAquX2JJWuA2m6zol0KUkFe3UkZ8zX, CC0 1.0). It cannot be fetched reproducibly by a script, so the owner downloads it once into the gitignored tmp/quaternius-intake/. Everything after that is scripted:

python3 tools/quaternius_parts.py inventory --dir tmp/quaternius-intake
python3 tools/quaternius_parts.py extract \
  --file tmp/quaternius-intake/<file>.glb --mesh <mesh> --part <part>
python3 tools/quaternius_parts.py verify --dir assets/models/blender_src/quaternius/parts

inventory and verify run outside Blender; extract needs Blender, because it rewrites the skin. The pack itself is never committed — only the parts that are actually used, each with its SHA-256 recorded here and in CREDITS.md.

Part contract

A part is one skinned mesh on the 62-joint rig:

  • one mesh object, parented to the rig's armature, carrying JOINTS_0/WEIGHTS_0;
  • the standard joint names (Hips, Chest, Head, UpperArm.L, …). The rig check in quaternius_parts.py verify fails a part that is missing any of them, because NpcAvatar maps those bones;
  • materials named after a contract slot (skin, cloth, pants, hair, accessory) so the runtime tint reaches them, or a fixed-colour detail name that is deliberately not tinted;
  • triangles counted against the character budget: base body plus every joined part must stay inside 24,000 triangles and 24,000 glTF vertices.

The builder drops the part's own armature when it joins the mesh onto a base body, because the base already owns the skeleton and two armatures would duplicate every bone. Weights survive the join because Blender merges vertex groups by name.

Assigning parts to a role

"npc_vest": {"layer": "vest", "base": "worker", "parts": ["hivis_vest"], ...}

build joins those parts after the body join and before the material slot map, so the part's materials go through the same slot mapping as the base. The T-pose cache is keyed on the part list.

Kept parts

Part Source file SHA-256 Tris
(none yet — the pack has not been intaken)