3.7 KiB
NPC proportion audit
Status: audited 2026-11-02. All eight library variants are inside the stylized proportion guide; no geometry correction was required in this pass. The report is repeatable from the exported GLBs:
python3 tools/npc_proportions.py report
python3 tools/npc_proportions.py report --json
Method
tools/npc_proportions.py reads the GLB meshes and rest-pose joint hierarchy:
- height from the full mesh bounds;
- head height, width and aspect from
Head/skinvertices (hair excluded so long hairstyles do not change the head measurement); - shoulder silhouette from vertices in the upper-chest band around the shoulder joint;
- hip width from
HipL/HipRpants vertices; - torso length from the Spine joint to the shoulder joint;
- leg length from the Spine joint to the lowest vertex;
- arm length from the shoulder joint to the Hand joint;
- foot length from the forward extent of the KneeL/KneeR shoe vertices.
All ratios are divided by total standing height except head_aspect
(width / head height).
Guide
These are stylized-but-credible bands for the game's low-poly adults, not photoreal anatomy. The broad build is allowed a larger shoulder/hip silhouette than the slim build.
| Ratio | Target | Notes |
|---|---|---|
head_height |
0.16–0.22 | deliberately larger than a realistic 0.13–0.15 |
head_aspect |
0.70–1.00 | width / height; rounded heads are acceptable |
shoulder_width |
0.28–0.38 | silhouette includes sleeves and build scaling |
hip_width |
0.17–0.23 | pants-only width, not skirt/coat flare |
torso_length |
0.28–0.38 | Spine joint to shoulder |
leg_length |
0.40–0.48 | Spine joint to ground |
arm_length |
0.28–0.38 | shoulder to hand |
foot_length |
0.12–0.18 | shoe forward extent |
Result
| Character | Height | Head | Aspect | Shoulder | Hip | Torso | Leg | Arm | Foot | Result |
|---|---|---|---|---|---|---|---|---|---|---|
npc_casual |
1.824 m | 0.190 | 0.907 | 0.321 | 0.209 | 0.307 | 0.449 | 0.329 | 0.144 | PASS |
npc_jacket |
1.824 m | 0.190 | 0.907 | 0.333 | 0.209 | 0.307 | 0.449 | 0.329 | 0.144 | PASS |
npc_coat |
1.824 m | 0.190 | 0.907 | 0.334 | 0.209 | 0.307 | 0.449 | 0.329 | 0.144 | PASS |
npc_vest |
1.819 m | 0.191 | 0.907 | 0.322 | 0.210 | 0.308 | 0.451 | 0.330 | 0.144 | PASS |
npc_dress |
1.825 m | 0.190 | 0.907 | 0.289 | 0.191 | 0.307 | 0.449 | 0.329 | 0.144 | PASS |
npc_hoodie |
1.856 m | 0.187 | 0.907 | 0.328 | 0.205 | 0.302 | 0.442 | 0.323 | 0.141 | PASS |
npc_firefighter |
1.819 m | 0.191 | 0.907 | 0.358 | 0.225 | 0.308 | 0.451 | 0.330 | 0.148 | PASS |
npc_guard |
1.819 m | 0.191 | 0.907 | 0.369 | 0.219 | 0.308 | 0.451 | 0.330 | 0.144 | PASS |
No variant is outside a band, so the body pass does not need a global skeleton or mesh rescale. The values closest to a boundary are:
- head height 0.190 against the 0.22 upper bound, and head aspect 0.907 against 1.00 — the head is deliberately large. Any head-size change must be coordinated with the face/headgear pass and its gear-fit measurements.
- guard shoulder 0.369 and firefighter hip 0.225 against the broad-build upper bounds — these are the intended uniform/turnout silhouettes, not outliers.
- leg length 0.449 and torso 0.307 sit inside the guide for all variants; the earlier short-leg impression came from the hip joint position, not the visible pelvis line.
Follow-up
The proportion audit does not replace the visual criteria in
npc-visual-review.md: neck/shoulder/hip transitions,
face depth, hand grips, clothing hems and shoes still need the appearance pass.
Re-run the audit after any body mesh or skeleton change and record the new
ratios here.