# 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 (, 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: ```sh python3 tools/quaternius_parts.py inventory --dir tmp/quaternius-intake python3 tools/quaternius_parts.py extract \ --file tmp/quaternius-intake/.glb --mesh --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 ```python "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)_ | | | |