Files
security-game/docs/npc-model-sourcing.md
T
zwitschi e2f52fbfd1
Full build / Import + headless tests (push) Successful in 48s
Full build / Full desktop build + optional release (push) Skipped
Accept ADR-0018 option 2: adopt the Quaternius 62-joint rig at runtime
2026-11-05 21:39:38 +01:00

12 KiB
Raw Blame History

NPC Model Sourcing

This page records the source evaluation and the active character plan. The decision is ADR-0017, which supersedes the generator-first sourcing decision in ADR-0015.

Active direction

Quaternius Ultimate Modular Characters (CC0) is the primary NPC mesh and animation source. The project-owned procedural library remains the shipped fallback until the Quaternius migration passes the silhouette and gear gates.

The migration keeps the runtime contract that Godot, gear and tests already consume:

  • one npc_base skinned mesh under the 13 required core bones (optional extras allowed);
  • five tint slots: skin, cloth, pants, accessory, hair;
  • front on Blender −Y / Godot +Z, feet grounded, height about 1.81 m;
  • 24,000 triangles / 24,000 glTF vertices per character;
  • gear stays at 1,500 triangles and props at 4,000;
  • committed GLBs and maps only; no Quaternius, Blender or network dependency in CI, build or runtime.

Stage 1 (default)

  1. Import the researched Quaternius GLBs and choose a canonical base.
  2. Map the 62 source joints to the 13-core contract and bake a proportion warp.
  3. Skin the mesh, retarget Idle and Walk, and verify seated/arm-down poses.
  4. Map the five slots, unwrap and bake 256² maps.
  5. Fit the existing gear and render the silhouette gate.
  6. Build the 12 variants, audit, and capture the 12 × 6 baseline.

The Quaternius 62-joint rig and its 24 animation clips are an authoring source. They are not loaded at runtime.

Stage 2 gate

The 62-joint T-pose source does not share the project's arm-down rest pose or proportions. If the Stage 1 proportion warp cannot preserve the Quaternius silhouette and deformation, stop the rollout and write a new ADR for adopting the 62-joint rig at runtime. Do not ship a hybrid rig, a second gear offset system or a silent NpcAvatar change.

Research findings

The researched files are the three converted Quaternius outfits used by the Ducz Character Creator: Casual, Casual_Hoodie and Worker. They are kept locally in tmp/npc-research/quaternius/ with the licence and mirror notes.

File SHA-256 Structure
Casual.glb bc2d84fba249ebaa0629cb9d133ad37234196e4b8004aa205a6397abed04e05c 4 meshes, 62 joints, 24 clips, 7 materials
Casual_Hoodie.glb f5b722199f7628b24550989af4230f65d5230727df9c326fd2b3e360effe5249 4 meshes, 62 joints, 24 clips, 7 materials
Worker.glb 8d0f454336c2effc5c08f63a177af3a82d1a7af025ca9588b40e4c90c4703534 4 meshes, 62 joints, 24 clips, 11 materials

Source: Quaternius Ultimate Modular Characters and Ultimate Modular Women, CC0 1.0. Download date: 2026-11-03 (via the Ducz Character Creator browser export). The Ducz mirror is a browser builder over the same packs; it adds 21 outfits and a shared skeleton. The three full GLBs are the initial scope; the 21-part builder is a fallback for role coverage, not the default.

Initial outfit scope (2026-11-05): the three full GLBs (Casual, Casual_Hoodie, Worker) are the canonical-base and silhouette-gate scope. They cover only ~3 of the 12 roles (casual, hood, vest); the jacket, coat, dress, responder (firefighter) and guard looks are not in the three GLBs, so §4 roster coverage must pull those from the 21-part modular builder or author new clothing. Do not start the modular builder until the canonical base passes §3.

The first prototype measured 12,518 imported vertices, 3,199 after welding and 2,423 vertices / 4,654 triangles after a 0.75 decimate. Idle and Walk read well. The source is a T-pose with a 62-joint realistic rig, roughly 0.96 m hip, 1.68 m arm span and 0.153 m shoulder offset, so a contract bake is required.

