Raise the NPC character budget to 24k and refine the prototype neck
This commit is contained in:
1 parent
f0d4b81239
commit
79224c5acf
19 files changed
+128
-56
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 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.
|
||||
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, 24,000/24,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
|
||||
@@ -51,8 +51,8 @@ and resolve the source of truth before editing assets.
|
||||
| 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. |
|
||||
| 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. |
|
||||
| Character budget | **24,000 triangles / 24,000 glTF vertices** per character (`CHAR_MAX_TRIS`/`CHAR_MAX_VERTS`). |
|
||||
| Frozen fallback | `npc_base` remains the low-poly fallback; it shares the 24,000/24,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. |
|
||||
@@ -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 16,000/16,000; gear/prop caps hold.
|
||||
- No character exceeds 24,000/24,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.
|
||||
|
||||
@@ -59,7 +59,7 @@ skin, cloth, pants, accessory, hair
|
||||
|
||||
| Asset | Limit |
|
||||
| --- | --- |
|
||||
| Character (library and base fallback) | 16,000 triangles / 16,000 glTF vertices |
|
||||
| Character (library and base fallback) | 24,000 triangles / 24,000 glTF vertices |
|
||||
| Gear piece | 1,500 triangles |
|
||||
| Prop | 4,000 triangles |
|
||||
| Library prop/venue total | must stay inside the venue tests and library budget |
|
||||
|
||||
@@ -91,8 +91,8 @@ specialists the task needs:
|
||||
### Project rules that override 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
|
||||
positions, five tint slots, front on Blender −Y / Godot +Z, grounded feet, 24,000
|
||||
triangles / 24,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.
|
||||
|
||||
@@ -4,6 +4,14 @@ All notable user-facing changes to Gig Line. The format follows
|
||||
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions use
|
||||
Semantic Versioning.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
- Raised the character mesh budget from 16,000 to 24,000 triangles and glTF
|
||||
vertices so the MakeHuman head, MPFB body, fused neck and clothing variants
|
||||
can fit without heavy decimation. Gear and prop budgets are unchanged.
|
||||
|
||||
## [0.9.8] — 2026-11-04
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -114,11 +114,21 @@ canonical implemented-features list in `docs/development-status.md`.
|
||||
`docs/asset-tooling.md#optional-interactive-blender-mcp`. 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
|
||||
- **Character mesh cap (2026-11-05):** all characters use 24,000 tris / 24,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
|
||||
low-poly `npc_base` fallback remains the shipped fallback. The raise funds the MPFB body and a
|
||||
seamless neck/shoulder junction. Measure the 24-NPC/Web budget after
|
||||
any geometry change; never silently lower the cap without a new decision.
|
||||
- **MPFB prototype neck (2026-11-05):** a boolean cylinder (r 0.102) cuts the body neck bore; a
|
||||
smooth lathe covers it. The accepted head keeps a wide flat cut brim at 1.53, so the prototype
|
||||
trims the head at 1.55 (discarding only the neck stub) and matches the lathe to the smaller
|
||||
elliptical opening. This removes the square collar, dark notches and wide brim. Remaining: a
|
||||
thin jaw crease and a hard shirt-shoulder point in three-quarter view. Do not re-add a torus,
|
||||
flat disk, collar shell or destructive neck smoothing; those were rejected.
|
||||
- **MPFB prototype count (2026-11-05):** 19,747 tris / 11,475 glTF verts / 1.810 m / 14 bones /
|
||||
10 materials; `inspect` clean. Body-only head/neck surgery lives in
|
||||
`tmp/npc-research/build_mpfb_npc.py` (backups in `/tmp/build_mpfb_npc_94.py`).
|
||||
- **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.
|
||||
|
||||
@@ -18,7 +18,7 @@ Goal: replace the sphere-and-primitive face and hand construction with a local,
|
||||
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 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.
|
||||
five tint slots, 24,000/24,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`.*
|
||||
@@ -28,7 +28,7 @@ gitignored `.blend1`; the 12 production characters are assembled procedurally by
|
||||
`tools/blender_assets.py` from `_shape_head_mesh`, `_face`, `_hair` and `_hands_and_shoes`.
|
||||
The MakeHuman head is now a second head source (`build_character(head="mh")`,
|
||||
`build --head mh`, `npc_parts.py assemble --head mh`) and all 12 variants assemble inside the
|
||||
16,000-triangle cap with it. The procedural body, hands and clothing remain unchanged. The
|
||||
24,000-triangle cap with it. The procedural body, hands and clothing remain unchanged. The
|
||||
MakeHuman body prototype and its temporary head/hand swap live under `tmp/npc-research/` and are
|
||||
not the shipped path. This overhaul supplies the reusable head/face and hand parts that both the
|
||||
procedural characters and the MakeHuman body can consume.
|
||||
@@ -45,7 +45,7 @@ the rest of §C remains the broad review checklist.
|
||||
`docs/3d-model-review.md` §Baseline inventory.
|
||||
- [x] 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 16,000/16,000 cap; optional extra bones are allowed, but the required 13 core bones and rest positions must not move.
|
||||
separation and gear contact. Keep the 24,000/24,000 cap; optional extra bones are allowed, but the required 13 core bones and rest positions must not move.
|
||||
Recorded in `docs/3d-model-review.md` §Overhaul acceptance criteria.
|
||||
- [x] Confirm the identity boundary: `npc_base.blend` is the frozen fallback and must not absorb
|
||||
prototype detail unless a separate contract decision approves it.
|
||||
@@ -195,7 +195,7 @@ the rest of §C remains the broad review checklist.
|
||||
### Full-body MPFB prototype
|
||||
|
||||
Goal: assemble the accepted MakeHuman head onto a CC0 MPFB body with project hands, shoes and
|
||||
14-bone contract rig, inside the 16,000/16,000 character budget. Local development only until the
|
||||
14-bone contract rig, inside the 24,000/24,000 character budget. Local development only until the
|
||||
owner reviews the silhouette and a production integration decision is recorded.
|
||||
|
||||
- [x] Build the dev pipeline at `tmp/npc-research/build_mpfb_npc.py`: create a macro-driven MPFB
|
||||
@@ -203,10 +203,19 @@ owner reviews the silhouette and a production integration decision is recorded.
|
||||
apply the helper MASK, scale to 1.81 m, retarget the A-pose arms to the contract wrist
|
||||
(`x=±0.27`, `z=0.78`), cut the neck at 1.505, decimate, bisect the clothing boundaries, paint
|
||||
the five slots, add a short neck flare, project hands, rounded shoe shells, cuffs, the
|
||||
accepted head and the 14-bone armature. Current output: **15,317 tris / 13,690 glTF verts /
|
||||
13,702 seam-split verts / 1.810 m / 14 bones / 10 materials**; `inspect` clean, feet grounded.
|
||||
accepted head and the 14-bone armature. Current output: **19,747 tris / 11,475 glTF verts /
|
||||
1.810 m / 14 bones / 10 materials**; `inspect` clean, feet grounded.
|
||||
The torso is inflated radially by 12% through z 0.72–1.40 (tapering out at the collar) so the
|
||||
shirt reads as fabric rather than body paint.
|
||||
- [x] Raise the character contract to 24,000 triangles / 24,000 glTF vertices so the MPFB body,
|
||||
the accepted head and a fused neck can coexist with headroom for the 12-variant clothing.
|
||||
Bumped `CHAR_MAX_TRIS`/`CHAR_MAX_VERTS`, `npc_pipeline.MAX_TRIANGLES`/`MAX_VERTICES`,
|
||||
the adapt defaults, the tests, `AGENTS.md`, ADR-0016 and the project skills.
|
||||
- [-] Fix the head/neck/shoulder junction so there are no gaps, square collars or hard rims.
|
||||
Done: circular boolean bore, smooth lathe, accepted head trimmed at its narrow neck (1.55),
|
||||
no dark notches or wide brim; prototype at 19,747 tris. Remaining: a thin jaw crease and a
|
||||
hard shirt-shoulder point in three-quarter view. Next candidate: reshape the shirt shoulder
|
||||
or a shaped collar that follows the neckline, not a torus or flat disk.
|
||||
- [x] Replace the spiky decimated MPFB hands with the project palm/finger primitives, straighten the
|
||||
splayed MPFB feet so the shoes point forward, and use rounded shoe shells + cuffs instead of
|
||||
flat blocks. Use flat slot colours in the prototype because the one-shot MPFB UV unwrap does
|
||||
@@ -299,7 +308,7 @@ 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 16000]`): imports the GLB, applies transforms, grounds the feet, welds seam
|
||||
[--target-tris 24000]`): 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
|
||||
|
||||
@@ -193,7 +193,7 @@ capture). Pass conditions:
|
||||
|
||||
### Contract (both, every prototype)
|
||||
|
||||
- 16,000 triangles / 16,000 glTF vertices per character; gear stays at 1,500.
|
||||
- 24,000 triangles / 24,000 glTF vertices per character; gear stays at 1,500.
|
||||
- Optional extra bones are allowed; the required 13 core bones and their rest positions must not
|
||||
move; the `npc_base` mesh node name and the five tint slots stay unchanged.
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ This folder holds the project documentation, visual references and generated QA
|
||||
|
||||
## Current priorities
|
||||
|
||||
1. [Blender NPC model overhaul](../TODO.md#blender-npc-model-overhaul-top-priority) — part-based head/face/hands pipeline and 16,000-budget contract.
|
||||
1. [Blender NPC model overhaul](../TODO.md#blender-npc-model-overhaul-top-priority) — part-based head/face/hands pipeline and 24,000-budget contract.
|
||||
2. [MakeHuman and 3D model/map improvements](../TODO.md#makehuman-character-pipeline) — body intake, asset re-evaluation and local map reconstruction.
|
||||
3. [0.10.0 release candidate](../TODO.md#milestone-0100--3d-model-and-map-improvements-minor) — versioned release hardening after the unversioned development tracks.
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# ADR-0016: 24,000-triangle character budget
|
||||
|
||||
- **Status:** Accepted
|
||||
- **Date:** 2026-11-05
|
||||
|
||||
## Context
|
||||
|
||||
ADR-0015 raised the character contract to 16,000 triangles / 16,000 glTF
|
||||
vertices for the MakeHuman head, hands and crowd variety. The local MPFB
|
||||
full-body prototype now uses that head, project hands and shoes, and a fused
|
||||
neck: it measures 19,747 triangles before any clothing variation. The 16,000 cap
|
||||
leaves no room for the firefighter and hoodie gear, and it forces the body and
|
||||
neck into a low decimation that produces visible facets.
|
||||
|
||||
## Decision
|
||||
|
||||
Raise the character contract to **24,000 triangles / 24,000 glTF vertices** per
|
||||
character (`CHAR_MAX_TRIS`/`CHAR_MAX_VERTS`, `npc_pipeline.MAX_TRIANGLES`/
|
||||
`MAX_VERTICES`, and the `adapt` defaults). The 13 core bones, five tint slots,
|
||||
front orientation, grounding and single `npc_base` skinned mesh are unchanged.
|
||||
Gear stays at 1,500 triangles and props at 4,000.
|
||||
|
||||
## Consequences
|
||||
|
||||
- The MPFB body, accepted head and neck fit with headroom for the 12 clothing
|
||||
variants and future jacket/hoodie detail.
|
||||
- The 24-NPC and Web frame-time budgets must be re-measured before shipping any
|
||||
variant built at the new cap; the extra geometry is not free.
|
||||
- The procedural generator and the low-poly `npc_base` fallback remain valid;
|
||||
they are not required to use the new headroom.
|
||||
- MPFB stays a local development tool. Production must bake a committed source
|
||||
GLB; CI and the build must not depend on MPFB.
|
||||
- Historical reviews and measurements that state 16,000 remain accurate for the
|
||||
date they were recorded; current contract documents state 24,000.
|
||||
|
||||
## Alternatives
|
||||
|
||||
- **Keep 16,000 and decimate the MPFB body further:** rejected because the neck
|
||||
and shoulder already show facets and the clothing variants would exceed the
|
||||
cap.
|
||||
- **Separate caps for the MPFB prototype and the shipped characters:** rejected
|
||||
because it creates a second contract and makes the rollout ambiguous.
|
||||
@@ -19,3 +19,4 @@ Each ADR records the context, decision, consequences and alternatives for a dura
|
||||
- [0013-blender-authored-npc-characters](0013-blender-authored-npc-characters.md)
|
||||
- [0014-runtime-image-root](0014-runtime-image-root.md)
|
||||
- [0015-npc-model-variety-sourcing](0015-npc-model-variety-sourcing.md)
|
||||
- [0016-npc-character-budget-24k](0016-npc-character-budget-24k.md)
|
||||
@@ -139,7 +139,7 @@ The runtime NPC contract is intentionally narrow. It is enforced by
|
||||
| Core bones | `Head`, `HipL/R`, `KneeL/R`, `ShoulderL/R`, `ElbowL/R`, `HandL/R`, `Spine`, `Neck` at the frozen rest positions. Optional extra bones (fingers, face, toes) are allowed if they do not move the core rest positions or break `NpcAvatar` proxies. |
|
||||
| Tint slots | `skin`, `cloth`, `pants`, `accessory`, `hair`; fixed detail materials keep their authored colours. |
|
||||
| Orientation | Blender −Y / Godot +Z front, feet grounded near `y = 0`, metre scale. |
|
||||
| Budget | 16,000 triangles / 16,000 glTF vertices per character; 1,500 per gear piece; 4,000 per prop. The low-poly `npc_base` remains a fallback, not a second contract. |
|
||||
| Budget | 24,000 triangles / 24,000 glTF vertices per character; 1,500 per gear piece; 4,000 per prop. The low-poly `npc_base` remains a fallback, not a second contract. |
|
||||
| Textures | 256² albedo + normal + packed ORM per slot; cloth/pants use the 4× `NPC_FABRIC_UV_SCALE` and skip per-character baked AO, while skin/hair/gear keep AO. |
|
||||
| Gear attach | Authored in attach-point space: head `Rig/Head` (0, 1.62, 0), back (0, 1.10, 0), chest (0, 1.30, 0), hand (±0.27, 0.78, 0.02); grip 5 cm below the origin. `GEAR_OFFSETS` and `HAND_ITEM_FORWARD` are runtime fit corrections, not authored-geometry changes. |
|
||||
| Fallback chain | Library variant → `npc_base.glb` → procedural `NpcAvatar` mesh. Committed GLBs and maps must keep CI offline and Blender-free. |
|
||||
@@ -217,8 +217,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 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/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 24,000-triangle / 24,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 24,000 tris / 24,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-visual-review.md#proportion-audit` | 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` |
|
||||
|
||||
@@ -200,8 +200,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 16000
|
||||
# prints: adapted makehuman_adapted.glb: 36972 -> 16000 tris (bones=N, meshes=1)
|
||||
--target-tris 24000
|
||||
# prints: adapted makehuman_adapted.glb: 36972 -> 24000 tris (bones=N, meshes=1)
|
||||
```
|
||||
|
||||
Run `inspect` on the adapted GLB before and after, and keep the procedural
|
||||
|
||||
@@ -141,7 +141,7 @@ render about 2.5 min.
|
||||
|
||||
All library variants share the [character and gear asset contract](architecture.md#character-and-gear-asset-contract):
|
||||
`npc_base` mesh node, required 13 core bones (optional extras allowed), five
|
||||
tint slots, +Z visual front, 16,000/16,000 character budget and the same 256²
|
||||
tint slots, +Z visual front, 24,000/24,000 character budget and the same 256²
|
||||
slot-map/AO rules. Role selection and look notes:
|
||||
|
||||
| Character | `layer_for()` / look | Suggested roles | Preview gear |
|
||||
@@ -200,7 +200,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 (characters 16000/16000, gear 1500, props 4000
|
||||
during LOD generation), budgets (characters 24000/24000, 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
|
||||
|
||||
@@ -8,7 +8,7 @@ remain references or local prototypes unless a later ADR accepts them.
|
||||
|
||||
The library needs variety beyond the original eight silhouettes while preserving
|
||||
the `npc_base` contract: mesh node, 13 required core bones (optional extras
|
||||
allowed), five tint slots, −Y/+Z front, grounded feet and the 16,000/16,000
|
||||
allowed), five tint slots, −Y/+Z front, grounded feet and the 24,000/24,000
|
||||
character budget.
|
||||
|
||||
| Source | Licence | Result |
|
||||
@@ -55,14 +55,16 @@ The MakeHuman body should reuse the approved local head/hand parts rather than f
|
||||
a second face implementation.
|
||||
|
||||
The current local MPFB full-body prototype (`tmp/npc-research/build_mpfb_npc.py`) assembles the
|
||||
accepted head on an MPFB 2.0.18 body at **15,317 / 16,000 tris**, 1.810 m, 14 bones and 10
|
||||
accepted head on an MPFB 2.0.18 body at **19,747 / 24,000 tris**, 1.810 m, 14 bones and 10
|
||||
materials, with project hands, bevelled shoe shells with inset soles and tongues, pant cuffs,
|
||||
cloth sleeve cuffs and flat slot colours. The torso is radially inflated by 12% through z 0.72–1.40
|
||||
to loosen the shirt. It is a review candidate, not a shipped asset. The neck is a radial cut
|
||||
of the decimated column bridged by a four-ring, 20-segment lathe (lower rings painted cloth,
|
||||
reading as a crew neck); the ankles are hidden by 0.11 m shoe shells and 0.08 m pant cuffs, and a
|
||||
light smoothing pass softens the closed thigh/hip region. The neck skin test is guarded to z >
|
||||
1.35 so it cannot paint the crotch. Remaining polish: the crotch hollow still reads as a V under
|
||||
to loosen the shirt. It is a review candidate, not a shipped asset. The neck is a boolean-cut
|
||||
circular bore bridged by a smooth lathe; the accepted head is trimmed at the narrow neck (z 1.55)
|
||||
so its wide flat cut brim is discarded, and the lathe flares to cover the bore, then tucks inside
|
||||
the jaw. This removed the square collar, dark notches and wide brim; a thin jaw crease and a hard
|
||||
shirt-shoulder point in three-quarter view remain. The ankles are hidden by 0.11 m shoe shells and
|
||||
0.08 m pant cuffs, and a light smoothing pass softens the closed thigh/hip region. The neck skin
|
||||
test is guarded to z > 1.35 so it cannot paint the crotch. Remaining polish: the crotch hollow still reads as a V under
|
||||
the shirt hem, a partly loosened shirt and angular thigh facets; a separate loose shirt shell is
|
||||
the fix. Lowering the hem to z 0.80, tilting it up at the front and a 13% hem flare were rejected
|
||||
as a unitard, high-cut swimwear and a peplum respectively. A quick open, flared solidified tube
|
||||
|
||||
@@ -71,8 +71,8 @@ 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 16,000 triangles
|
||||
and 16,000 glTF vertices per character. The required 13 core bones stay fixed;
|
||||
front +Z, feet within 3 cm of y=0, 1.6–2.1 m height, at most 24,000 triangles
|
||||
and 24,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
|
||||
|
||||
+11
-11
@@ -53,14 +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"]
|
||||
# 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
|
||||
# Character cap raised to 24000/24000 on 2026-11-05 for the MPFB body, the
|
||||
# accepted MakeHuman head and a seamless neck/shoulder junction. 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 the 24-NPC
|
||||
# smoke test must confirm frame time before shipping.
|
||||
CHAR_MAX_TRIS = 24000
|
||||
CHAR_MAX_VERTS = 24000
|
||||
GEAR_MAX_TRIS = 1500
|
||||
PROP_MAX_TRIS = 4000
|
||||
|
||||
@@ -2486,7 +2486,7 @@ def inspect_glb(path, category=None) -> dict:
|
||||
return result
|
||||
|
||||
|
||||
def adapt_glb(path, out_path, target_tris=16000):
|
||||
def adapt_glb(path, out_path, target_tris=24000):
|
||||
"""Import an external GLB and adapt it toward the library contract.
|
||||
|
||||
Applies node transforms, grounds the feet (lowest vertex at y = 0), welds
|
||||
@@ -2892,8 +2892,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=16000,
|
||||
help="decimate target (default 16000)")
|
||||
ada.add_argument("--target-tris", type=int, default=24000,
|
||||
help="decimate target (default 24000)")
|
||||
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")
|
||||
|
||||
@@ -23,7 +23,7 @@ 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
|
||||
* <= 16000 triangles / 16000 vertices, UVs in [0,1], feet at y ~= 0
|
||||
* <= 24000 triangles / 24000 vertices, UVs in [0,1], feet at y ~= 0
|
||||
* the 13 core bones are required; extra optional bones are allowed
|
||||
"""
|
||||
|
||||
@@ -45,8 +45,8 @@ BONES = [
|
||||
"Head", "HipL", "HipR", "KneeL", "KneeR",
|
||||
"ShoulderL", "ShoulderR", "ElbowL", "ElbowR", "HandL", "HandR",
|
||||
]
|
||||
MAX_TRIANGLES = 16000
|
||||
MAX_VERTICES = 16000
|
||||
MAX_TRIANGLES = 24000
|
||||
MAX_VERTICES = 24000
|
||||
TEX_SIZE = 256
|
||||
AI_DIR = TEX_DIR / "ai"
|
||||
# Base material slots that get an AI fabric albedo (`prepare` layers them over
|
||||
|
||||
@@ -9,10 +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 character cap was raised to 16000/16000 for the head/face/hand
|
||||
# The character cap was raised to 24000/24000 for the MPFB body and the head
|
||||
# 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)
|
||||
self.assertLessEqual(ba.CHAR_MAX_TRIS, 24000)
|
||||
self.assertLessEqual(ba.CHAR_MAX_VERTS, 24000)
|
||||
|
||||
def test_gear_uses_known_attach_points(self):
|
||||
for name, attach in ba.GEAR.items():
|
||||
@@ -197,7 +197,7 @@ class InspectionTests(unittest.TestCase):
|
||||
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=17000, split_vertices=17000,
|
||||
triangles=25000, split_vertices=25000,
|
||||
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)
|
||||
@@ -205,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 17000 > {ba.CHAR_MAX_TRIS}", issues)
|
||||
self.assertIn(f"glTF vertices 17000 > {ba.CHAR_MAX_VERTS}", issues)
|
||||
self.assertIn(f"triangles 25000 > {ba.CHAR_MAX_TRIS}", issues)
|
||||
self.assertIn(f"glTF vertices 25000 > {ba.CHAR_MAX_VERTS}", issues)
|
||||
self.assertIn("feet not on the ground", issues)
|
||||
self.assertIn("unexpected height", issues)
|
||||
|
||||
|
||||
@@ -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, 16000)
|
||||
self.assertLessEqual(npc_pipeline.MAX_VERTICES, 16000)
|
||||
self.assertLessEqual(npc_pipeline.MAX_TRIANGLES, 24000)
|
||||
self.assertLessEqual(npc_pipeline.MAX_VERTICES, 24000)
|
||||
|
||||
def test_textures_exist_for_every_slot(self):
|
||||
for slot in npc_pipeline.SLOTS:
|
||||
|
||||
Reference in new issue
Block a user