Files
security-game/.agents/skills/gig-line-blender-asset-contract/references/asset-contract.md
T
zwitschi 2ba40f3578
Full build / Import + headless tests (push) Successful in 41s
Full build / Full desktop build + optional release (push) Skipped
Reorganize docs into category folders and drop the retired head-review page
Group the top-level docs into docs/project, docs/design, docs/assets and
docs/process, each with its own README index. Delete the superseded
docs/screens/head-review page and sheets. Rewrite every markdown link,
absolute docs path and tool/test reference to the new locations, fix the
pre-existing broken anchors and remove the dead Joke Shop photo-board link.
check_docs OK, Python tooling 167/167.
2026-11-06 20:13:03 +01:00

5.8 KiB
Raw Blame History

Asset Contract Reference

This is a working summary. The authoritative sources remain docs/assets/blender-assets.md, docs/assets/asset-tooling.md, ADR-0013, the tests in src/test/tests/ and the constants in tools/blender_assets.py / tools/npc_pipeline.py.

Library inventory

  • Character variants (8): npc_casual, npc_jacket, npc_coat, npc_vest, npc_dress, npc_hoodie, npc_firefighter, npc_guard.
  • Frozen fallback: npc_base / assets/models/generated/npc_base.glb.
  • Gear: 18 attach-space pieces covering head, back, chest and hand items.
  • Library props: 20 Blender-authored props plus 6 generated props.
  • Venues: procedural venues in src/game/world_builder.gd; Blender venue geometry follows the same budgets and collision/provenance rules.

Skeleton and geometry

The required contract skeleton has 13 core bones:

Head, Spine, Neck,
HipL, HipR,
KneeL, KneeR,
ShoulderL, ShoulderR,
ElbowL, ElbowR,
HandL, HandR

Optional extra bones (fingers, face controls, toes) are allowed if they do not move these core rest positions and do not break NpcAvatar's animation proxies.

Requirements:

  • npc_base mesh node exists and is skinned under Rig.
  • Limb node names stay stable for NpcAvatar and tests.
  • Front is Blender −Y / Godot +Z.
  • Feet are grounded at approximately y = 0; no floating origin.
  • Units are metres; character height is approximately 1.8 m.
  • No zero-area/duplicate degenerate faces in the exported mesh.
  • Every character has UVs in [0,1] unless a planned UDIM/atlas change is explicitly accepted.

Material slots

Exactly these five tint slots:

skin, cloth, pants, accessory, hair
  • Neutral albedo is authored in Blender; runtime tinting is authoritative.
  • Slot names are contract values; do not rename or add a sixth slot casually.
  • The procedural fallback (NpcAvatar._build_body) must keep working when the GLB is missing.

Budgets

Asset Limit
Character (library and base fallback) 24,000 triangles / 24,000 glTF vertices
Gear piece 1,500 triangles
Prop 4,000 triangles
Library prop/venue total must stay inside the venue tests and library budget

CHAR_MAX_TRIS, CHAR_MAX_VERTS, GEAR_MAX_TRIS, PROP_MAX_TRIS and related constants live in tools/blender_assets.py. The budget is per character, not an average. Measure after every mesh change. Do not lower the cap to make a diff pass.

Gear and hand items

  • Gear is authored in the attach-point space documented by GEAR / GEAR_ATTACH / ATTACH_BLENDER.
  • blender_assets.py fit measures gear boxes against the character's head band, clothing radius and back clearance.
  • Runtime offsets are intentional:
    • NpcAvatar.GEAR_OFFSETS = {"lanyard": Vector3(0,0,0.04), "firefighter_helmet": Vector3(0,0.03,0)}
    • NpcAvatar.HAND_ITEM_FORWARD = Vector3(0,0,0.04)
  • An offset is not an authored-asset change; do not bake it into the GLB without a separate contract decision.
  • Open-palm grip (no finger-curl rig) is the accepted stylized limit.

Textures and AO

  • NPC maps are 256² albedo + normal + packed ORM.
  • TEX_SIZE = 256 in tools/npc_pipeline.py.
  • Fabric UV scale is Materials.NPC_FABRIC_UV_SCALE = Vector3(4,4,1).
  • Cloth/pants skip the per-character baked AO; skin/hair/gear keep it. This avoids the large blotchy magnification that appeared at 256².
  • Gear/props may have their own AO maps; tools/bake_ao.py writes <name>_ao.png next to the GLB and Godot wires it into the AO channel.
  • Never overwrite an existing committed image; use a new -vN candidate and promote only after review.
  • Run python3 tools/asset_pipeline.py audit <path> and the relevant npc_pipeline.py audit before committing map changes.

File map

Path Role
tools/blender_assets.py Catalogue, builders, audit/fit/inspect/texels/sheet.
tools/npc_pipeline.py npc_base builder, texture preparation and audit.
tools/bake_ao.py Blender AO bake into <name>_ao.png.
tools/npc_proportions.py Exported-GLB proportion audit (no Blender).
tools/npc_baseline.py Contact sheets/comparisons (no Blender).
assets/models/blender/manifest.json Generated asset manifest.
assets/models/blender/**/*.glb Committed library assets.
assets/models/generated/npc_base.glb Frozen NPC fallback.
assets/textures/npc/*_{albedo,normal,orm}.png Committed NPC maps.
src/test/capture_npc_baseline.gd 48-frame neutral baseline.
src/test/capture_npc_review.gd 96-frame final-context review.

Provenance and source rules

  • Procedural Blender assets are project-owned.
  • External/CC assets need ADR-0015 clearance: CC0 preferred, CC-BY only with attribution in CREDITS.md; no service assets with redistribution limits.
  • Editable .blend files under assets/models/blender_src/ are gitignored; only exported .glb, AO maps, manifests and committed preview sheets ship.
  • AI-generated source images are development inputs, not shipped assets. Keep raw generations under gitignored paths until picked, checked and credited.
  • Do not copy a downloaded/Street View/AI reference into a committed asset without the licence and provenance review.

Verification invariants

The asset pass is not complete unless:

  1. python3 tools/blender_assets.py audit exits 0.
  2. python3 tools/blender_assets.py fit exits 0 and the report is reviewed.
  3. python3 tools/npc_proportions.py report passes the stylized guide.
  4. python3 tools/npc_pipeline.py audit passes when the base/textures changed.
  5. The 48-frame baseline and 96-frame final-context review are captured, with no blank frames.
  6. The 24-NPC budget smoke is inside its frame budget.
  7. The full Godot suite and Python tooling tests pass.
  8. No runtime contract, renderer or dependency changed except the rebuilt assets and their generated metadata.