The 24,000 cap leaves room to stay much closer to the source LOD than the prototype's 4,654 triangles. Do not decimate to the old 7,000-triangle target before the silhouette gate.

Quaternius GLB inventory (2026-11-05)

All three GLBs share one 62-joint rig and the same 24 animation clips; only the meshes and materials differ. Each import also adds a 42-vert/80-tri Icosphere bone-display helper — ignore it.

Meshes (verts / tris)

GLB Body Feet Head Legs Total
Casual 5,338 / 2,654 1,082 / 538 5,122 / 2,526 1,426 / 706 12,968 / 6,424
Casual_Hoodie 6,132 / 3,048 1,024 / 512 3,836 / 1,888 1,526 / 758 12,518 / 6,206
Worker 6,074 / 3,018 928 / 464 1,862 / 936 1,670 / 822 10,534 / 5,240

Joints (62)

  • Spine: Root, Hips, Torso, Body, Abdomen, Chest, Neck, Head (8).
  • Arms: Shoulder.L/R, UpperArm.L/R, LowerArm.L/R, Wrist.L/R (8) plus PT.L/R (2 pole targets).
  • Fingers: Thumb×3, Index×4, Middle×4, Ring×4, Pinky×4 × L/R (30).
  • Legs: UpperLeg.L/R, LowerLeg.L/R, Foot.L/R (6).

Animation clips (24)

Idle, Idle_Neutral, Walk, Run, Run_Back, Run_Left, Run_Right, Wave, Interact, Death, Gun_Shoot, Idle_Gun, Idle_Gun_Pointing, Idle_Gun_Shoot, Idle_Sword, Run_Shoot, Sword_Slash, HitRecieve, HitRecieve_2, Kick_Left, Kick_Right, Punch_Left, Punch_Right, Roll.

The retarget scope is Idle and Walk; combat/gun/sword clips are discarded (see §2).

Material → slot map

The five project slots (skin, cloth, pants, accessory, hair) are assigned by mesh region first, then material — the same material name can mean cloth on the body and accessory on the feet.

Material Where Project slot
Skin all meshes skin
Hair_Blond, Hair_Brown, Hair, Brown (head), Eyebrows, Moustache Head hair
Eye Head accessory
Worker_Yellow Worker body (vest stripe) + head (helmet) cloth / accessory
White, Grey, Purple, Black Body / Feet cloth (body) / accessory (feet)
Orange, LightBlue, LightBrown, Brown, Brown2 Legs pants
Worker_Vest Worker body cloth

Canonical base (built 2026-11-05)

tmp/npc-research/quaternius_base.glb is the welded, triangulated, grounded, animation-free canonical base built from Casual_Hoodie.glb (the most detailed body) by tmp/npc-research/build_quaternius_base.py:

  • one npc_base mesh — 3,199 welded verts / 6,206 tris (Body + Feet + Head + Legs joined);
  • 62 joints, skinned (no unskinned faces);
  • height 1.81 m, feet at y 0, front on Godot +Z / Blender −Y (T-pose rest);
  • no animation clips; inspect clean (no issues).

This is the §2 contract-bake input: the 62-joint rig is authoring-only and is mapped to the 13-core contract next, not shipped as-is.

62-joint → 13-core joint map (2026-11-05)

The Quaternius hierarchy (measured from quaternius_base.glb):

  • Root → Body → Hips → Abdomen → Torso → Chest → Neck → Head (spine);
  • Chest → Shoulder.L/R → UpperArm.L/R → LowerArm.L/R → Wrist.L/R → fingers (arms);
  • Body → UpperLeg.L/R → LowerLeg.L/R and Root → Foot.L/R (legs — the foot is a separate child of Root, not of LowerLeg);
  • Root → PT.L/R (IK pole targets, no deforming weights).

The contract is 14 bones (13 core + Hips root): Hips, Spine, Neck, Head, Shoulder.L/R, Elbow.L/R, Hand.L/R, Hip.L/R, Knee.L/R. The map:

