Retire the unused beanie gear and sequence asset fixes after the map rebuild
Full build / Import + headless tests (push) Successful in 43s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-04 09:36:10 +01:00
1 parent ac0cf35cfb
commit 5158efc467
9 files changed
+19 -37

No files matched your search

+10 -2
View File
@@ -21,6 +21,12 @@ separate sources: licensed real-location photos, generated concept boards, and b
is an unversioned development track: it must not change the `npc_base` contract, the renderer or is an unversioned development track: it must not change the `npc_base` contract, the renderer or
the 0.10.0 release candidate. the 0.10.0 release candidate.
**Sequencing (2026-11-03, owner):** the asset-review fixes (A–G, notably the character P0/P1
rebuilds and the face/foliage prototypes) stay **blocked** until the full local map rebuild
(H–M) is done **and** a fresh 3D model review runs against the new maps. The measurements and
scorecard in `docs/3d-model-review.md` stand as the pre-rebuild baseline, not a go-ahead to start
character work now. Character development stays gated behind that second review.
Reference material is collected first (section A): local, gitignored, development-only photo Reference material is collected first (section A): local, gitignored, development-only photo
research may use any source the owner authorises (DuckDuckGo image search, street-view frames, research may use any source the owner authorises (DuckDuckGo image search, street-view frames,
neighbouring properties, buildings across the street) **without the licence gate**. The licence neighbouring properties, buildings across the street) **without the licence gate**. The licence
@@ -96,7 +102,8 @@ licence-free zone only.
`texels` and `inspect --json --out` were added to make the measurements repeatable. All 46 `texels` and `inspect --json --out` were added to make the measurements repeatable. All 46
assets audit/inspect clean; texel density 64–122 px/m authored, 287–440 effective fabric.) assets audit/inspect clean; texel density 64–122 px/m authored, 287–440 effective fabric.)
- [ ] Review the scorecard with the project owner, rank the P0/P1 gaps and decide fix vs accept - [ ] Review the scorecard with the project owner, rank the P0/P1 gaps and decide fix vs accept
per item; record the decision and the reason in the review document. per item; record the decision and the reason in the review document. **Deferred until the
full map rebuild (H–M) lands and a fresh 3D review runs against the new maps.**
### C. Character re-evaluation (8 variants + fallback) ### C. Character re-evaluation (8 variants + fallback)
@@ -142,7 +149,8 @@ licence-free zone only.
plus stride scaling are the accepted approach; a baked cloth-sim pipeline would only be plus stride scaling are the accepted approach; a baked cloth-sim pipeline would only be
reconsidered if a later close-up shows visible hem/coat stiffness. reconsidered if a later close-up shows visible hem/coat stiffness.
- [ ] Fix only the ranked P0/P1s, one asset family per commit; refresh the comparison sheet and - [ ] Fix only the ranked P0/P1s, one asset family per commit; refresh the comparison sheet and
re-run `inspect`, `audit`, `fit` and `npc_proportions.py` after each fix. re-run `inspect`, `audit`, `fit` and `npc_proportions.py` after each fix. **Blocked until
the map rebuild + second 3D review (see the track's sequencing note).**
- [ ] Build a licensed real-photo reference board for crowd variety (ages, builds, hair, outer - [ ] Build a licensed real-photo reference board for crowd variety (ages, builds, hair, outer
layers) and record what was adopted; reference only, never traced or repainted. layers) and record what was adopted; reference only, never traced or repainted.
- [ ] Generate a face/hand concept board for the highest-ranked P1 and compare it with the 0.9.4 - [ ] Generate a face/hand concept board for the highest-ranked P1 and compare it with the 0.9.4
+1 -23
View File
@@ -48,28 +48,6 @@
"triangles": 380, "triangles": 380,
"vertices": 408 "vertices": 408
}, },
"beanie": {
"attach": "head",
"bounds_godot": {
"max": [
0.193,
0.215,
0.183
],
"min": [
-0.193,
0.014,
-0.203
]
},
"category": "npc_gear",
"materials": [
"plastic_grey"
],
"path": "assets/models/blender/npc_gear/beanie.glb",
"triangles": 460,
"vertices": 403
},
"bench": { "bench": {
"bounds_godot": { "bounds_godot": {
"max": [ "max": [
@@ -1246,4 +1224,4 @@
"head": "Rig/Head marker (y = 1.62 m, head centre)" "head": "Rig/Head marker (y = 1.62 m, head centre)"
}, },
"generator": "tools/blender_assets.py" "generator": "tools/blender_assets.py"
} }
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

+3 -3
View File
@@ -103,7 +103,6 @@ yet reviewed; this document is the place to fill it.
| Gear | Attach | Tris | Verdict | | Gear | Attach | Tris | Verdict |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| `cap` | head | 328 | — (fit measured, visual pending) | | `cap` | head | 328 | — (fit measured, visual pending) |
| `beanie` | head | 460 | — (unused by any character) |
| `hood` | head | 804 | — | | `hood` | head | 804 | — |
| `sunglasses` | head | 164 | accept (0.9.4 clearance) | | `sunglasses` | head | 164 | accept (0.9.4 clearance) |
| `firefighter_helmet` | head | 672 | accept (0.9.4 + 3 cm runtime offset) | | `firefighter_helmet` | head | 672 | accept (0.9.4 + 3 cm runtime offset) |
@@ -130,7 +129,8 @@ head band at 0.64× head width. Three caveats worth recording, none of which cha
measured against the **hip/skirt** radius, which is wider than the upper back where the bags measured against the **hip/skirt** radius, which is wider than the upper back where the bags
actually sit; `cap` and `firefighter_helmet` report `band=OUTSIDE` because they sit on the crown actually sit; `cap` and `firefighter_helmet` report `band=OUTSIDE` because they sit on the crown
above the 1.55–1.81 face/head band (expected); and the `lanyard` clip is corrected at runtime by above the 1.55–1.81 face/head band (expected); and the `lanyard` clip is corrected at runtime by
`GEAR_OFFSETS` (+4 cm forward). `beanie` is unused and remains a retire/reassign candidate. `GEAR_OFFSETS` (+4 cm forward). The unused `beanie` was retired on 2026-11-03 (removed from
`GEAR`, its builder, `npc_avatar.gd` and the manifest).
### Props (20 library + 6 generated fallbacks) ### Props (20 library + 6 generated fallbacks)
@@ -249,7 +249,7 @@ owner review decides.
palm with `HAND_ITEM_FORWARD`; no finger bones exist, so a curl rig is a contract decision, not palm with `HAND_ITEM_FORWARD`; no finger bones exist, so a curl rig is a contract decision, not
a modelling tidy-up. a modelling tidy-up.
7. **Gear never reviewed as silhouette language (P2).** 18 pieces pass fit/contract but have no 7. **Gear never reviewed as silhouette language (P2).** 18 pieces pass fit/contract but have no
prop-artist verdict; `beanie` is unused and could be retired or reassigned. prop-artist verdict (the unused `beanie` was retired 2026-11-03).
8. **Venue shape language (P2).** Hollywood and the Joke Shop have budget data but no 8. **Venue shape language (P2).** Hollywood and the Joke Shop have budget data but no
`environment-artist`/`archviz` review; the TV Studio has no recorded map-budget number in this `environment-artist`/`archviz` review; the TV Studio has no recorded map-budget number in this
document yet. document yet.
+2 -2
View File
@@ -21,7 +21,7 @@ captures in `docs/screenshots/`.
- **People** (`targeting_npc`, `joke_shop_queue`, `studio_arrival`, - **People** (`targeting_npc`, `joke_shop_queue`, `studio_arrival`,
`crowd_panic`, `responder_arrival`): ordinary adults in sweaters, jackets, `crowd_panic`, `responder_arrival`): ordinary adults in sweaters, jackets,
long coats, hoodies and beanies; a security guard in a dark uniform with a cap long coats and hoodies; a security guard in a dark uniform with a cap
and belt; a firefighter in a dark turnout coat with yellow reflective bands, and belt; a firefighter in a dark turnout coat with yellow reflective bands,
a helmet and an SCBA tank. The current skinned `npc_base` is a set of boxes a helmet and an SCBA tank. The current skinned `npc_base` is a set of boxes
and cylinders with a flat face, so silhouette was the main gap. and cylinders with a flat face, so silhouette was the main gap.
@@ -145,7 +145,7 @@ attach point:
| Attach | Godot parent / position | Gear | | Attach | Godot parent / position | Gear |
| --- | --- | --- | | --- | --- | --- |
| `head` | `Rig/Head` marker (0, 1.62, 0) | cap, beanie, hood, sunglasses, firefighter_helmet | | `head` | `Rig/Head` marker (0, 1.62, 0) | cap, hood, sunglasses, firefighter_helmet |
| `back` | `Rig` at (0, 1.10, 0), spine centre; items sit behind the body (Blender +Y = Godot −Z) | backpack, shoulder_bag, scba_tank | | `back` | `Rig` at (0, 1.10, 0), spine centre; items sit behind the body (Blender +Y = Godot −Z) | backpack, shoulder_bag, scba_tank |
| `chest` | `Rig` at (0, 1.30, 0), sternum | lanyard | | `chest` | `Rig` at (0, 1.30, 0), sternum | lanyard |
| `hand` | Hand proxy (±0.27, 0.78, 0.02); grip 5 cm below the origin | phone, cup, clipboard, umbrella, camera, protest_sign, flashlight, wand, radio | | `hand` | Hand proxy (±0.27, 0.78, 0.02); grip 5 cm below the origin | phone, cup, clipboard, umbrella, camera, protest_sign, flashlight, wand, radio |
+1 -1
View File
@@ -78,7 +78,7 @@ pass every applicable item before a library rebuild is accepted.
the head volume has a readable jaw/cheek/chin transition; no face-plane seams, the head volume has a readable jaw/cheek/chin transition; no face-plane seams,
inverted normals or z-fighting. The face direction must remain unambiguous. inverted normals or z-fighting. The face direction must remain unambiguous.
4. **Hair and headgear:** hair covers the scalp without gaps or scalp-through 4. **Hair and headgear:** hair covers the scalp without gaps or scalp-through
seams; fringes, buns and beards keep their silhouette. Caps, beanies, hoods, seams; fringes, buns and beards keep their silhouette. Caps, hoods,
sunglasses and the firefighter helmet clear the brow, eyes and ears. Headgear sunglasses and the firefighter helmet clear the brow, eyes and ears. Headgear
may sit outside the 1.55–1.81 m face band, but its brim must not cover the may sit outside the 1.55–1.81 m face band, but its brim must not cover the
eyes. eyes.
+1 -1
View File
@@ -185,7 +185,7 @@ const GEAR_OFFSETS := {
## item forward into the open palm. ## item forward into the open palm.
const HAND_ITEM_FORWARD := Vector3(0, 0, 0.04) const HAND_ITEM_FORWARD := Vector3(0, 0, 0.04)
const GEAR_ATTACH := { const GEAR_ATTACH := {
"cap": "head", "beanie": "head", "hood": "head", "sunglasses": "head", "cap": "head", "hood": "head", "sunglasses": "head",
"firefighter_helmet": "head", "firefighter_helmet": "head",
"backpack": "back", "shoulder_bag": "back", "scba_tank": "back", "backpack": "back", "shoulder_bag": "back", "scba_tank": "back",
"lanyard": "chest", "lanyard": "chest",
+1 -5
View File
@@ -123,7 +123,7 @@ FIT_HIP_BAND = (0.55, 0.95) # fallback body radius for trousers/vests
# tell where the bag body starts. Measure the body-only y band for this fit. # tell where the bag body starts. Measure the body-only y band for this fit.
FIT_BODY_BANDS = {"shoulder_bag": (-0.34, -0.16)} FIT_BODY_BANDS = {"shoulder_bag": (-0.34, -0.16)}
GEAR = { GEAR = {
"cap": "head", "beanie": "head", "hood": "head", "sunglasses": "head", "cap": "head", "hood": "head", "sunglasses": "head",
"firefighter_helmet": "head", "firefighter_helmet": "head",
"backpack": "back", "shoulder_bag": "back", "scba_tank": "back", "backpack": "back", "shoulder_bag": "back", "scba_tank": "back",
"lanyard": "chest", "lanyard": "chest",
@@ -1060,10 +1060,6 @@ def build_gear(name):
p.append(cyl("Brim", 0.11, 0.11, 0.012, (0, -0.17, 0.055), M("plastic_black"), p.append(cyl("Brim", 0.11, 0.11, 0.012, (0, -0.17, 0.055), M("plastic_black"),
seg=16, scale=(1.0, 0.8, 1.0), rot=(math.radians(-8), 0, 0))) seg=16, scale=(1.0, 0.8, 1.0), rot=(math.radians(-8), 0, 0)))
p.append(sphere("Button", 0.014, (0, 0.01, 0.195), M("plastic_black"), seg=8, rings=4)) p.append(sphere("Button", 0.014, (0, 0.01, 0.195), M("plastic_black"), seg=8, rings=4))
elif name == "beanie":
p.append(sphere("Knit", 0.172, (0, 0.01, 0.04), M("plastic_grey"), seg=20, rings=12,
scale=(1.0, 1.04, 1.02), cut_below=-0.05))
p.append(torus("Cuff", 0.163, 0.03, (0, 0.01, 0.04), M("plastic_grey"), seg=20))
elif name == "hood": elif name == "hood":
p.append(_hood("Hood", M("plastic_grey"), (0, 0, 0.015))) p.append(_hood("Hood", M("plastic_grey"), (0, 0, 0.015)))
elif name == "sunglasses": elif name == "sunglasses":