Research NPC model sources and plan 0.11.0 expansion

This commit is contained in:
zwitschi committed 2026-11-03 07:46:47 +01:00
1 parent 46f1e41874
commit bfe3c5a701
6 files changed
+324

No files matched your search

+11
View File
@@ -4,6 +4,17 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o
## Decisions ## Decisions
- **NPC model sourcing research (2026-11-03):** `docs/npc-model-sourcing.md` evaluates
Quaternius Ultimate Modular (CC0), Kenney Blocky Characters (CC0), Khronos
CesiumMan/RiggedFigure (CC-BY 4.0) and the MakeHuman base mesh (CC0). No download is a
drop-in: every source lacks the `npc_base` node, the 13 contract bones and the five tint
slots; Quaternius additionally exceeds the vertex budget (10.5k–13k imported) and uses a
62-bone T-pose rig, CesiumMan/RiggedFigure are short technical references, and the
MakeHuman base is ~19k verts with no rig. Downloaded files stay under
`tmp/npc-research/` (gitignored), with SHA-256 provenance in the doc. The direction is
pending owner review; default if unreviewed is procedural expansion. Do not commit or
ship an external model before the licence/ADR decision.
- **0.10.0 balance protocol:** `docs/balance-acceptance.md` defines targets and - **0.10.0 balance protocol:** `docs/balance-acceptance.md` defines targets and
denominator/cohort rules for the 36 venue/difficulty/phase cells, seeds 1–100, denominator/cohort rules for the 36 venue/difficulty/phase cells, seeds 1–100,
access/emergency error rates and matched calm vs emergency-first comparisons. access/emergency error rates and matched calm vs emergency-first comparisons.
+1
View File
@@ -189,3 +189,4 @@ The game should feel like a tense workplace simulation with occasional crisis mo
- A rare Bob Dobbs cameo (Easter-egg appearance; placement note in `MEMORY.md`). - A rare Bob Dobbs cameo (Easter-egg appearance; placement note in `MEMORY.md`).
- Specific unusual NPC behaviors, such as slapping their own face, using hands as scissors, or interacting with props unexpectedly. - Specific unusual NPC behaviors, such as slapping their own face, using hands as scissors, or interacting with props unexpectedly.
- Live 3D body-camera replay; additional venues or seasonal events; real voice/dialogue audio; an image-to-mesh prop pipeline. - Live 3D body-camera replay; additional venues or seasonal events; real voice/dialogue audio; an image-to-mesh prop pipeline.
- More varied NPC silhouettes (age, build, hair and outfit), using either an extended procedural character generator or a reviewed CC0/CC-BY source; the evaluation and pending decision are in `docs/npc-model-sourcing.md`.
+60
View File
@@ -196,6 +196,66 @@ verify every distribution path. This is the next minor release after the 0.9.x p
- [ ] Exit: the release candidate is content-locked, externally played, legally reviewed, - [ ] Exit: the release candidate is content-locked, externally played, legally reviewed,
documented, reproducibly built, and approved as the 0.10.0 release candidate. documented, reproducibly built, and approved as the 0.10.0 release candidate.
## Milestone 0.11.0 — NPC model variety
Goal: break the eight-character clone effect with a reviewed, licence-cleared set of new NPC
looks while keeping the frozen `npc_base` bone, tint-slot and gear-attach contract. Start only
after the 0.10.0 release candidate is published; this milestone must not delay the release.
### 0.11.1 Source review and decision
- [x] Research free/open-source character sources and evaluate at least three downloads against
the existing Blender contract. (Measured Quaternius CC0, Kenney CC0, Khronos
CesiumMan/RiggedFigure CC-BY and the MakeHuman CC0 base mesh; none is a drop-in.
Results, local preview sheet and SHA-256 provenance are in
`docs/npc-model-sourcing.md`.)
- [ ] Review the sourcing research with the project owner and choose Option A (procedural),
Option B (Quaternius CC0 intake) or Option C (MakeHuman/MPFB body pipeline); record the
decision in an ADR and in `MEMORY.md`.
- [ ] Add a source licence allow-list and provenance rule: CC0 preferred, CC-BY only with
attribution in `CREDITS.md`, and no service assets whose terms restrict redistribution.
- [ ] Decide whether the external preview sheet stays local under `tmp/` or is committed with
the required CC-BY attribution.
### 0.11.2 Intake and validation
- [ ] Add a Blender `inspect` path that imports a GLB, applies node transforms, reports
tris/verts, bounds, bones, materials, UVs and skinning, and lists contract failures.
- [ ] Add an `adapt` path that scales/grounds the mesh, welds seams, decimates to the
triangle/vertex budget, maps materials into the five tint slots, rebuilds the contract
armature, transfers weights and writes the `npc_base` node name.
- [ ] Keep `tools/blender_assets.py audit` as the single final gate; add a regression test for the
intake report/adaptation using a deterministic synthetic or licence-cleared fixture.
- [ ] Document the adapter commands and the go/no-go checks in `docs/asset-tooling.md`.
### 0.11.3 One-character prototype
- [ ] Adapt one Quaternius CC0 variant and capture front, three-quarter, profile, back,
full-body and crowd views plus a walk cycle.
- [ ] Measure the prototype against the `npc_casual` controls: silhouette, face style, hands,
gear fit, rest pose and walk pose.
- [ ] Make a go/no-go decision on Option B; if no-go, remove the prototype from the pipeline and
continue with Option A.
### 0.11.4 Roster and runtime
- [ ] Approve four new looks (age/build/hair/outfit variation across everyday, workwear and
responder families; no clothing that labels the NPC's behaviour).
- [ ] Build or adapt the approved variants and add them to the manifest with roles and tint data.
- [ ] Replace the fixed `character_model_for()` mapping with deterministic per-role pools and add
tests for repeatability and duplicate avoidance.
- [ ] Rebuild and verify gear fit for every new variant (`blender_assets.py fit` plus the runtime
gear checks).
### 0.11.5 QA and release
- [ ] Run the 24-NPC budget smoke, portrait baseline, gear fit, headless suite and a release build
with the expanded library.
- [ ] Update `CREDITS.md`, `docs/development-status.md`, `docs/npc-visual-review.md` and
`CHANGELOG.md`; record any accepted visual limits.
- [ ] Exit: a reviewed 12-character library passes contract audit, portrait/gear acceptance,
the 24-NPC budget and licence/provenance review without changing the runtime contract.
## Future 0.x / non-blocking candidates ## Future 0.x / non-blocking candidates
- [ ] Live 3D body-camera replay. - [ ] Live 3D body-camera replay.
+1
View File
@@ -13,6 +13,7 @@ This folder holds the project documentation, visual references and generated QA
- [`asset-tooling.md`](asset-tooling.md) — image/model pipelines and screenshot gates - [`asset-tooling.md`](asset-tooling.md) — image/model pipelines and screenshot gates
- [`npc-visual-review.md`](npc-visual-review.md) — NPC visual baseline, acceptance criteria and ranked gaps - [`npc-visual-review.md`](npc-visual-review.md) — NPC visual baseline, acceptance criteria and ranked gaps
- [`npc-proportion-audit.md`](npc-proportion-audit.md) — NPC proportion ratios and stylized guide results - [`npc-proportion-audit.md`](npc-proportion-audit.md) — NPC proportion ratios and stylized guide results
- [`npc-model-sourcing.md`](npc-model-sourcing.md) — free/open-source character sources, contract evaluation and the 0.11.0 expansion plan
- [`development-status.md`](development-status.md) — implemented features and current gaps - [`development-status.md`](development-status.md) — implemented features and current gaps
- [`accessibility.md`](accessibility.md) — accessibility statement and known gaps - [`accessibility.md`](accessibility.md) — accessibility statement and known gaps
- [`known-limitations.md`](known-limitations.md) — release-candidate blockers and accepted limits - [`known-limitations.md`](known-limitations.md) — release-candidate blockers and accepted limits
+4
View File
@@ -129,6 +129,10 @@ with colliders/avoidance and drives their emissive parts from the day/night
cycle. The single `npc_base.glb` and primitive props remain offline fallbacks. cycle. The single `npc_base.glb` and primitive props remain offline fallbacks.
Contract and integration notes: [`blender-assets.md`](blender-assets.md). Contract and integration notes: [`blender-assets.md`](blender-assets.md).
Sourcing and expansion research (no external model is shipped yet):
[`npc-model-sourcing.md`](npc-model-sourcing.md) compares Quaternius, Kenney, Khronos and
MakeHuman sources against the character contract and records the pending 0.11.0 decision.
| Characters | Props | | Characters | Props |
| --- | --- | | --- | --- |
| ![characters](../docs/blender_previews/sheet_npc.jpg) | ![props](../docs/blender_previews/sheet_props.jpg) | | ![characters](../docs/blender_previews/sheet_npc.jpg) | ![props](../docs/blender_previews/sheet_props.jpg) |
+247
View File
@@ -0,0 +1,247 @@
# NPC model sourcing and expansion plan
Status: **research complete, direction not chosen (2026-11-03).** No downloaded
model is committed to the game or included in a release. The local evaluation
files live under `tmp/npc-research/` (gitignored).
This page records the free/open-source character sources that were reviewed, how
they behave when imported into the existing Blender tooling, and the options for
creating a larger NPC model library. The runtime contract and current library are
documented in [`blender-assets.md`](blender-assets.md) and
[`npc-visual-review.md`](npc-visual-review.md).
## Why this review exists
The library has eight skinned characters, and `NpcAvatar.character_model_for()`
reuses them across role families. That is enough for a release candidate, but
crowds repeat the same faces, builds and outfits. Three venues, a 24-NPC budget
and close-up portraits make that repetition visible.
Any expansion must preserve the existing integration contract:
- mesh node `npc_base` under a `Skeleton3D`;
- bones `Head`, `HipL/R`, `KneeL/R`, `ShoulderL/R`, `ElbowL/R`, `HandL/R` plus
`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;
- gear attach points at head, back, chest and hand.
The existing `audit` command is the gate. A source that looks good in a preview
but fails `audit` is not usable without an adaptation step.
## What was evaluated
Blender 5.2.0 LTS (Flatpak) imported each file in background mode. Measurements
below come from the imported scene, because external GLBs often carry node
transforms that the project's audit (which reads accessor-local bounds) does not
apply. "Vertices" are the imported, seam-split counts that matter for the glTF
budget, not the source file's vertex count.
| Source | Licence | Files checked | Geometry / rig | Height | Verdict |
| --- | --- | --- | --- | --- | --- |
| **Quaternius Ultimate Modular Men / Women** (mirrored GLB pack) | CC0 1.0 | `Casual_Hoodie.glb`, `Worker.glb`, `Casual.glb` | 5,240–6,424 tris; 10,534–12,968 verts; 62 bones; 24 animations; 4 skinned meshes on one armature | 1.80–1.87 m | **Best silhouette/outfit match.** Fails the contract: wrong bone names/rest positions, no tint slots, no `npc_base` node, vertex budget exceeded. |
| **Kenney Blocky Characters 2.0** | CC0 1.0 | full pack (18 characters), `character-a.glb`, `character-f.glb` | 72 tris; 143 verts; static, no armature; one texture atlas per character | 2.7 m imported (needs 0.67× scale) | **Not a close-up character.** Useful as a crowd/impostor LOD or placeholder, but cannot be driven by the skeleton and has no separate face/clothing slots. |
| **Khronos CesiumMan** | CC BY 4.0 (© Cesium) | `CesiumMan.glb` | 4,672 tris; 3,273 verts; 19-bone walk rig; 1 material/texture; 1 animation | 1.45 m | **Technical retarget test only.** One outfit and one look, wrong rig, short; works as a skinning/pose reference. Attribution is required. |
| **Khronos RiggedFigure** | CC BY 4.0 (© Cesium) | `RiggedFigure.glb` | 256 tris; 370 verts; 19-bone walk rig; no UVs; 1 animation | 1.48 m | **Rig smoke test only.** A mannequin with no usable surface detail. |
| **MakeHuman core base mesh / MPFB** | Core assets CC0 1.0; application AGPL/GPL | `makehuman/data/3dobjs/base.obj` | 19,158 verts; 18,486 polygons; 36,972 tris; no rig in the base mesh | ~16.9 model units before scaling | **Best body-shape diversity, highest pipeline cost.** Needs scaling, decimation/retopology and a generated rig. The MakeHuman/MPFB tool itself is not bundled. |
Local review sheet (front views, not committed):
`tmp/npc-research/previews/contact_sheet.jpg`.
Rejected without downloading: Mixamo and Ready Player Me. Both are useful
services, but their terms are not a simple free/open-source redistribution basis
for shipped character meshes. Sketchfab, Poly Pizza and OpenGameArt can contain
excellent CC0 work, but each asset needs a case-by-case licence and provenance
check; they are not a consistent library source.
### Measured contract failures
Every example fails the unmodified `audit` contract:
| Check | Quaternius | Kenney | CesiumMan | RiggedFigure | MakeHuman base |
| --- | --- | --- | --- | --- | --- |
| `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) |
| 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 |
The practical conclusion is that **there is no drop-in download**. External
sources need a deliberate intake step, and the expensive part is not decimation:
it is rebuilding or retargeting the skeleton and material slots without breaking
the animation proxies and gear placement.
The table uses Blender-imported world bounds. The stdlib `audit` reads accessor-local
bounds and ignores node transforms, so an unapplied external GLB can fail floor/height
checks even when the imported scene looks correct. The intake step must apply
transforms before it measures and exports.
## Options
### Option A — extend the procedural generator
Add more variation to `tools/blender_assets.py` rather than importing models:
body builds, height ranges, head/face shapes, hair and facial hair, outfit
layers, and more `CHARACTERS` specs. This keeps a single owned style, needs no
third-party licence review, and stays inside the existing builder/audit flow.
- **Strengths:** lowest integration risk, deterministic, no new dependencies.
- **Limits:** the current face and clothing vocabulary is intentionally simple;
more variants may still read as the same model with a different coat.
- **Best for:** a quick 4–8 variant expansion and filling obvious role gaps.
### Option B — Quaternius CC0 intake with a contract adapter
Use Quaternius meshes as silhouette/outfit donors and adapt them to the project
contract. The visible result is a different body/clothing language from the
current library, so the adapter must also normalise head/hand style or rebuild
those parts.
- **Strengths:** best free outfit/hair variety, animations included, CC0,
already close to game proportions, front axis and floor contact.
- **Work:** weld/decimate to the vertex budget, remap materials to the five
slots, rebuild the armature at the contract rest positions, transfer weights,
repose/normalise proportions, rename the mesh node, export, audit and compare
in the acceptance harness.
- **Main risk:** retargeting a 62-bone T-pose rig to the 13-bone arm-down
contract. Hip/knee rest heights differ substantially (Quaternius upper leg
starts near 0.96 m; the contract hip starts near 0.62 m), so a naive
nearest-bone weight transfer can produce a good still image and bad walk
poses. Prototype one character before committing to a roster.
- **Best for:** a larger, visibly different library if the prototype passes the
portrait and walk gates.
### Option C — MakeHuman/MPFB body-shape pipeline
Generate a range of ages, builds and body shapes from the CC0 MakeHuman base
mesh, then replace the head/hands and dress them with project-owned clothing.
This is the strongest answer to "everyone has the same body", but requires an
offline authoring step, decimation/retopology and a custom rig/weight step. It
should be treated as a later pipeline project, not a quick content drop.
## Recommended direction
1. **Do not add raw external models.** Keep the current library and contract
unchanged until a human has reviewed this page.
2. **Prototype Option B once** (one Quaternius character) behind a new intake
command. If the walk pose, face style and gear fit pass, use it for a small
set of silhouette donors and keep the project's faces/hands where possible.
3. **Fall back to Option A** for the remaining variants. Procedural variation
(age, build, hair, outfit colour/layers, accessory mix) is cheaper and keeps
the library coherent.
4. **Defer Option C** until the release candidate is out and there is a concrete
need for body-shape diversity that A/B cannot meet.
This is a proposal, not a decision. The review questions are at the end of the
page.
## Provisional NPC roster
The design rule stays: clothes, props and behaviour carry the read; a model must
not label a person as "the threat". The roster therefore adds ordinary adults
across age, build and style, not costumes that telegraph the outcome.
| Look family | Current | Proposed additions | Variation axes |
| --- | --- | --- | --- |
| Everyday | `npc_casual`, `npc_jacket`, `npc_coat`, `npc_hoodie`, `npc_dress` | older casual, denim jacket, short coat, open hoodie, second dress | age, build, height, hair, facial hair, outfit colour |
| Workwear | `npc_vest`, `npc_guard` | second hi-vis build, venue-security build, cleaner/vendor apron | build, height, headwear, badge/radio gear |
| Responder | `npc_firefighter` | paramedic/medical responder (only if the design supports it) | turnout vs medical kit, build, helmet |
| Crowd/LOD | none | Kenney blocky or a decimated library variant for distant crowds | silhouette and palette only |
A first target is **12 library characters** (the current eight plus four new
looks), not twenty. That is enough to break the clone effect without doubling
the portrait QA matrix. The existing `character_model_for()` mapping becomes a
pool per role family with a deterministic seed choice; the current two-way
alternation for guests, trespassers and threats is the template.
## Implementation plan
The actionable tasks live in `TODO.md` under milestone 0.11.0. The workstreams
are:
1. **Decision and licence gate.** Review this page, choose A/B/C, record the
decision in an ADR, and add a source allow-list (CC0 preferred; CC-BY only
with attribution in `CREDITS.md`; no service assets whose terms restrict
redistribution).
2. **Intake/validator.** Add an `inspect` report and an `adapt` path. The
validator should check bones, rest positions, node name, slots, budgets,
ground/height, UVs and skinning before and after adaptation. Keep the
existing `audit` as the final gate rather than creating a second contract.
3. **One-character prototype.** Adapt a single Quaternius CC0 variant; capture
front/three-quarter/profile/full-body/crowd views and a walk cycle; compare
against `npc_casual` and `sheet_npc_baseline.jpg`. Stop if the retarget does
not pass.
4. **Roster build.** Add four approved variants, update the manifest, and extend
the runtime selection pools. Rebuild gear fit and check each new variant with
the existing acceptance criteria.
5. **QA and integration.** Run the 24-NPC budget, portrait baseline, gear fit,
headless suite and release build. Record provenance and any accepted limits.
Only then update `CHANGELOG.md` and `docs/development-status.md`.
### Adapter notes
- Apply node transforms before measuring or exporting. CesiumMan imports with a
Z-up root and an `Icosphere` helper object; exclude helpers, not just the mesh
names, when measuring.
- 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
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
"Worker_Vest" needs an explicit mapping to `cloth`, `pants`, `skin`, `hair` or
`accessory`; do not rely on colour heuristics.
- Rebuild the armature at the contract rest positions and transfer weights, or
prove that a renamed external rig produces the same rest and pose behaviour.
Do not add a second skeleton format to `NpcAvatar`.
- Keep the face direction unambiguous. The front is Blender −Y; verify it with
a capture, not by guessing from the source file.
## Review questions
The project owner should answer these before the 0.11.0 work starts:
1. Are third-party CC0 characters acceptable in shipped game assets, or should
the library stay entirely project-owned?
2. If yes, is the Quaternius CC0 pack acceptable as a silhouette/outfit donor
with a rebuilt project-style head and hands?
3. Which four role families would benefit most from a new look: everyday
guests, workwear, responders, or crowd variety?
4. Is the MakeHuman/MPFB body-shape pipeline worth a later investment, or is
procedural variation enough?
5. Should the preview sheet be committed as a review artefact (with attribution
for the CC-BY entries), or stay local under `tmp/`?
Until those answers exist, the safe default is **Option A: extend the owned
procedural generator and keep external models as references only.**
## Downloaded example provenance
Files were downloaded on 2026-11-03 and kept out of version control:
| File | Source | SHA-256 |
| --- | --- | --- |
| `quaternius/Casual_Hoodie.glb` | `raw.githubusercontent.com/LuanDucate/Ducz.CharacterCreator/HEAD/public/models/Male/Casual_Hoodie.glb` (Quaternius CC0) | `f5b722199f7628b24550989af4230f65d5230727df9c326fd2b3e360effe5249` |
| `quaternius/Worker.glb` | same mirror, `Male/Worker.glb` | `8d0f454336c2effc5c08f63a177af3a82d1a7af025ca9588b40e4c90c4703534` |
| `quaternius/Casual.glb` | same mirror, `Female/Casual.glb` | `bc2d84fba249ebaa0629cb9d133ad37234196e4b8004aa205a6397abed04e05c` |
| `kenney_blocky_characters.zip` | `kenney.nl/assets/blocky-characters` | `5e123859aa0c1598342b600c6db197024a1d63eb9ec531398b310725f589887e` |
| `khronos/CesiumMan.glb` | `github.com/KhronosGroup/glTF-Sample-Assets` | `b7001eaeea8254bd44773bcd247e78696d94169388fbb2a1800fc69434e777d9` |
| `khronos/RiggedFigure.glb` | same repository | `d6be85417d3e256861ee733eea6916093a7af7c79c16366181fd8abcaeb38cf5` |
| `makehuman/base.obj` | `github.com/makehumancommunity/makehuman/blob/master/makehuman/data/3dobjs/base.obj` | `8e761e6624b8f54536409135d1636da63b32486a90d4897f84e121d144f6fb4c` |
Source terms:
- Quaternius packs are CC0 1.0 according to the pack page and the mirror's
credits. The mirror is a convenience download; the original pack page is
<https://quaternius.com/packs/ultimatemodularcharacters.html>.
- Kenney Blocky Characters 2.0 is CC0 1.0; the pack's `License.txt` is included
in the download.
- CesiumMan and RiggedFigure are CC BY 4.0, © 2017 Cesium. If any derivative is
committed or shipped, the attribution must be added to `CREDITS.md`.
- MakeHuman core assets are CC0 per `LICENSE.ASSETS.md`; the application source
is AGPL and is not bundled.