Contract bone Quaternius source Notes
Hips Hips Root + Body collapse into Hips
Spine Abdomen, Torso, Chest three collapse into one
Neck Neck
Head Head
Shoulder.L/R UpperArm.L/R the collar Shoulder.L/R collapses into Spine
Elbow.L/R LowerArm.L/R
Hand.L/R Wrist.L/R
Hip.L/R UpperLeg.L/R
Knee.L/R LowerLeg.L/R

Optional extras (allowed by the contract; kept if they survive within 24,000 vertices):

  • the 30 finger bones (Thumb×3, Index×4, Middle×4, Ring×4, Pinky×4 × L/R) → optional finger bones;
  • Foot.L/R → optional toe bones.

Dropped (never shipped): PT.L/R (pole targets carry no deforming weights), and the Root/Body/collar-Shoulder collapse bones above.

Rest-pose and proportion-warp measurement (2026-11-05)

The rest-pose bake (T-pose → arm-down) works: rotate the UpperArm.L/R pose bones −90° around their local X, apply the Armature modifier to bake the deformation, then armature_apply to bake it as the new rest pose (see tmp/npc-research/warp_full.py). The mesh deforms cleanly to the arm-down pose (deformed bounds x ±0.221 vs the T-pose ±0.811).

The proportion warp to the contract positions is measured and it distorts the silhouette:

Joint Quaternius Contract Delta
Hips height 0.869 0.62 −0.249 (lower hip)
Head top 1.614 1.82 +0.206 (raise head)
Shoulder x 0.148 0.27 +0.122 (widen)
Arm (shoulder→wrist) 0.402 0.60 ×1.49
Arm (shoulder→hand tip) 0.429 0.70 ×1.63
Leg (hip→ankle) 0.835 0.62 ×0.74
Torso (hip→head) 0.745 1.20 ×1.61

The vision judge reads the warped mesh as: paddle/claw hands (the 1.63× arm stretch blows the hand out), forearms lost into the torso, stretched shins, and "long legs + short torso". The arm must either stay short (a "shortened arm" vs the contract hand) or stretch 1.63× (a distorted deltoid + hand) — both are the gate's rejection conditions.

Finding: the Stage 1 proportion warp cannot preserve the Quaternius silhouette at the contract proportions; the gate fails and Stage 2 (a 62-joint runtime ADR) is indicated. Do not start the 12-variant rebuild on the warped base.

ADR-0018 records the Stage 2 decision (accepted 2026-11-05, owner chose option 2): adopt the Quaternius 62-joint rig at runtime, keep the mesh at source LOD, re-derive gear attach points from the Quaternius skeleton, and use the Quaternius Idle/Walk clips directly (no retarget).

Contract mismatch

The expensive part is the rig and proportions, not the mesh. The source has a T-pose and a realistic skeleton; the runtime expects an arm-down 13-core rig, fixed gear attach points and the existing pose composition. The Stage 1 bake must therefore:

  • rotate the arms down and match the contract wrist positions;
  • warp the hips, knees, shoulders and head without collapsing the deltoid, shortening the arms or changing the silhouette;
  • keep one skinned npc_base mesh and the five slots;
  • verify gear against the new shoulder, hip and head positions.

If those constraints distort the model, Stage 2 is the correct next decision, not a local workaround.

Licence and provenance

  • CC0 preferred. CC-BY is allowed only with attribution in CREDITS.md.
  • No service asset whose terms restrict redistribution may be shipped.
  • Keep the source URL, author, licence, download date and SHA-256 in this page and in CREDITS.md.
  • Research files and generated previews stay in tmp/ (gitignored). Only final audited assets and committed review sheets enter the repository.
  • Quaternius models and animations are CC0; the existing credits entry already names Quaternius. Keep it accurate if the shipped source set changes.

Closed tracks

The MakeHuman/MPFB body pipeline is closed for the NPC base. The accepted MakeHuman head and the procedural npc_base remain tested fallbacks until the Quaternius rollout is complete. Their research scripts and renders were removed from tmp/ after the pivot; the measurements and decisions remain in DONE.md, MEMORY.md and the review docs.