Raise character limits and document optional Blender MCP
Full build / Import + headless tests (push) Successful in 41s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-04 13:47:16 +01:00
1 parent 50a48d2256
commit aec1fb7b69
20 files changed
+303 -96

No files matched your search

@@ -1,6 +1,6 @@
---
name: gig-line-blender-asset-contract
description: Use when adding, rebuilding, auditing or fixing any Gig Line Blender-authored character, NPC base, gear, prop or venue geometry. Covers the 13-bone npc_base contract, five tint slots, triangle/vertex budgets, gear attach space, 256² texture/AO rules, headless flatpak Blender commands, and the inspect/audit/fit/proportion/capture gates. Do not use for pure GDScript/UI work or release publishing.
description: Use when adding, rebuilding, auditing or fixing any Gig Line Blender-authored character, NPC base, gear, prop or venue geometry. Covers the required 13 core bones (optional extra bones allowed), five tint slots, 16,000/16,000 character budgets, gear attach space, 256² texture/AO rules, headless flatpak Blender commands, optional MCP guidance, and the inspect/audit/fit/proportion/capture gates. Do not use for pure GDScript/UI work or release publishing.
compatibility: Gig Line repository checkout. Godot 4.7.2 on PATH; Blender 5.2 LTS via the org.blender.Blender flatpak for build/bake/render. Audit, fit, inspect and proportion checks are stdlib-only.
metadata:
project: Gig Line
@@ -21,9 +21,10 @@ Use this skill for any change that touches:
- Blender-authored venue/prop geometry
The project contract and measured gates override any generic Blender advice.
There is **no Blender MCP** in this project. Blender runs headless through the
flatpak CLI; the `blender-skills` pack is optional, local guidance only, and
gitignored.
Blender MCP is optional interactive tooling; the headless flatpak CLI remains
authoritative and CI never needs Blender or MCP. The `blender-skills` pack is
optional, local guidance only, and gitignored. Setup and safety are in
`docs/blender-mcp.md`.
## Read first
@@ -47,11 +48,11 @@ and resolve the source of truth before editing assets.
| Area | Rule |
| --- | --- |
| Mesh root | `npc_base` mesh node, skinned under `Rig`; preserve the limb node names. |
| Bones | 13 contract bones: `Head`, `HipL/R`, `KneeL/R`, `ShoulderL/R`, `ElbowL/R`, `HandL/R`, `Spine`, `Neck` (parent/helper bones must not change the contract). |
| Bones | The 13 required core bones: `Head`, `HipL/R`, `KneeL/R`, `ShoulderL/R`, `ElbowL/R`, `HandL/R`, `Spine`, `Neck`. Optional extra bones (fingers, face, toes) are allowed; they must not move the core rest positions or break animation proxies. |
| Tint slots | `skin`, `cloth`, `pants`, `accessory`, `hair`. |
| Orientation | Front is Blender −Y / Godot +Z; feet grounded near y = 0; metres. |
| Library budget | **8,000 triangles / 8,000 glTF vertices** per character (`CHAR_MAX_TRIS`/`CHAR_MAX_VERTS`). |
| Frozen fallback | `npc_base` keeps **6,000 tris / 4,000 verts**. Do not silently raise or lower it. |
| Character budget | **16,000 triangles / 16,000 glTF vertices** per character (`CHAR_MAX_TRIS`/`CHAR_MAX_VERTS`). |
| Frozen fallback | `npc_base` remains the low-poly fallback; it shares the 16,000/16,000 cap but is not required to use it. Do not silently lower the cap. |
| Gear budget | **1,500 triangles** per gear piece; authored in attach-point space. |
| Prop budget | **4,000 triangles** per prop. |
| Gear attach | Use the catalogued attach points; verify with `fit`. Runtime `GEAR_OFFSETS` (lanyard forward, firefighter helmet up) and `HAND_ITEM_FORWARD` are intentional, not asset-contract changes. |
@@ -113,8 +114,7 @@ only the specialists the task needs:
- budget/LOD/collision: `asset-optimization`, `lod-pipeline`, `collision-proxy`
- final review: `qa-review`
Translate any MCP instruction into a change to `tools/*.py` or a headless CLI
run. Never add an MCP dependency to the build, CI or runtime.
If MCP is available, use it for interactive part exploration only; mirror the result into a scripted change or local `.blend`, then re-export and run the CLI audit/fit gates. Never make the build, CI, tests or runtime depend on MCP. Setup: `docs/blender-mcp.md`.
### 4. Build or bake
@@ -167,7 +167,7 @@ At minimum:
- `npc_proportions.py` passes the stylized guide.
- `npc_pipeline.py audit` passes if the base/textures changed.
- texel density is inside the authored/fabric bands.
- No character exceeds 8,000/8,000; gear/prop caps hold.
- No character exceeds 16,000/16,000; gear/prop caps hold.
- 24-NPC budget and Web/Compatibility path remain green.
- Contract tests, headless suite, capture gates and docs check pass.
- The diff contains only the intended assets, tools, tests and docs.
@@ -197,12 +197,14 @@ gates run, and any accepted limit.
- [`references/asset-contract.md`](references/asset-contract.md) — full contract,
inventory, file locations and provenance rules.
- `docs/blender-mcp.md` — optional MCP installation, connection, safety and
part-workflow instructions.
- [`references/verification.md`](references/verification.md) — command matrix,
capture gates, expected results and acceptance criteria.
## Do not
- Add an MCP server, Blender dependency or API call to the build/runtime.
- Make the build, CI, tests or runtime depend on MCP, Blender or API calls.
- Change the bone/tint/contract to make a generic asset fit.
- Rewrite committed baselines or overwrite existing images.
- Commit `.blend` sources, raw captures or generated AI inputs.
@@ -17,7 +17,7 @@ This is a working summary. The authoritative sources remain
## Skeleton and geometry
The contract skeleton has 13 bones:
The required contract skeleton has 13 core bones:
```text
Head, Spine, Neck,
@@ -28,6 +28,9 @@ 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`.
@@ -56,8 +59,7 @@ skin, cloth, pants, accessory, hair
| Asset | Limit |
| --- | --- |
| Library character | 8,000 triangles / 8,000 glTF vertices |
| `npc_base` fallback | 6,000 triangles / 4,000 vertices |
| Character (library and base fallback) | 16,000 triangles / 16,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 |
+9 -7
View File
@@ -88,15 +88,17 @@ specialists the task needs:
### Project rules that override a skill
1. **The project contract wins.** `npc_base` mesh node, the 13 contract bones at their rest
positions, five tint slots, front on Blender −Y / Godot +Z, grounded feet, 8,000
triangles / 8,000 glTF vertices per character, 1,500 per gear, 4,000 per prop. A skill
1. **The project contract wins.** `npc_base` mesh node, the 13 required core bones at their rest
positions, five tint slots, front on Blender −Y / Godot +Z, grounded feet, 16,000
triangles / 16,000 glTF vertices per character, 1,500 per gear, 4,000 per prop. Optional
extra bones (fingers, face, toes) are allowed if they do not move the core rest positions. A skill
may recommend another topology, naming or budget scheme; do not adopt it unless the
change is explicitly planned and the contract, tests and docs are updated together.
2. **There is no Blender MCP here.** The skills assume MCP tools; this project runs Blender
as headless flatpak scripts (`tools/blender_assets.py`, `tools/npc_pipeline.py`). Translate
MCP steps into script changes or CLI runs. Never add an MCP dependency to the build, CI or
runtime.
2. **Blender MCP is optional interactive tooling.** The headless flatpak scripts
(`tools/blender_assets.py`, `tools/npc_pipeline.py`) remain authoritative. MCP may be used
for local part exploration; setup and safety are in [`docs/blender-mcp.md`](docs/blender-mcp.md).
Never add an MCP dependency to the build, CI, tests or runtime, and always re-run the CLI
audit/fit gates on anything MCP touched.
3. **CI stays offline and skill-free.** Skills are local guidance only; every gate must still
work from a fresh checkout with committed `.glb`/`.png`/`.tres` files and Godot.
4. **No new asset source without the licence gate.** Skills may suggest reference packs or
+9 -3
View File
@@ -58,9 +58,15 @@ canonical implemented-features list in `docs/development-status.md`.
36 venue/difficulty/phase cells, seeds 1–100, and access/emergency error rates. Gotcha:
`_read_npc_truth()` is type-derived, not behaviour-derived; the emergency-fairness review must
account for that oracle mismatch.
- **Character mesh cap:** eight library variants use 8,000 tris / 8,000 glTF vertices
(`CHAR_MAX_TRIS`/`CHAR_MAX_VERTS` in `tools/blender_assets.py`); the frozen `npc_base` fallback
keeps 6,000/4,000. Measure after any geometry change; never silently lower the cap back to 5,000.
- **Blender MCP is optional (2026-11-04):** setup and safe part workflow are in
`docs/blender-mcp.md`. The headless flatpak scripts remain authoritative; MCP is
never a build/CI/test/runtime dependency, and anything MCP touched must pass the
CLI audit/fit gates.
- **Character mesh cap (2026-11-04):** all characters use 16,000 tris / 16,000 glTF vertices
(`CHAR_MAX_TRIS`/`CHAR_MAX_VERTS` in `tools/blender_assets.py`; `npc_pipeline.MAX_TRIANGLES`/
`MAX_VERTICES`). The required 13 core bones stay, optional extra bones are allowed, and the
low-poly `npc_base` fallback remains the shipped fallback. Measure the 24-NPC/Web budget after
any geometry change; never silently lower the cap without a new decision.
- **Engine baseline:** Godot 4.7.2 stable (official editor `~/.local/bin/godot`). The system's
`godot-runner` cannot load arbitrary project paths (compiled without path overrides); use the
official editor binary.
+1
View File
@@ -180,6 +180,7 @@ Full setup, every run/test/smoke command, and the controls table are in
- [`CREDITS.md`](CREDITS.md) — Credits, AI/reference provenance and licensing notes.
- [`PRIVACY.md`](PRIVACY.md) — Local-only data, save files and development API use.
- [`docs/blender-assets.md`](docs/blender-assets.md) — Blender asset library: characters, gear, props, attach points.
- [`docs/blender-mcp.md`](docs/blender-mcp.md) — optional Blender MCP installation, connection and safe part-workflow.
- [`docs/npc-visual-review.md`](docs/npc-visual-review.md) — 0.9.4 NPC baseline, acceptance criteria and ranked visual gaps; 0.9.5 texture comparison is in [`docs/blender_previews/sheet_texture_refinement_0.9.5.jpg`](docs/blender_previews/sheet_texture_refinement_0.9.5.jpg).
- [`docs/npc-proportion-audit.md`](docs/npc-proportion-audit.md) — NPC proportion measurements against the shared stylized guide.
- [`docs/adr/`](docs/adr/) — Architecture Decision Records.
+25 -17
View File
@@ -17,8 +17,8 @@ The MIT Blender skill pack lives locally at `.agents/skills/blender-skills/` (gi
Goal: replace the sphere-and-primitive face and hand construction with a local, part-based
development pipeline that can build, inspect and compare the **head/face** and **hands** separately
before assembling them into the shipped character. Prioritise face readability at portrait
distance, then hand silhouette and gear contact. Preserve the `npc_base` contract, the 13-bone rig,
five tint slots, 8,000/8,000 character cap and Compatibility/Web path.
distance, then hand silhouette and gear contact. Preserve the `npc_base` contract, the 13 core-bone rig (optional extra bones allowed),
five tint slots, 16,000/16,000 character cap, optional extra bones beyond the required 13, and the Compatibility/Web path.
*Skill route: `character-artist`, `retopology`, `sculpting`, `rigging`, `uv-workflow`,
`texture-workflow`, `materials`, `lookdev`, `asset-optimization`, `qa-review`.*
@@ -42,7 +42,7 @@ the rest of §C remains the broad review checklist.
UV layout and the exact locations of eye/mouth/finger geometry.
- [ ] Define measurable acceptance: face front/three-quarter/profile at 1.5 m and 1.85 m; hands
open and gripping at 0.8 m; silhouette, eye/mouth readability, ear/nose/jaw planes, finger
separation and gear contact. Keep the 8,000/8,000 cap; no contract or renderer change.
separation and gear contact. Keep the 16,000/16,000 cap; optional extra bones are allowed, but the required 13 core bones and rest positions must not move.
- [ ] Confirm the identity boundary: `npc_base.blend` is the frozen fallback and must not absorb
prototype detail unless a separate contract decision approves it.
- [ ] Choose a local working-set layout: `tmp/npc-parts/<variant>/` (gitignored) for part `.blend`
@@ -61,6 +61,10 @@ the rest of §C remains the broad review checklist.
- [ ] Add tests for deterministic part assembly, contract output (mesh root, bones, slots, budgets)
and the non-Blender failure path. Verify one assembled prototype with `audit`/`fit`/`inspect`
before touching production variants.
- [x] Consider optional Blender MCP for interactive part exploration and document setup/safety.
(`docs/blender-mcp.md` covers addon/client setup, Pi `pi mcp add`, flatpak networking,
viewport/`bpy` workflow and the rule that headless audit/fit remains authoritative; MCP is
not a build/CI/runtime dependency.)
- [ ] Document the commands, working-set paths and “part source is not a shipped asset” rule in
`docs/asset-tooling.md`, `docs/blender-assets.md` and
`.agents/skills/gig-line-blender-asset-contract/references/verification.md`.
@@ -84,8 +88,9 @@ the rest of §C remains the broad review checklist.
- [ ] Build separate left/right hand parts with a connected palm, four multi-segment fingers, a
thumb, knuckles and rounded tips. Support an open palm and a relaxed grip; preserve the
current `HAND_ITEM_FORWARD` behaviour for phone/cup/clipboard/camera/flashlight/wand/radio.
- [ ] Decide finger articulation explicitly: the 13-bone contract has no finger bones, so keep the
open/relaxed-palm approach unless an ADR approves extra bones and the budget/weight path.
- [ ] Decide finger articulation explicitly: the current rig has no finger bones, so keep the
open/relaxed-palm approach unless an ADR approves optional finger bones and the
budget/weight path.
- [ ] Verify all hand gear at 0.8 m (contact, clipping, direction) and capture open/grip hand
close-ups for the review sheet.
- [ ] Roll the approved hands into all 12 variants only after the one-variant hand sheet passes.
@@ -93,7 +98,8 @@ the rest of §C remains the broad review checklist.
### 5. Assembly and rollout
- [ ] Integrate the approved parts into `build_character` with deterministic joins, weights, UVs and
AO. The final output remains one `npc_base` skinned mesh under the existing 13-bone armature;
AO. The final output remains one `npc_base` skinned mesh under the existing 13-core armature;
optional extra bones are allowed but the core rest positions stay fixed;
no second rig, no material-slot rename.
- [ ] Keep the MakeHuman body prototype consumable with the same approved head/hands; do not let it
grow a second face/hand implementation while the part pipeline is being proven.
@@ -148,11 +154,11 @@ an active track; ADR-0015 (CC0 / CC-BY with attribution) still governs every int
### Intake and adaptation
- [x] `adapt` path added to `tools/blender_assets.py` (`adapt --file <in> --out <out>
[--target-tris 8000]`): imports the GLB, applies transforms, grounds the feet, welds seam
splits and decimates to the budget, then exports. The five tint slots + 13-bone rig stay a
manual step (recorded in the command doc).
[--target-tris 16000]`): imports the GLB, applies transforms, grounds the feet, welds seam
splits and decimates to the budget, then exports. The five tint slots + 13-core rig
(optional extra bones allowed) stay a manual step (recorded in the command doc).
- [x] `audit` stays the final gate; `test_adapt_requires_blender` covers the non-Blender error
path (161/161 Python).
path (162/162 Python).
- [x] Adapter commands + go/no-go documented in `docs/asset-tooling.md` §Intake adaptation.
### MPFB / MakeHuman body pipeline
@@ -163,18 +169,18 @@ an active track; ADR-0015 (CC0 / CC-BY with attribution) still governs every int
x ±0.53 / y 0–1.82 / z −0.12…+0.35, one neutral material, UVs present, unskinned. The
body (no rig) is the input for the rigging step; the script + mesh stay in `tmp/` (CC0, not
committed).
- [x] Rig strategy decided (owner): **retarget the body to the 13-bone contract**.
- [x] Rig strategy decided (owner): **retarget the body to the 13-core contract; optional extra bones are allowed**.
`tmp/npc-research/makehuman_retarget.py` rotates the A-pose arms down (−38°/+38°), scales the
arms 1.63× to the contract 0.70 m length, welds the split vertices, smooth-shades, adds the
contract armature + `_auto_weights`, paints the five slot regions (hair/cloth/pants/accessory/
skin) and exports `makehuman_retargeted.glb`. **Contract passes:** 6,444 / 8,000 tris,
7,726 / 8,000 verts, 14 bones (13 + Hips), skinned, arm-down, grounded, five slots, no issues.
skin) and exports `makehuman_retargeted.glb`. **Contract passes:** 6,444 / 16,000 tris,
7,726 / 16,000 verts, 14 bones (13 + Hips), skinned, arm-down, grounded, five slots, no issues.
Vision-reviewed: arms hang down and the silhouette + slot regions read, but the 1.63× arm warp
distorts the deltoid/shoulder (spiky/warped), the decimated hands are blocky, and the slot
boundaries are rough — these are the refinement steps below.
- [x] Head/hands/feet swap (`makehuman_final.py`): cut the decimated MakeHuman head/hands/feet and
joined the project's `_face`/`_hair`/`_hands_and_shoes`, then re-weighted/re-UV'd. Contract
passes: 6,407 / 8,000 tris, 6,651 / 8,000 verts, 14 bones, skinned, five slots, no issues.
passes: 6,407 / 16,000 tris, 6,651 / 16,000 verts, 14 bones, skinned, five slots, no issues.
Vision-reviewed: the head now reads as a realistic face, the hands as detailed fingers and
the shoes as attached. Remaining (manual retopology): a 1.63× arm-scale warp still distorts
the deltoid/shoulder, stray hand blobs linger at the hips, shirt/shirt seams are rough, and
@@ -299,9 +305,11 @@ licence-free zone only.
- [x] Hands/grip review: the hands ARE detailed — `tools/blender_assets.py._hands_and_shoes()`
builds a wider shallower palm, four two-segment bent fingers with rounded tips and a thumb;
gear contact is the open palm plus the `HAND_ITEM_FORWARD` (0.04 m) offset. Decision: **keep
the open palm + forward offset; a finger-curl rig stays out of scope** — there are no finger
bones in the 13-bone contract, so a curl rig is a contract decision, not a modelling tidy-up.
Recorded as ranked gap #6 (accept; revisit only if face work opens the budget).
the open palm + forward offset; a finger-curl rig stays out of scope** — the current rig has
no finger bones, so a curl rig is a contract decision, not a modelling tidy-up. Optional
extra finger bones are now allowed by the cap/contract extension, but require an ADR and
weight/budget verification. Recorded as ranked gap #6 (accept; revisit only if face work
opens the budget).
- [x] Weights/pose evidence captured and vision-reviewed, and the P1s fixed: wrist/hand
detachment (wrist + hand now 100% `Hand`, hand raised, sleeve cuff follows the hand),
hip/thigh collapse + knee pinch (thigh/shin rigid with a short knee blend). Vision-verified:
+7 -6
View File
@@ -24,9 +24,10 @@ severity, explicit verdict) rather than an opinion pass:
| Props, gear, foliage | `prop-artist`, `hard-surface`, `vegetation-artist` | Silhouette read, bevel/chamfer language, collision proxies, carded foliage |
| Look and verdict | `lookdev`, `qa-review` | Day/night beauty captures, ship / ship-with-notes / no-ship verdict |
Project contract and gates stay authoritative; see `AGENTS.md` §Local Blender skills. The skills
assume Blender MCP, which this project does not use: everything below came from the headless
`tools/blender_assets.py` / `tools/npc_pipeline.py` pipelines plus the Godot capture harnesses.
Project contract and gates stay authoritative; see `AGENTS.md` §Local Blender skills. Blender MCP
is optional interactive tooling (see [`blender-mcp.md`](blender-mcp.md)); this review's evidence
came from the headless `tools/blender_assets.py` / `tools/npc_pipeline.py` pipelines plus the
Godot capture harnesses, so it remains reproducible without MCP.
## What was captured and measured (2026-11-03)
@@ -63,14 +64,14 @@ with the runtime 4× fabric repeat).
| `npc_crowd_b` | 4,734 / 4,353 | 1.809 / +0.000 | 7 | 107–118 | 434–439 | Contract pass; crowd prototype |
| `npc_crowd_c` | 5,674 / 5,440 | 1.824 / +0.000 | 7 | 76–83 | 317 | Contract pass; crowd prototype |
| `npc_crowd_d` | 5,814 / 5,300 | 1.856 / +0.000 | 7 | 92–106 | 377–381 | Contract pass; crowd prototype |
| `npc_base` (fallback) | 1,204 / 2,488 | 1.836 / +0.000 | 5 | 70.1–72.9 | 4× on fabric | Contract pass; far below its 6,000/4,000 cap |
| `npc_base` (fallback) | 1,204 / 2,488 | 1.836 / +0.000 | 5 | 70.1–72.9 | 4× on fabric | Contract pass; compact fallback under the 16,000/16,000 cap |
Blender-side `inspect` counts can differ by ±1 vertex from the glTF accessor count in `audit`
(normal-split rounding); both are recorded and neither changes a verdict.
Readings:
- Every character is inside 8,000/8,000 with the farthest at 5,474 tris (68% of budget) and 5,494
- Every character is inside 16,000/16,000 with the farthest well below the new cap and 5,494
verts (69%), so there is headroom for targeted topology detail without a cap change.
- Surface area tracks clothing volume: the firefighter coat is the largest body (4.28 m²) and has
the lowest authored density; `npc_casual` is the smallest (2.44 m²) and the highest.
@@ -254,7 +255,7 @@ owner review decides.
brow ridge, a fuller lower lip and both eyelids (upper + lower); recessed creases (nasolabial,
temple, chin cleft) were rejected because they bake as dark AO patches. Vision-reviewed: the new
face reads cleaner and more realistic than the old (set-in eyes, brow break, lip volume, no
faceting); tris 4,482 → 5,038 (still under 8,000). The other seven variants keep the old face
faceting); tris 4,482 → 5,038 (still under 16,000). The other seven variants keep the old face
until this prototype is approved.
2. **No pose/weight evidence (unknown).** Idle, walk, sit, block and turn deformation has never been
captured as a review set, so shoulder/hip/neck collapse is unmeasured. Cheap to add and it
+1
View File
@@ -16,6 +16,7 @@ This folder holds the project documentation, visual references and generated QA
- [`architecture.md`](architecture.md) — arc42 system architecture
- [`getting-started.md`](getting-started.md) — setup, run/test commands and controls
- [`asset-tooling.md`](asset-tooling.md) — image/model pipelines and screenshot gates
- [`blender-mcp.md`](blender-mcp.md) — optional Blender MCP setup and safety
- [`../tools/README.md`](../tools/README.md) — tool inventory, categories and test runner
- [`gameplay.md`](gameplay.md) — controls, venues and escalation
- [`joke-shop-map.md`](joke-shop-map.md) — Sunset Strip real-site mapping
@@ -70,3 +70,14 @@ measured. None was a drop-in; the full results are in
polygon count, no rig in the base mesh and a separate authoring dependency.
- **Use Mixamo or Ready Player Me.** Rejected: service terms are not a simple
free/open-source redistribution basis for shipped meshes.
## Amendment 2026-11-04
- The character budget is raised to **16,000 triangles / 16,000 glTF vertices** per character.
The required 13 core bones remain; optional extra bones (fingers, face, toes) are allowed if
they do not move the core rest positions. The low-poly fallback remains the fallback, not a
second contract.
- MakeHuman is now an active local development pipeline (body retarget plus project-owned
head/hands), while the procedural library remains the shipped path and CI fallback.
- Blender MCP is optional interactive tooling only; it is not a build, CI, test or runtime
dependency. Setup is in [`docs/blender-mcp.md`](../blender-mcp.md).
+2 -2
View File
@@ -141,8 +141,8 @@ GLBs and maps.
| Tool | Role | Committed artifact | Verification gate |
| --- | --- | --- | --- |
| `tools/npc_pipeline.py` | Builds the skinned base avatar, five-slot material maps, palette and AI-fabric preparation (`prepare`/`palette`) | `npc_base.glb`, `assets/textures/npc/*_{albedo,normal,orm}.png`, `palette.json` | `audit_glb` against the frozen 6,000-triangle / 4,000-vertex base contract |
| `tools/blender_assets.py` | Builds/renders the library: 8 characters, 18 gear pieces, 20 props, plus `manifest.json`; stdlib `audit`/`fit`/`sheet`/`list` | `assets/models/blender/{npc,npc_gear,props}/*.glb` | Library cap 8,000 tris / 8,000 verts per character, 1,500 per gear, 4,000 per prop; grounding, UV, degenerate-triangle, attach-fit and manifest coverage checks |
| `tools/npc_pipeline.py` | Builds the skinned base avatar, five-slot material maps, palette and AI-fabric preparation (`prepare`/`palette`) | `npc_base.glb`, `assets/textures/npc/*_{albedo,normal,orm}.png`, `palette.json` | `audit_glb` against the 16,000-triangle / 16,000-vertex base contract (13 core bones required; extras allowed) |
| `tools/blender_assets.py` | Builds/renders the library: 8 characters, 18 gear pieces, 20 props, plus `manifest.json`; stdlib `audit`/`fit`/`sheet`/`list` | `assets/models/blender/{npc,npc_gear,props}/*.glb` | Character cap 16,000 tris / 16,000 verts, 1,500 per gear, 4,000 per prop; grounding, UV, degenerate-triangle, attach-fit and manifest coverage checks |
| `tools/bake_ao.py` | Bakes per-asset AO maps | `<asset>_ao.png` (256²) | Wired through `Materials.apply_ao()`/`SurfaceMaterials`; cloth/pants opt out (see below) |
| `tools/npc_proportions.py` | Measures exported GLB rest pose (height, head, shoulders, hips, torso, limbs, feet) against the stylized guide | report / JSON in `docs/npc-proportion-audit.md` | All eight variants must stay inside the guide after a body change |
| `tools/npc_baseline.py` | Assembles neutral-baseline sheets and before/after comparisons | `docs/blender_previews/sheet_npc_baseline*.jpg` | Human review against `docs/npc-visual-review.md` |
+11 -3
View File
@@ -189,7 +189,7 @@ Caveats:
`adapt` is the mechanical first half of an external-mesh intake (MakeHuman,
MPFB, downloaded GLB): import, apply transforms, ground the feet, weld seam
splits, decimate to the character budget, and export a GLB. It does **not** map
the five tint slots or rebuild the 13-bone `npc_base` armature — those stay a
the five tint slots or rebuild the 13-core-bone `npc_base` armature (optional extra bones are allowed) — those stay a
manual `retopology`/`rigging` step with a recorded second-rig contract if the
source rig cannot be retargeted:
@@ -198,8 +198,8 @@ flatpak run org.blender.Blender --background \
--python "$PWD/tools/blender_assets.py" -- adapt \
--file "$PWD/tmp/npc-research/makehuman_base.glb" \
--out "$PWD/tmp/npc-research/makehuman_adapted.glb" \
--target-tris 8000
# prints: adapted makehuman_adapted.glb: 36972 -> 8000 tris (bones=N, meshes=1)
--target-tris 16000
# prints: adapted makehuman_adapted.glb: 36972 -> 16000 tris (bones=N, meshes=1)
```
Run `inspect` on the adapted GLB before and after, and keep the procedural
@@ -343,6 +343,14 @@ python3 tools/model_pipeline.py audit
python3 tools/npc_pipeline.py audit
```
### Optional interactive Blender MCP
The headless pipeline above is authoritative. For local part exploration, an
optional Blender MCP bridge can query the scene, run small `bpy` snippets and
capture viewport screenshots. It is not a build, CI, test or runtime dependency;
setup, safety and the part workflow are in
[`blender-mcp.md`](blender-mcp.md).
## Realism pass: scene concepts, skylines and textures
The skyline, surface tiles and phase lighting were rebuilt against AI concept frames. The
+13 -7
View File
@@ -35,6 +35,12 @@ captures in `docs/screenshots/`.
doors, stair handrails and a dark sedan. Today's in-game props are primitive
boxes, and the trees are cones.
## Optional MCP
Blender MCP can be used for interactive head/face/hand part exploration, but it
is not required. The headless commands below remain the build and audit path;
see [`blender-mcp.md`](blender-mcp.md) for installation, connection and safety.
## Running it
```bash
@@ -98,12 +104,12 @@ All eight use the `npc_base` contract, so each one can replace
`Materials.npc_slot()` tints them the same way it tints `npc_base`. Cloth and
pants repeat the weave 4× (`NPC_FABRIC_UV_SCALE`) and intentionally skip the
per-character baked AO; skin, hair and fixed gear keep it.
- budget ≤ **8,000 triangles and ≤ 8,000 glTF vertices** for the eight library
variants (vertex count after seam splits; `CHAR_MAX_TRIS`/`CHAR_MAX_VERTS` in
`tools/blender_assets.py`, raised from 6,000/5,000 on 2026-11-02). The frozen
`npc_base` fallback keeps its original 6,000/4,000 contract. The current range
is 4,482–5,474 triangles and 4,260–5,494 vertices, leaving room for the
remaining grip and clothing detail.
- budget ≤ **16,000 triangles and ≤ 16,000 glTF vertices** per character (vertex count after
seam splits; `CHAR_MAX_TRIS`/`CHAR_MAX_VERTS` in `tools/blender_assets.py`). The 13 core bones
remain required; optional extra bones are allowed as long as the core rest positions and
`NpcAvatar` animation proxies are unchanged. The frozen low-poly `npc_base` fallback keeps its
compact geometry but is no longer capped at 6,000/4,000. The current range is 5,038–6,030
triangles and 4,756–5,902 vertices, leaving substantial head/hand headroom.
Construction: the torso and limbs are one continuous Skin-modifier mesh,
subdivided twice, decimated to 26 % with X symmetry, and cut at the waist, cuffs,
@@ -185,7 +191,7 @@ carry baked AO and the shared neutral material maps described above.
- `python3 tools/blender_assets.py audit`: container, `POSITION`/`NORMAL`/
`TEXCOORD_0`, UVs in [0, 1], no zero-area triangles (Godot warns about them
during LOD generation), budgets (library characters 8000/8000, base fallback 6000/4000, gear 1500, props 4000
during LOD generation), budgets (characters 16000/16000, gear 1500, props 4000
triangles), grounding, and an editable `.blend`. For characters it also
checks skinning, bones, slots, the `npc_base` mesh node and the height.
- `tools/tests/test_blender_assets.py`: catalogue and contract consistency with
+149
View File
@@ -0,0 +1,149 @@
# Optional Blender MCP
Status: **optional interactive tooling, not a build dependency.** Blender MCP is
useful for exploring a local part scene, moving the viewport and iterating on a
head/hand mesh without a manual UI walkthrough. The authoritative asset
pipeline remains the headless CLI plus `audit`/`fit`/`inspect`; CI, tests and
release builds must continue to work with no Blender process and no MCP server.
This project does not vend the third-party addon or pin a runtime MCP
dependency. Install it outside the repository and keep generated scenes under
`tmp/`.
## What it adds
With Blender MCP connected, an agent can:
- query the current scene and object data;
- run small `bpy` snippets through the MCP bridge;
- capture a viewport screenshot for visual checks;
- inspect or modify a local part scene before exporting a GLB.
It does **not** replace:
- `python3 tools/blender_assets.py audit/fit/inspect`;
- `python3 tools/npc_proportions.py`;
- the Godot capture and smoke gates;
- the project's licence/provenance review.
## Prerequisites
- Blender 5.2 LTS, installed as the `org.blender.Blender` flatpak (the project
standard).
- An MCP-capable client.
- The upstream [BlenderMCP addon](https://github.com/ahujasid/blender-mcp)
(`addon.py`) and its MCP server.
- `uv`/`uvx` if you use the server's `uvx blender-mcp` launcher; a local install
of the server package is equally valid.
Check the upstream README for the current package/addon version and any command
changes before installing. Do not copy the addon into this repository.
## Setup
### 1. Install the Blender addon
1. Download or clone the upstream BlenderMCP project.
2. In Blender: **Edit → Preferences → Add-ons → Install from Disk**, select
`addon.py` from that checkout.
3. Enable **Interface: Blender MCP**.
4. Open the 3D View sidebar (N panel), find the **BlenderMCP** tab, and click
**Connect to MCP server**. The default server listens on
`localhost:9876`.
The addon must be running inside the Blender process that has the scene open.
Starting a second Blender instance does not connect the first one.
### 2. Configure the MCP client
For Pi, add the server at user scope so it is not committed into the project:
```bash
pi mcp add blender -- uvx blender-mcp
pi mcp list
```
Then start/reload Pi and use `/mcp` to inspect the connection. Other clients
use their normal MCP server configuration. A generic JSON example:
```json
{
"mcpServers": {
"blender": {
"command": "uvx",
"args": ["blender-mcp"]
}
}
}
```
For a client with a different config schema, use the equivalent server command
and keep the server name `blender`. Restart/reload the client after adding it,
then request the tool list and run a harmless `get_scene_info` before editing.
### 3. Connect through the flatpak
Start Blender through the project's normal flatpak command, open the local part
scene, and connect from the sidebar. If the client cannot reach the addon:
- confirm the addon panel says connected;
- confirm the client is launching the MCP server, not just a shell;
- check port `9876` is not occupied;
- if the flatpak sandbox is blocking localhost networking, grant network
permission only for this interactive use, for example:
`flatpak override --user --share=network org.blender.Blender`
(review the permission change afterwards; do not add it to CI or build
scripts).
- restart both the MCP client and Blender after changing the addon or config.
## Recommended part-workflow
1. Create a local scene, for example
`tmp/npc-parts/npc_casual/head.blend`, or open a copy of an exported part GLB.
Never save over the tracked `assets/models/npc/npc_base.blend`.
2. Ask the MCP client for `get_scene_info`, then inspect the object/bone/mesh
names it reports.
3. Use `execute_blender_code` for small, reversible edits. Prefer adding a new
object or modifier over deleting existing geometry; keep a backup copy.
4. Use `get_viewport_screenshot` after camera/material changes to check the
head/face/hand before exporting.
5. Export a **local** GLB under `tmp/npc-parts/`, not directly into
`assets/models/`.
6. Run the normal gates on the exported file:
```bash
flatpak run org.blender.Blender --background \
--python "$PWD/tools/blender_assets.py" -- \
inspect --file "$PWD/tmp/npc-parts/head.glb" --category npc --json
python3 tools/blender_assets.py audit
python3 tools/blender_assets.py fit
python3 tools/npc_proportions.py report
```
7. Only after the part is reviewed and the contract passes should it be
assembled into a character and rebuilt through the headless pipeline.
## Safety and project rules
- MCP is **not** part of `project.godot`, the build, CI, tests, release packages
or runtime.
- Do not commit `.blend` part scenes, MCP configuration, API keys or generated
previews. The working set stays in `tmp/`.
- Do not use MCP to bypass the contract, budgets, AO/UV rules or licence gate.
- The 13 core bones must remain at their rest positions; extra optional bones
are allowed only if `NpcAvatar` and the audit/tests still pass.
- Prefer scripted headless changes for reproducible work; MCP is for the
interactive exploration and review that is awkward in a one-shot script.
- If MCP is unavailable, use the headless CLI and document the manual step; never
make the project depend on MCP being present.
## Troubleshooting
| Symptom | Check |
| --- | --- |
| Client cannot find `blender` | MCP client config path/schema; restart client; confirm server command exists |
| `Connection refused` | Addon **Connect to MCP server** pressed; Blender still running; port 9876 |
| Tools return stale scene data | Refresh scene/object query after edits; restart the connection if needed |
| Flatpak cannot reach localhost | Check flatpak network permission; grant only for interactive use |
| Changes look wrong in export | Re-import the GLB with `inspect`; check transforms, scale, UVs and materials |
| Contract audit fails | Fix the mesh/bones first; do not edit the audit expectations around a broken asset |
+2 -1
View File
@@ -62,7 +62,8 @@ Python tooling is 161/161 after the GLB `inspect` intake coverage.
- Texture visual verification (0.9.5 work): the nine-stage realism run used `z-ai/glm-5.3-flash` once per shot; mean `after` scores were overall 1.8, lighting 2.3, materials 1.8, texture detail 1.2, backdrop 2.0 and characters 1.2, with a Pillow metric gap of 0.306. The judge remains an optional review aid, not a CI gate. The committed before/after close-up sheet is [`blender_previews/sheet_texture_refinement_0.9.5.jpg`](blender_previews/sheet_texture_refinement_0.9.5.jpg); it records that the paver/Walk of Fame and NPC fabric repairs are visible, while asphalt, limestone and skyline picks held without a replacement. `tools/check_screenshots.sh` passed 21 good / 0 bad and the screen-design judge passed 21/21 match with 0 review.
- NPC visual optimization (0.9.4, complete 2026-11-02): all eight variants passed the portrait/readability, proportion, gear, foot/shoe, headgear and final-context gates. The library uses an 8,000-triangle / 8,000-glTF-vertex cap (up from 6,000/5,000; `npc_base` fallback remains 6,000/4,000); current characters measure 4,482–5,474 triangles and 4,260–5,494 vertices. The 48-frame baseline and 96-frame final-context review pass, the hand/gear offset and shoes are in, and the accepted stylized limits are documented in `npc-visual-review.md`.
- NPC face-detail pass (0.9.4 work): ala wings and a smaller nose bridge/tip, one rounded mouth slot, and a darker ear concha; all eight rebuilt. The comparison is `sheet_npc_baseline_compare-face-detail.jpg`.
- NPC face realism pass (2026-11-03/04): all eight variants now use the `seg=24/rings=16` head with a subtle brow ridge, a fuller lower lip and both eyelids (recessed creases were rejected because they bake as dark AO patches). Vision-reviewed as cleaner/more realistic than the 0.9.4 face; characters measure 5,038–5,900 tris / 4,756–5,902 verts (still under 8,000). `sheet_npc_baseline.jpg` was refreshed.
- Character contract extension (2026-11-04): the character cap is **16,000 triangles / 16,000 glTF vertices** (library and base fallback); the 13 core bones remain required and optional extra bones are allowed. Blender MCP is documented as optional interactive tooling in [`blender-mcp.md`](blender-mcp.md), not a build/CI/runtime dependency. Blender/NPC audits still pass.
- NPC face realism pass (2026-11-03/04): all eight variants now use the `seg=24/rings=16` head with a subtle brow ridge, a fuller lower lip and both eyelids (recessed creases were rejected because they bake as dark AO patches). Vision-reviewed as cleaner/more realistic than the 0.9.4 face; characters measure 5,038–5,900 tris / 4,756–5,902 verts (still under 16,000). `sheet_npc_baseline.jpg` was refreshed.
- Crowd-variety roster (character development, 2026-11-04): four new variants — `npc_crowd_a` (slim/bun/sunglasses), `npc_crowd_b` (broad/bald/beard/shoulder bag), `npc_crowd_c` (coat/umbrella), `npc_crowd_d` (slim/hood/cup) — built with the realistic face and wired into `CHARACTER_POOLS` so the routine crowd roles (tourist, confused visitor, intoxicated) pick them by seed instead of cloning `npc_casual`. The 24-NPC smoke is now 152,464 tris / 168 meshes / 6.94 ms (under the 50 ms budget).
- NPC headgear clearance (0.9.4 work): the 96-frame final-context review after the face-detail pass confirms the cap, firefighter helmet, hood and sunglasses clear the refined brow and eyes; no gear rebuild was needed.
- NPC footwear pass (0.9.4 work): casual shoes gained rounded toe and heel caps; responder/firefighter boots gained matching toe/heel volumes while retaining the black rubber boot language. All eight rebuilt; comparison `sheet_npc_baseline_compare-shoes.jpg`.
+5 -5
View File
@@ -28,7 +28,7 @@ Any expansion must preserve the existing integration contract:
`Hips`, `Spine`, `Neck` at the contract rest positions;
- five tint slots (`skin`, `cloth`, `pants`, `accessory`, `hair`);
- front on Blender −Y / Godot +Z, feet near the floor, 1.6–2.1 m height;
- at most 8,000 triangles and 8,000 glTF vertices per character;
- at most 16,000 triangles and 16,000 glTF vertices per character;
- gear attach points at head, back, chest and hand.
The existing `audit` command is the gate. A source that looks good in a preview
@@ -68,8 +68,8 @@ Every example fails the unmodified `audit` contract:
| `npc_base` mesh node | no | no | no | no | no |
| Required 13 bones | no (62 different names) | no rig | no (19 different names) | no (19 different names) | no rig |
| Five tint slots | no | no | no | no | no |
| ≤ 8,000 tris | yes | yes | yes | yes | no |
| ≤ 8,000 verts | no (10.5–13k) | yes | yes | yes | no (19k) |
| ≤ 16,000 tris | yes | yes | yes | yes | yes |
| ≤ 16,000 verts | yes (10.5–13k) | yes | yes | yes | no (19k) |
| Feet on floor | yes | yes (2.7 m scale) | yes (−11 mm) | yes | no (needs scaling) |
| Height 1.6–2.1 m | yes | no (2.7 m) | no (1.45 m) | no (1.48 m) | needs scale |
| Skinned / UV mapped | yes / yes | no / yes | yes / yes | yes / no | no / no |
@@ -211,7 +211,7 @@ the A-pose arms down (−38°/+38°) and scales them **1.63×** to the contract
arm, welds the split vertices, smooth-shades, adds the 13-bone contract armature
with the project's distance-to-bone `_auto_weights`, paints the five slot regions,
renames the mesh to `npc_base`, and exports `makehuman_retargeted.glb` — **6,444 /
8,000 tris, 7,726 / 8,000 verts**, 14 bones, skinned, arm-down, grounded, five
16,000 tris, 7,726 / 16,000 verts**, 14 bones, skinned, arm-down, grounded, five
slots, no contract issues. The proportion warp (1.63× arms) is the same class of
issue that blocked Quaternius; here it is accepted, but the vision review shows
it distorts the deltoid/shoulder, the decimated hands are blocky, and the slot
@@ -283,7 +283,7 @@ are:
- Weld duplicate seam vertices before decimating. Quaternius' 12k imported
vertices are mostly UV/normal splits; the underlying surface is much smaller,
but the glTF budget counts the splits after export.
- Decimate to a target below 8,000 tris/verts, then re-unwrap only if the
- Decimate to a target below 16,000 tris/verts, then re-unwrap only if the
existing UVs cannot survive the material remap. The current library uses
smart projection at 80° to keep islands large.
- Map materials by semantic role, not by source name. A source "Purple" or
+5 -5
View File
@@ -71,9 +71,9 @@ The criteria below are for the stylized target, not photorealism. A change must
pass every applicable item before a library rebuild is accepted.
1. **Asset contract:** `npc_base` mesh node, the required bones, five tint slots,
front +Z, feet within 3 cm of y=0, 1.6–2.1 m height, at most 8,000 triangles
and 8,000 glTF vertices per library character. The frozen `npc_base` fallback
keeps 6,000 triangles / 4,000 vertices. Gear remains at most 1,500 triangles.
front +Z, feet within 3 cm of y=0, 1.6–2.1 m height, at most 16,000 triangles
and 16,000 glTF vertices per character. The required 13 core bones stay fixed;
optional extra bones are allowed. Gear remains at most 1,500 triangles.
2. **Proportion and silhouette:** head, neck, shoulders, torso, hips, limbs and
feet read as one body; front/three-quarter/profile silhouettes agree with the
rest of the eight-character library; broad/slim/average build variation is
@@ -134,8 +134,8 @@ From `python3 tools/blender_assets.py fit` and the manifest:
| `npc_firefighter` | 5,344 | 5,494 | 0.315 m | 0.255 m (skirt) | helmet width ratio 1.651; SCBA x −0.105, radial −0.076 |
| `npc_guard` | 5,046 | 5,096 | 0.315 m | 0.194 m (hip) | cap width ratio 1.067 |
`npc_coat` is widest at 5,474 triangles (2,526 below the 8,000 cap);
`npc_firefighter` is closest on vertices at 5,494 (2,506 below the 8,000 cap).
`npc_coat` is widest at 5,474 triangles (well below the 16,000 cap);
`npc_firefighter` is closest on vertices at 5,494 (well below the 16,000 cap).
The refit backpack measures 380 triangles / 406 vertices.
## Baseline findings, ranked
+15 -13
View File
@@ -53,13 +53,14 @@ MANIFEST = OUT_DIR / "manifest.json"
SLOTS = ["skin", "cloth", "pants", "accessory", "hair"]
BONES = ["Head", "HipL", "HipR", "KneeL", "KneeR", "ShoulderL", "ShoulderR",
"ElbowL", "ElbowR", "HandL", "HandR"]
# The eight library variants may use more geometry than the frozen npc_base
# fallback (6000 tris / 4000 verts). Raised to 8000/8000 on 2026-11-02 so the
# remaining face, hand-grip and clothing work is not forced to replace detail.
# The glTF vertex count is after UV-seam splits; each avatar is still one
# skinned mesh, and `smoke_npc_budget.gd` must confirm the 24-NPC frame time.
CHAR_MAX_TRIS = 8000
CHAR_MAX_VERTS = 8000
# Character cap raised to 16000/16000 on 2026-11-04 for the head/face/hand
# overhaul and possible MakeHuman parts. The required 13 core bones stay, but
# optional extra bones (fingers, face, toes) are allowed; they must not move the
# core rest positions. The glTF vertex count is after UV-seam splits; each
# avatar is still one skinned mesh, and `smoke_npc_budget.gd` must confirm the
# 24-NPC frame time before accepting the increase.
CHAR_MAX_TRIS = 16000
CHAR_MAX_VERTS = 16000
GEAR_MAX_TRIS = 1500
PROP_MAX_TRIS = 4000
@@ -2135,14 +2136,15 @@ def inspect_glb(path, category=None) -> dict:
return result
def adapt_glb(path, out_path, target_tris=8000):
def adapt_glb(path, out_path, target_tris=16000):
"""Import an external GLB and adapt it toward the library contract.
Applies node transforms, grounds the feet (lowest vertex at y = 0), welds
duplicated seam vertices and decimates to `target_tris`, then exports the
result to `out_path` as a GLB. The five tint slots and the 13-bone contract
armature are deliberately NOT auto-mapped — that is a manual retopology/rig
step. Returns before/after measurements for the intake report.
result to `out_path` as a GLB. The five tint slots and the required 13 core
bones (optional extra bones are allowed) are deliberately NOT auto-mapped —
that is a manual retopology/rig step. Returns before/after measurements for
the intake report.
"""
if bpy is None:
return {"ok": False, "error": "adapt must run inside Blender"}
@@ -2537,8 +2539,8 @@ def main(argv=None):
ada.add_argument("--file", required=True,
help="external GLB to adapt (absolute path; runs in Blender)")
ada.add_argument("--out", required=True, help="where to write the adapted GLB")
ada.add_argument("--target-tris", type=int, default=8000,
help="decimate target (default 8000)")
ada.add_argument("--target-tris", type=int, default=16000,
help="decimate target (default 16000)")
tex = sub.add_parser("texels", help="per-slot texel density of the character GLBs")
tex.add_argument("--only", default="")
tex.add_argument("--json", action="store_true")
+4 -3
View File
@@ -23,7 +23,8 @@ Contract (frozen in ADR-0013 and docs/blender-assets.md):
(plus Hips/Spine/Neck as parents)
* material slots: skin, cloth, pants, accessory, hair
* neutral albedo + normal + packed ORM maps, albedo tinted at runtime
* <= 6000 triangles / 4000 vertices, UVs in [0,1], feet at y ~= 0
* <= 16000 triangles / 16000 vertices, UVs in [0,1], feet at y ~= 0
* the 13 core bones are required; extra optional bones are allowed
"""
import argparse
@@ -44,8 +45,8 @@ BONES = [
"Head", "HipL", "HipR", "KneeL", "KneeR",
"ShoulderL", "ShoulderR", "ElbowL", "ElbowR", "HandL", "HandR",
]
MAX_TRIANGLES = 6000
MAX_VERTICES = 4000
MAX_TRIANGLES = 16000
MAX_VERTICES = 16000
TEX_SIZE = 256
AI_DIR = TEX_DIR / "ai"
# Base material slots that get an AI fabric albedo (`prepare` layers them over
+14 -8
View File
@@ -9,11 +9,10 @@ class CatalogueTests(unittest.TestCase):
def test_contract_matches_npc_pipeline(self):
self.assertEqual(ba.SLOTS, npc_pipeline.SLOTS)
self.assertEqual(sorted(ba.BONES), sorted(npc_pipeline.BONES))
# The base mesh keeps the frozen 6000/4000 contract; the eight library
# variants have their own 8000/8000 detail budget (documented in
# blender-assets.md and covered by smoke_npc_budget.gd).
self.assertLessEqual(ba.CHAR_MAX_TRIS, 8000)
self.assertLessEqual(ba.CHAR_MAX_VERTS, 8000)
# The character cap was raised to 16000/16000 for the head/face/hand
# overhaul; the 13 core bones stay required and extra bones are optional.
self.assertLessEqual(ba.CHAR_MAX_TRIS, 16000)
self.assertLessEqual(ba.CHAR_MAX_VERTS, 16000)
def test_gear_uses_known_attach_points(self):
for name, attach in ba.GEAR.items():
@@ -188,10 +187,17 @@ class InspectionTests(unittest.TestCase):
self.assertEqual(result["bones_missing"], [])
self.assertEqual(result["budget"]["max_triangles"], ba.CHAR_MAX_TRIS)
def test_extra_optional_bones_are_allowed(self):
stats = self.stats(bones=list(ba.BONES) + ["Hips", "Spine", "Neck",
"FingerL", "FingerR"])
result = ba.analyse_inspection(stats)
self.assertTrue(result["ok"], result["issues"])
self.assertEqual(result["bones_missing"], [])
def test_character_contract_failures_are_listed(self):
stats = self.stats(mesh_nodes=["Armature"], skinned=False, unskinned=["Armature"],
materials=["cloth"], bones=["Head"], meshes_without_uv=1,
triangles=9000, split_vertices=9000,
triangles=17000, split_vertices=17000,
world_bounds={"min": [-0.3, -0.4, -0.2], "max": [0.3, 1.2, 0.2]})
issues = "\n".join(ba.analyse_inspection(stats)["issues"])
self.assertIn("no mesh node named npc_base", issues)
@@ -199,8 +205,8 @@ class InspectionTests(unittest.TestCase):
self.assertIn("missing material slot skin", issues)
self.assertIn("mesh not skinned", issues)
self.assertIn("mesh(es) without UVs", issues)
self.assertIn(f"triangles 9000 > {ba.CHAR_MAX_TRIS}", issues)
self.assertIn(f"glTF vertices 9000 > {ba.CHAR_MAX_VERTS}", issues)
self.assertIn(f"triangles 17000 > {ba.CHAR_MAX_TRIS}", issues)
self.assertIn(f"glTF vertices 17000 > {ba.CHAR_MAX_VERTS}", issues)
self.assertIn("feet not on the ground", issues)
self.assertIn("unexpected height", issues)
+2 -2
View File
@@ -13,8 +13,8 @@ class NpcContractTests(unittest.TestCase):
"ShoulderL", "ShoulderR", "ElbowL", "ElbowR",
"HandL", "HandR"]:
self.assertIn(bone, npc_pipeline.BONES)
self.assertLessEqual(npc_pipeline.MAX_TRIANGLES, 6000)
self.assertLessEqual(npc_pipeline.MAX_VERTICES, 4000)
self.assertLessEqual(npc_pipeline.MAX_TRIANGLES, 16000)
self.assertLessEqual(npc_pipeline.MAX_VERTICES, 16000)
def test_textures_exist_for_every_slot(self):
for slot in npc_pipeline.SLOTS: