55 lines
2.4 KiB
Markdown
55 lines
2.4 KiB
Markdown
# 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:
|
|
|
|
```sh
|
|
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
|
|
|
|
```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)_ | | | |
|