Files
security-game/docs/npc-model-sourcing.md
T

15 KiB
Raw Blame History

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 and 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.

  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.