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
|
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.
|
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:
|
metadata:
|
||||||
project: Gig Line
|
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. |
|
| 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`. |
|
| Tint slots | `skin`, `cloth`, `pants`, `accessory`, `hair`. |
|
||||||
| Orientation | Front is Blender −Y / Godot +Z; feet grounded near y = 0; metres. |
|
| 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`). |
|
| 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 16,000/16,000 cap but is not required to use it. Do not silently lower the cap. |
|
| 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. |
|
| Gear budget | **1,500 triangles** per gear piece; authored in attach-point space. |
|
||||||
| Prop budget | **4,000 triangles** per prop. |
|
| 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. |
|
| 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_proportions.py` passes the stylized guide.
|
||||||
- `npc_pipeline.py audit` passes if the base/textures changed.
|
- `npc_pipeline.py audit` passes if the base/textures changed.
|
||||||
- texel density is inside the authored/fabric bands.
|
- 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.
|
- 24-NPC budget and Web/Compatibility path remain green.
|
||||||
- Contract tests, headless suite, capture gates and docs check pass.
|
- Contract tests, headless suite, capture gates and docs check pass.
|
||||||
- The diff contains only the intended assets, tools, tests and docs.
|
- The diff contains only the intended assets, tools, tests and docs.
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ skin, cloth, pants, accessory, hair
|
|||||||
|
|
||||||
| Asset | Limit |
|
| 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 |
|
| Gear piece | 1,500 triangles |
|
||||||
| Prop | 4,000 triangles |
|
| Prop | 4,000 triangles |
|
||||||
| Library prop/venue total | must stay inside the venue tests and library budget |
|
| 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
|
### Project rules that override a skill
|
||||||
|
|
||||||
1. **The project contract wins.** `npc_base` mesh node, the 13 required core bones at their rest
|
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
|
positions, five tint slots, front on Blender −Y / Godot +Z, grounded feet, 24,000
|
||||||
triangles / 16,000 glTF vertices per character, 1,500 per gear, 4,000 per prop. Optional
|
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
|
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
|
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.
|
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
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions use
|
||||||
Semantic Versioning.
|
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
|
## [0.9.8] — 2026-11-04
|
||||||
|
|
||||||
### Fixed
|
### 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
|
`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
|
never a build/CI/test/runtime dependency, and anything MCP touched must pass the
|
||||||
CLI audit/fit gates.
|
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`/
|
(`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
|
`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.
|
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
|
- **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
|
`godot-runner` cannot load arbitrary project paths (compiled without path overrides); use the
|
||||||
official editor binary.
|
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
|
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
|
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),
|
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`,
|
*Skill route: `character-artist`, `retopology`, `sculpting`, `rigging`, `uv-workflow`,
|
||||||
`texture-workflow`, `materials`, `lookdev`, `asset-optimization`, `qa-review`.*
|
`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`.
|
`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")`,
|
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
|
`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
|
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
|
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.
|
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.
|
`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
|
- [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
|
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.
|
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
|
- [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.
|
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
|
### Full-body MPFB prototype
|
||||||
|
|
||||||
Goal: assemble the accepted MakeHuman head onto a CC0 MPFB body with project hands, shoes and
|
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.
|
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
|
- [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
|
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
|
(`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
|
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 /
|
accepted head and the 14-bone armature. Current output: **19,747 tris / 11,475 glTF verts /
|
||||||
13,702 seam-split verts / 1.810 m / 14 bones / 10 materials**; `inspect` clean, feet grounded.
|
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
|
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.
|
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
|
- [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
|
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
|
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
|
### Intake and adaptation
|
||||||
|
|
||||||
- [x] `adapt` path added to `tools/blender_assets.py` (`adapt --file <in> --out <out>
|
- [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
|
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).
|
(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
|
- [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)
|
### 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
|
- 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.
|
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
|
## 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.
|
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.
|
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)
|
- [0013-blender-authored-npc-characters](0013-blender-authored-npc-characters.md)
|
||||||
- [0014-runtime-image-root](0014-runtime-image-root.md)
|
- [0014-runtime-image-root](0014-runtime-image-root.md)
|
||||||
- [0015-npc-model-variety-sourcing](0015-npc-model-variety-sourcing.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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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 |
|
| 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/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 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/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/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_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` |
|
| `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 \
|
--python "$PWD/tools/blender_assets.py" -- adapt \
|
||||||
--file "$PWD/tmp/npc-research/makehuman_base.glb" \
|
--file "$PWD/tmp/npc-research/makehuman_base.glb" \
|
||||||
--out "$PWD/tmp/npc-research/makehuman_adapted.glb" \
|
--out "$PWD/tmp/npc-research/makehuman_adapted.glb" \
|
||||||
--target-tris 16000
|
--target-tris 24000
|
||||||
# prints: adapted makehuman_adapted.glb: 36972 -> 16000 tris (bones=N, meshes=1)
|
# 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
|
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):
|
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
|
`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:
|
slot-map/AO rules. Role selection and look notes:
|
||||||
|
|
||||||
| Character | `layer_for()` / look | Suggested roles | Preview gear |
|
| 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`/
|
- `python3 tools/blender_assets.py audit`: container, `POSITION`/`NORMAL`/
|
||||||
`TEXCOORD_0`, UVs in [0, 1], no zero-area triangles (Godot warns about them
|
`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
|
triangles), grounding, and an editable `.blend`. For characters it also
|
||||||
checks skinning, bones, slots, the `npc_base` mesh node and the height.
|
checks skinning, bones, slots, the `npc_base` mesh node and the height.
|
||||||
- `tools/tests/test_blender_assets.py`: catalogue and contract consistency with
|
- `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 library needs variety beyond the original eight silhouettes while preserving
|
||||||
the `npc_base` contract: mesh node, 13 required core bones (optional extras
|
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.
|
character budget.
|
||||||
|
|
||||||
| Source | Licence | Result |
|
| 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.
|
a second face implementation.
|
||||||
|
|
||||||
The current local MPFB full-body prototype (`tmp/npc-research/build_mpfb_npc.py`) assembles the
|
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,
|
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
|
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
|
to loosen the shirt. It is a review candidate, not a shipped asset. The neck is a boolean-cut
|
||||||
of the decimated column bridged by a four-ring, 20-segment lathe (lower rings painted cloth,
|
circular bore bridged by a smooth lathe; the accepted head is trimmed at the narrow neck (z 1.55)
|
||||||
reading as a crew neck); the ankles are hidden by 0.11 m shoe shells and 0.08 m pant cuffs, and a
|
so its wide flat cut brim is discarded, and the lathe flares to cover the bore, then tucks inside
|
||||||
light smoothing pass softens the closed thigh/hip region. The neck skin test is guarded to z >
|
the jaw. This removed the square collar, dark notches and wide brim; a thin jaw crease and a hard
|
||||||
1.35 so it cannot paint the crotch. Remaining polish: the crotch hollow still reads as a V under
|
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 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
|
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
|
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.
|
pass every applicable item before a library rebuild is accepted.
|
||||||
|
|
||||||
1. **Asset contract:** `npc_base` mesh node, the required bones, five tint slots,
|
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
|
front +Z, feet within 3 cm of y=0, 1.6–2.1 m height, at most 24,000 triangles
|
||||||
and 16,000 glTF vertices per character. The required 13 core bones stay fixed;
|
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.
|
optional extra bones are allowed. Gear remains at most 1,500 triangles.
|
||||||
2. **Proportion and silhouette:** head, neck, shoulders, torso, hips, limbs and
|
2. **Proportion and silhouette:** head, neck, shoulders, torso, hips, limbs and
|
||||||
feet read as one body; front/three-quarter/profile silhouettes agree with the
|
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"]
|
SLOTS = ["skin", "cloth", "pants", "accessory", "hair"]
|
||||||
BONES = ["Head", "HipL", "HipR", "KneeL", "KneeR", "ShoulderL", "ShoulderR",
|
BONES = ["Head", "HipL", "HipR", "KneeL", "KneeR", "ShoulderL", "ShoulderR",
|
||||||
"ElbowL", "ElbowR", "HandL", "HandR"]
|
"ElbowL", "ElbowR", "HandL", "HandR"]
|
||||||
# Character cap raised to 16000/16000 on 2026-11-04 for the head/face/hand
|
# Character cap raised to 24000/24000 on 2026-11-05 for the MPFB body, the
|
||||||
# overhaul and possible MakeHuman parts. The required 13 core bones stay, but
|
# accepted MakeHuman head and a seamless neck/shoulder junction. The required
|
||||||
# optional extra bones (fingers, face, toes) are allowed; they must not move the
|
# 13 core bones stay, but optional extra bones (fingers, face, toes) are
|
||||||
# core rest positions. The glTF vertex count is after UV-seam splits; each
|
# allowed; they must not move the core rest positions. The glTF vertex count is
|
||||||
# avatar is still one skinned mesh, and `smoke_npc_budget.gd` must confirm the
|
# after UV-seam splits; each avatar is still one skinned mesh, and the 24-NPC
|
||||||
# 24-NPC frame time before accepting the increase.
|
# smoke test must confirm frame time before shipping.
|
||||||
CHAR_MAX_TRIS = 16000
|
CHAR_MAX_TRIS = 24000
|
||||||
CHAR_MAX_VERTS = 16000
|
CHAR_MAX_VERTS = 24000
|
||||||
GEAR_MAX_TRIS = 1500
|
GEAR_MAX_TRIS = 1500
|
||||||
PROP_MAX_TRIS = 4000
|
PROP_MAX_TRIS = 4000
|
||||||
|
|
||||||
@@ -2486,7 +2486,7 @@ def inspect_glb(path, category=None) -> dict:
|
|||||||
return result
|
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.
|
"""Import an external GLB and adapt it toward the library contract.
|
||||||
|
|
||||||
Applies node transforms, grounds the feet (lowest vertex at y = 0), welds
|
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,
|
ada.add_argument("--file", required=True,
|
||||||
help="external GLB to adapt (absolute path; runs in Blender)")
|
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("--out", required=True, help="where to write the adapted GLB")
|
||||||
ada.add_argument("--target-tris", type=int, default=16000,
|
ada.add_argument("--target-tris", type=int, default=24000,
|
||||||
help="decimate target (default 16000)")
|
help="decimate target (default 24000)")
|
||||||
tex = sub.add_parser("texels", help="per-slot texel density of the character GLBs")
|
tex = sub.add_parser("texels", help="per-slot texel density of the character GLBs")
|
||||||
tex.add_argument("--only", default="")
|
tex.add_argument("--only", default="")
|
||||||
tex.add_argument("--json", action="store_true")
|
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)
|
(plus Hips/Spine/Neck as parents)
|
||||||
* material slots: skin, cloth, pants, accessory, hair
|
* material slots: skin, cloth, pants, accessory, hair
|
||||||
* neutral albedo + normal + packed ORM maps, albedo tinted at runtime
|
* 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
|
* the 13 core bones are required; extra optional bones are allowed
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -45,8 +45,8 @@ BONES = [
|
|||||||
"Head", "HipL", "HipR", "KneeL", "KneeR",
|
"Head", "HipL", "HipR", "KneeL", "KneeR",
|
||||||
"ShoulderL", "ShoulderR", "ElbowL", "ElbowR", "HandL", "HandR",
|
"ShoulderL", "ShoulderR", "ElbowL", "ElbowR", "HandL", "HandR",
|
||||||
]
|
]
|
||||||
MAX_TRIANGLES = 16000
|
MAX_TRIANGLES = 24000
|
||||||
MAX_VERTICES = 16000
|
MAX_VERTICES = 24000
|
||||||
TEX_SIZE = 256
|
TEX_SIZE = 256
|
||||||
AI_DIR = TEX_DIR / "ai"
|
AI_DIR = TEX_DIR / "ai"
|
||||||
# Base material slots that get an AI fabric albedo (`prepare` layers them over
|
# 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):
|
def test_contract_matches_npc_pipeline(self):
|
||||||
self.assertEqual(ba.SLOTS, npc_pipeline.SLOTS)
|
self.assertEqual(ba.SLOTS, npc_pipeline.SLOTS)
|
||||||
self.assertEqual(sorted(ba.BONES), sorted(npc_pipeline.BONES))
|
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.
|
# overhaul; the 13 core bones stay required and extra bones are optional.
|
||||||
self.assertLessEqual(ba.CHAR_MAX_TRIS, 16000)
|
self.assertLessEqual(ba.CHAR_MAX_TRIS, 24000)
|
||||||
self.assertLessEqual(ba.CHAR_MAX_VERTS, 16000)
|
self.assertLessEqual(ba.CHAR_MAX_VERTS, 24000)
|
||||||
|
|
||||||
def test_gear_uses_known_attach_points(self):
|
def test_gear_uses_known_attach_points(self):
|
||||||
for name, attach in ba.GEAR.items():
|
for name, attach in ba.GEAR.items():
|
||||||
@@ -197,7 +197,7 @@ class InspectionTests(unittest.TestCase):
|
|||||||
def test_character_contract_failures_are_listed(self):
|
def test_character_contract_failures_are_listed(self):
|
||||||
stats = self.stats(mesh_nodes=["Armature"], skinned=False, unskinned=["Armature"],
|
stats = self.stats(mesh_nodes=["Armature"], skinned=False, unskinned=["Armature"],
|
||||||
materials=["cloth"], bones=["Head"], meshes_without_uv=1,
|
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]})
|
world_bounds={"min": [-0.3, -0.4, -0.2], "max": [0.3, 1.2, 0.2]})
|
||||||
issues = "\n".join(ba.analyse_inspection(stats)["issues"])
|
issues = "\n".join(ba.analyse_inspection(stats)["issues"])
|
||||||
self.assertIn("no mesh node named npc_base", 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("missing material slot skin", issues)
|
||||||
self.assertIn("mesh not skinned", issues)
|
self.assertIn("mesh not skinned", issues)
|
||||||
self.assertIn("mesh(es) without UVs", issues)
|
self.assertIn("mesh(es) without UVs", issues)
|
||||||
self.assertIn(f"triangles 17000 > {ba.CHAR_MAX_TRIS}", issues)
|
self.assertIn(f"triangles 25000 > {ba.CHAR_MAX_TRIS}", issues)
|
||||||
self.assertIn(f"glTF vertices 17000 > {ba.CHAR_MAX_VERTS}", issues)
|
self.assertIn(f"glTF vertices 25000 > {ba.CHAR_MAX_VERTS}", issues)
|
||||||
self.assertIn("feet not on the ground", issues)
|
self.assertIn("feet not on the ground", issues)
|
||||||
self.assertIn("unexpected height", issues)
|
self.assertIn("unexpected height", issues)
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ class NpcContractTests(unittest.TestCase):
|
|||||||
"ShoulderL", "ShoulderR", "ElbowL", "ElbowR",
|
"ShoulderL", "ShoulderR", "ElbowL", "ElbowR",
|
||||||
"HandL", "HandR"]:
|
"HandL", "HandR"]:
|
||||||
self.assertIn(bone, npc_pipeline.BONES)
|
self.assertIn(bone, npc_pipeline.BONES)
|
||||||
self.assertLessEqual(npc_pipeline.MAX_TRIANGLES, 16000)
|
self.assertLessEqual(npc_pipeline.MAX_TRIANGLES, 24000)
|
||||||
self.assertLessEqual(npc_pipeline.MAX_VERTICES, 16000)
|
self.assertLessEqual(npc_pipeline.MAX_VERTICES, 24000)
|
||||||
|
|
||||||
def test_textures_exist_for_every_slot(self):
|
def test_textures_exist_for_every_slot(self):
|
||||||
for slot in npc_pipeline.SLOTS:
|
for slot in npc_pipeline.SLOTS:
|
||||||
|
|||||||
Reference in new issue
Block a user