# 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: ```bash 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`/`skin` vertices (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`/`HipR` pants 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.320 | 0.209 | 0.307 | 0.449 | 0.329 | 0.144 | PASS | | `npc_jacket` | 1.824 m | 0.190 | 0.907 | 0.325 | 0.209 | 0.307 | 0.449 | 0.329 | 0.144 | PASS | | `npc_coat` | 1.824 m | 0.190 | 0.907 | 0.329 | 0.209 | 0.307 | 0.449 | 0.329 | 0.144 | PASS | | `npc_vest` | 1.819 m | 0.191 | 0.907 | 0.321 | 0.210 | 0.308 | 0.451 | 0.330 | 0.144 | PASS | | `npc_dress` | 1.825 m | 0.190 | 0.907 | 0.287 | 0.191 | 0.307 | 0.449 | 0.329 | 0.144 | PASS | | `npc_hoodie` | 1.856 m | 0.187 | 0.907 | 0.320 | 0.205 | 0.302 | 0.442 | 0.323 | 0.141 | PASS | | `npc_firefighter` | 1.819 m | 0.191 | 0.907 | 0.356 | 0.225 | 0.308 | 0.451 | 0.330 | 0.148 | PASS | | `npc_guard` | 1.819 m | 0.191 | 0.907 | 0.370 | 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.370** 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`](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.