Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a196a35342 | ||
|
|
efa062833f | ||
|
|
6381dbc5cb | ||
|
|
7546092c01 | ||
|
|
16dc1dfea4 | ||
|
|
2ba40f3578 | ||
|
|
045ed2a58f | ||
|
|
d3a87acf2d | ||
|
|
b18236f9b4 | ||
|
|
3b9e3b61d8 | ||
|
|
f6bb2b1de3 | ||
|
|
7a46963e3f | ||
|
|
a0dbf75806 | ||
|
|
c70a523f0f | ||
|
|
fcbeee0db2 | ||
|
|
d5e180e50c | ||
|
|
a36068aae7 | ||
|
|
6b58350464 | ||
|
|
219588bf8a | ||
|
|
cba00facf5 | ||
|
|
9fd48243ad | ||
|
|
30d145079a | ||
|
|
98f618c501 | ||
|
|
a290fe83c8 | ||
|
|
529d15ee7a | ||
|
|
3ab7577634 | ||
|
|
c8875a3dfa | ||
|
|
b3acf370fc | ||
|
|
04d211b90b | ||
|
|
a6ccd86f85 | ||
|
|
1ce173e9d1 | ||
|
|
90f189a269 | ||
|
|
fb3e75aba3 | ||
|
|
cd285b3a39 | ||
|
|
68f49253fe | ||
|
|
b012c6a675 | ||
|
|
2a6f29f5d0 | ||
|
|
bb54ef3eec | ||
|
|
11f53f66a3 | ||
|
|
9b65a93587 | ||
|
|
56a14747d4 | ||
|
|
8b1bf736af | ||
|
|
f121167e52 | ||
|
|
140a7ada0f | ||
|
|
5508f5510f | ||
|
|
7baa2c4f54 | ||
|
|
0cd12af994 | ||
|
|
271f10ac4d | ||
|
|
e2f52fbfd1 | ||
|
|
f5fa321a8f | ||
|
|
a2ae9e03c3 | ||
|
|
cff3937c16 | ||
|
|
1ed9e05d9b | ||
|
|
8c69f367b0 | ||
|
|
2a7921bae6 | ||
|
|
b419923637 | ||
|
|
c7fd4b59cc | ||
|
|
3fa3482608 | ||
|
|
1049d8631e | ||
|
|
deb74c53af | ||
|
|
9968bc0a4c | ||
|
|
2e1bb19e2c | ||
|
|
5450dbf88a | ||
|
|
79224c5acf | ||
|
|
f0d4b81239 | ||
|
|
48a9795248 | ||
|
|
a5e62534ce | ||
|
|
cd7697cba4 | ||
|
|
d2f773c7ad | ||
|
|
a3c3a37270 | ||
|
|
8dd4f77901 | ||
|
|
ba444152c9 | ||
|
|
d56f14c6dd | ||
|
|
b297c4543f | ||
|
|
958d3ae0ff |
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
|
||||||
@@ -24,7 +24,7 @@ The project contract and measured gates override any generic Blender advice.
|
|||||||
Blender MCP is optional interactive tooling; the headless flatpak CLI remains
|
Blender MCP is optional interactive tooling; the headless flatpak CLI remains
|
||||||
authoritative and CI never needs Blender or MCP. The `blender-skills` pack is
|
authoritative and CI never needs Blender or MCP. The `blender-skills` pack is
|
||||||
optional, local guidance only, and gitignored. Setup and safety are in
|
optional, local guidance only, and gitignored. Setup and safety are in
|
||||||
`docs/asset-tooling.md#optional-interactive-blender-mcp`.
|
`docs/assets/asset-tooling.md#optional-interactive-blender-mcp`.
|
||||||
|
|
||||||
## Read first
|
## Read first
|
||||||
|
|
||||||
@@ -33,11 +33,11 @@ skill alone:
|
|||||||
|
|
||||||
1. `AGENTS.md` — required workflow and verification.
|
1. `AGENTS.md` — required workflow and verification.
|
||||||
2. `TODO.md` and `MEMORY.md` — current track, claimed tasks, known gotchas.
|
2. `TODO.md` and `MEMORY.md` — current track, claimed tasks, known gotchas.
|
||||||
3. `docs/blender-assets.md` — library contract and command reference.
|
3. `docs/assets/blender-assets.md` — library contract and command reference.
|
||||||
4. `docs/asset-tooling.md` — exact rebuild/bake/capture commands.
|
4. `docs/assets/asset-tooling.md` — exact rebuild/bake/capture commands.
|
||||||
5. `docs/npc-visual-review.md` and `docs/3d-model-review.md` — accepted limits,
|
5. `docs/assets/npc-model-sourcing.md` and `docs/assets/3d-model-review.md` — accepted limits,
|
||||||
scorecards and known blockers.
|
scorecards and known blockers.
|
||||||
6. `docs/known-limitations.md` — limits that must not be silently “fixed” into
|
6. `docs/design/known-limitations.md` — limits that must not be silently “fixed” into
|
||||||
contract changes.
|
contract changes.
|
||||||
|
|
||||||
The contract lives in code and docs, not in this skill. If they disagree, stop
|
The contract lives in code and docs, not in this skill. If they disagree, stop
|
||||||
@@ -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. |
|
||||||
@@ -114,7 +114,7 @@ only the specialists the task needs:
|
|||||||
- budget/LOD/collision: `asset-optimization`, `lod-pipeline`, `collision-proxy`
|
- budget/LOD/collision: `asset-optimization`, `lod-pipeline`, `collision-proxy`
|
||||||
- final review: `qa-review`
|
- final review: `qa-review`
|
||||||
|
|
||||||
If MCP is available, use it for interactive part exploration only; mirror the result into a scripted change or local `.blend`, then re-export and run the CLI audit/fit gates. Never make the build, CI, tests or runtime depend on MCP. Setup: `docs/asset-tooling.md#optional-interactive-blender-mcp`.
|
If MCP is available, use it for interactive part exploration only; mirror the result into a scripted change or local `.blend`, then re-export and run the CLI audit/fit gates. Never make the build, CI, tests or runtime depend on MCP. Setup: `docs/assets/asset-tooling.md#optional-interactive-blender-mcp`.
|
||||||
|
|
||||||
### 4. Build or bake
|
### 4. Build or bake
|
||||||
|
|
||||||
@@ -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.
|
||||||
@@ -185,7 +185,7 @@ gates run, and any accepted limit.
|
|||||||
- **Empty or stale captures** — close modals/pause, check the capture script's
|
- **Empty or stale captures** — close modals/pause, check the capture script's
|
||||||
settle frames, and remove stale output directories before re-running.
|
settle frames, and remove stale output directories before re-running.
|
||||||
- **Pose harness mismatch** — the current `capture_npc_pose.gd` is blocked per
|
- **Pose harness mismatch** — the current `capture_npc_pose.gd` is blocked per
|
||||||
`docs/3d-model-review.md`; do not use its frames as pose evidence until the
|
`docs/assets/3d-model-review.md`; do not use its frames as pose evidence until the
|
||||||
recipe is fixed.
|
recipe is fixed.
|
||||||
- **Asset test fails after import** — re-run audit/fit first, then import; if the
|
- **Asset test fails after import** — re-run audit/fit first, then import; if the
|
||||||
manifest or AO path changed, rebuild the affected asset rather than editing
|
manifest or AO path changed, rebuild the affected asset rather than editing
|
||||||
@@ -197,7 +197,7 @@ gates run, and any accepted limit.
|
|||||||
|
|
||||||
- [`references/asset-contract.md`](references/asset-contract.md) — full contract,
|
- [`references/asset-contract.md`](references/asset-contract.md) — full contract,
|
||||||
inventory, file locations and provenance rules.
|
inventory, file locations and provenance rules.
|
||||||
- `docs/asset-tooling.md#optional-interactive-blender-mcp` — optional MCP installation, connection, safety and
|
- `docs/assets/asset-tooling.md#optional-interactive-blender-mcp` — optional MCP installation, connection, safety and
|
||||||
part-workflow instructions.
|
part-workflow instructions.
|
||||||
- [`references/verification.md`](references/verification.md) — command matrix,
|
- [`references/verification.md`](references/verification.md) — command matrix,
|
||||||
capture gates, expected results and acceptance criteria.
|
capture gates, expected results and acceptance criteria.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Asset Contract Reference
|
# Asset Contract Reference
|
||||||
|
|
||||||
This is a working summary. The authoritative sources remain
|
This is a working summary. The authoritative sources remain
|
||||||
`docs/blender-assets.md`, `docs/asset-tooling.md`, ADR-0013, the tests in
|
`docs/assets/blender-assets.md`, `docs/assets/asset-tooling.md`, ADR-0013, the tests in
|
||||||
`src/test/tests/` and the constants in `tools/blender_assets.py` /
|
`src/test/tests/` and the constants in `tools/blender_assets.py` /
|
||||||
`tools/npc_pipeline.py`.
|
`tools/npc_pipeline.py`.
|
||||||
|
|
||||||
@@ -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 |
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ For each changed variant, inspect at least:
|
|||||||
- Day and night/LATE final-context frames.
|
- Day and night/LATE final-context frames.
|
||||||
- Front, three-quarter and profile for a shape change.
|
- Front, three-quarter and profile for a shape change.
|
||||||
|
|
||||||
Accepted stylized limits are in `docs/npc-visual-review.md` and
|
Accepted stylized limits are in `docs/assets/3d-model-review.md` and
|
||||||
`docs/known-limitations.md`. Do not turn an accepted limit into an unreviewed
|
`docs/design/known-limitations.md`. Do not turn an accepted limit into an unreviewed
|
||||||
contract change.
|
contract change.
|
||||||
|
|
||||||
## Final diff review
|
## Final diff review
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ publishing, and the full visual/QA gate. For a Blender/asset rebuild, use
|
|||||||
|
|
||||||
1. `AGENTS.md` — release procedure and verification rules.
|
1. `AGENTS.md` — release procedure and verification rules.
|
||||||
2. `TODO.md` — current milestone, blockers and release exit criteria.
|
2. `TODO.md` — current milestone, blockers and release exit criteria.
|
||||||
3. `docs/RELEASING.md` — build/publish commands, artifact list, macOS policy.
|
3. `docs/process/RELEASING.md` — build/publish commands, artifact list, macOS policy.
|
||||||
4. `docs/release-qa.md` — manual QA matrix and balance protocol.
|
4. `docs/process/release-qa.md` — manual QA matrix and balance protocol.
|
||||||
5. `docs/development-status.md`, `CHANGELOG.md`, `README.md` — current claims.
|
5. `docs/project/development-status.md`, `CHANGELOG.md`, `README.md` — current claims.
|
||||||
6. `MEMORY.md` — release gotchas, especially the clean-worktree rule.
|
6. `MEMORY.md` — release gotchas, especially the clean-worktree rule.
|
||||||
|
|
||||||
A release is not just a tag. It includes a version bump, changelog, clean build,
|
A release is not just a tag. It includes a version bump, changelog, clean build,
|
||||||
@@ -58,8 +58,8 @@ Update:
|
|||||||
|
|
||||||
1. `project.godot` `config/version`.
|
1. `project.godot` `config/version`.
|
||||||
2. `CHANGELOG.md` with a dated entry.
|
2. `CHANGELOG.md` with a dated entry.
|
||||||
3. `README.md`, `PLAN.md`, `docs/architecture.md`,
|
3. `README.md`, `PLAN.md`, `docs/project/architecture.md`,
|
||||||
`docs/development-status.md`, `TODO.md`/`DONE.md` and `MEMORY.md` as needed.
|
`docs/project/development-status.md`, `TODO.md`/`DONE.md` and `MEMORY.md` as needed.
|
||||||
|
|
||||||
For a release candidate, use a prerelease version only if the project policy
|
For a release candidate, use a prerelease version only if the project policy
|
||||||
allows it and never present it as the final release.
|
allows it and never present it as the final release.
|
||||||
@@ -213,7 +213,7 @@ The default `RETAIN_RELEASES=0` never prunes.
|
|||||||
|
|
||||||
### 7. Post-release record
|
### 7. Post-release record
|
||||||
|
|
||||||
Update `README.md`, `docs/development-status.md`, `MEMORY.md`, `CHANGELOG.md`,
|
Update `README.md`, `docs/project/development-status.md`, `MEMORY.md`, `CHANGELOG.md`,
|
||||||
`TODO.md`/`DONE.md` and the release page with the built/CI result. Commit the
|
`TODO.md`/`DONE.md` and the release page with the built/CI result. Commit the
|
||||||
release record and push. Record any skipped check and the reason; never leave a
|
release record and push. Record any skipped check and the reason; never leave a
|
||||||
tag with unreported missing verification.
|
tag with unreported missing verification.
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ python3 tools/screen_designs.py judge --model auto
|
|||||||
```
|
```
|
||||||
|
|
||||||
Record model, confidence/verdict summary, `diff` count and any manual review.
|
Record model, confidence/verdict summary, `diff` count and any manual review.
|
||||||
`docs/ui-copy.md#screen-design-judge-report` is the durable record.
|
`docs/design/ui-copy.md#screen-design-judge-report` is the durable record.
|
||||||
|
|
||||||
## 6. Realism judge (when visual assets/lighting changed)
|
## 6. Realism judge (when visual assets/lighting changed)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Release Runbook
|
# Release Runbook
|
||||||
|
|
||||||
Authoritative source: `AGENTS.md` (Release Procedure), `docs/RELEASING.md`.
|
Authoritative source: `AGENTS.md` (Release Procedure), `docs/process/RELEASING.md`.
|
||||||
This runbook is the operational checklist; if it conflicts with those, they win.
|
This runbook is the operational checklist; if it conflicts with those, they win.
|
||||||
|
|
||||||
## 0. Decide the release
|
## 0. Decide the release
|
||||||
@@ -29,8 +29,8 @@ Files to update:
|
|||||||
| `project.godot` | `config/version="X.Y.Z"` |
|
| `project.godot` | `config/version="X.Y.Z"` |
|
||||||
| `CHANGELOG.md` | dated `## [X.Y.Z] — YYYY-MM-DD` entry |
|
| `CHANGELOG.md` | dated `## [X.Y.Z] — YYYY-MM-DD` entry |
|
||||||
| `README.md` | latest/current version and summary |
|
| `README.md` | latest/current version and summary |
|
||||||
| `PLAN.md` / `docs/architecture.md` | current version reference |
|
| `PLAN.md` / `docs/project/architecture.md` | current version reference |
|
||||||
| `docs/development-status.md` | shipped capability/release result |
|
| `docs/project/development-status.md` | shipped capability/release result |
|
||||||
| `TODO.md` / `DONE.md` | close/move milestone when complete |
|
| `TODO.md` / `DONE.md` | close/move milestone when complete |
|
||||||
| `MEMORY.md` | release state and gotchas |
|
| `MEMORY.md` | release state and gotchas |
|
||||||
|
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ The project should be developed in small, reviewable steps. Agents must keep pla
|
|||||||
- `README.md` — Root-level documentation for the project. It should explain what the game is, how to work on it, how to run it, and where to find project information.
|
- `README.md` — Root-level documentation for the project. It should explain what the game is, how to work on it, how to run it, and where to find project information.
|
||||||
- `AGENTS.md` — This collaboration and agent workflow guide.
|
- `AGENTS.md` — This collaboration and agent workflow guide.
|
||||||
- `CHANGELOG.md` — The version history of user-facing changes. Keep an entry for each patch, minor, and major version.
|
- `CHANGELOG.md` — The version history of user-facing changes. Keep an entry for each patch, minor, and major version.
|
||||||
- `docs/development-status.md` — The implemented-features list and what is not yet implemented. Update it whenever a feature lands, is renamed, or is removed.
|
- `docs/project/development-status.md` — The implemented-features list and what is not yet implemented. Update it whenever a feature lands, is renamed, or is removed.
|
||||||
- `docs/architecture.md` — The arc42-style architecture documentation (goals, constraints, building blocks, runtime views, decisions, risks).
|
- `docs/project/architecture.md` — The arc42-style architecture documentation (goals, constraints, building blocks, runtime views, decisions, risks).
|
||||||
- `docs/gameplay.md` — Gameplay systems, tutorial, venues and the escalation model.
|
- `docs/design/gameplay.md` — Gameplay systems, tutorial, venues and the escalation model.
|
||||||
- `docs/venues.md` — Real-site evidence, game mapping and venue simplifications.
|
- `docs/design/venues.md` — Real-site evidence, game mapping and venue simplifications.
|
||||||
- `docs/asset-tooling.md` — Asset pipelines, model tools, optional Blender MCP and screenshot gates.
|
- `docs/assets/asset-tooling.md` — Asset pipelines, model tools, optional Blender MCP and screenshot gates.
|
||||||
- `docs/blender-assets.md` — Blender library operation and asset roles.
|
- `docs/assets/blender-assets.md` — Blender library operation and asset roles.
|
||||||
- `docs/npc-model-sourcing.md` — Character-source evaluation, licence rules and the character-development plan.
|
- `docs/assets/npc-model-sourcing.md` — Character-source evaluation, licence rules and the character-development plan.
|
||||||
- `docs/getting-started.md` — Setup, run/test commands, and the controls table.
|
- `docs/process/getting-started.md` — Setup, run/test commands, and the controls table.
|
||||||
- `docs/release-qa.md` — The manual smoke checklist and balance-acceptance protocol.
|
- `docs/process/release-qa.md` — The manual smoke checklist and balance-acceptance protocol.
|
||||||
- `docs/adr/` — Architecture Decision Records.
|
- `docs/adr/` — Architecture Decision Records.
|
||||||
|
|
||||||
## Priority and Versioning
|
## Priority and Versioning
|
||||||
@@ -90,22 +90,27 @@ 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, five tint slots, front on Blender −Y /
|
||||||
positions, five tint slots, front on Blender −Y / Godot +Z, grounded feet, 16,000
|
Godot +Z, grounded feet, 24,000 triangles / 24,000 glTF vertices per character, 1,500 per
|
||||||
triangles / 16,000 glTF vertices per character, 1,500 per gear, 4,000 per prop. Optional
|
gear, 4,000 per prop. The shipped procedural library uses the 13 required core bones at their
|
||||||
extra bones (fingers, face, toes) are allowed if they do not move the core rest positions. A skill
|
rest positions; optional extra bones (fingers, face, toes) are allowed if they do not move the
|
||||||
may recommend another topology, naming or budget scheme; do not adopt it unless the
|
core rest positions. The one documented exception is the accepted Quaternius runtime path
|
||||||
change is explicitly planned and the contract, tests and docs are updated together.
|
([ADR-0018](docs/adr/0018-quaternius-stage2-runtime-rig.md)): it keeps the 62-joint source rig
|
||||||
|
at runtime while the 0.9.9 face/silhouette gate is open, and it must still supply the five tint
|
||||||
|
slots, valid gear attach points and the same budgets. Both paths stay tested until that gate
|
||||||
|
closes. 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.
|
||||||
2. **Blender MCP is optional interactive tooling.** The headless flatpak scripts
|
2. **Blender MCP is optional interactive tooling.** The headless flatpak scripts
|
||||||
(`tools/blender_assets.py`, `tools/npc_pipeline.py`) remain authoritative. MCP may be used
|
(`tools/blender_assets.py`, `tools/npc_pipeline.py`) remain authoritative. MCP may be used
|
||||||
for local part exploration; setup and safety are in [`docs/asset-tooling.md#optional-interactive-blender-mcp`](docs/asset-tooling.md#optional-interactive-blender-mcp).
|
for local part exploration; setup and safety are in [`docs/assets/asset-tooling.md#optional-interactive-blender-mcp`](docs/assets/asset-tooling.md#optional-interactive-blender-mcp).
|
||||||
Never add an MCP dependency to the build, CI, tests or runtime, and always re-run the CLI
|
Never add an MCP dependency to the build, CI, tests or runtime, and always re-run the CLI
|
||||||
audit/fit gates on anything MCP touched.
|
audit/fit gates on anything MCP touched.
|
||||||
3. **CI stays offline and skill-free.** Skills are local guidance only; every gate must still
|
3. **CI stays offline and skill-free.** Skills are local guidance only; every gate must still
|
||||||
work from a fresh checkout with committed `.glb`/`.png`/`.tres` files and Godot.
|
work from a fresh checkout with committed `.glb`/`.png`/`.tres` files and Godot.
|
||||||
4. **No new asset source without the licence gate.** Skills may suggest reference packs or
|
4. **No new asset source without the licence gate.** Skills may suggest reference packs or
|
||||||
generated meshes; ADR-0015 (CC0, or CC-BY with attribution in `CREDITS.md`) and the
|
generated meshes; ADR-0017 (the CC0 Quaternius NPC base) supersedes the generator-first
|
||||||
provenance rules in `docs/npc-model-sourcing.md` still apply.
|
decision in ADR-0015, and the CC0/CC-BY rule in ADR-0015 (attribution in `CREDITS.md`) plus
|
||||||
|
the provenance rules in `docs/assets/npc-model-sourcing.md` still apply to any new source.
|
||||||
5. **Evidence, not vibes.** After a skill-informed change, run `blender_assets.py inspect`,
|
5. **Evidence, not vibes.** After a skill-informed change, run `blender_assets.py inspect`,
|
||||||
`audit` and `fit` plus the relevant capture/smoke gates, and say in the handoff which
|
`audit` and `fit` plus the relevant capture/smoke gates, and say in the handoff which
|
||||||
skills informed the change and what the measurements were.
|
skills informed the change and what the measurements were.
|
||||||
@@ -191,7 +196,7 @@ first, then versioned milestones in version order, then future/deferred work.
|
|||||||
level-3 section to `DONE.md`.
|
level-3 section to `DONE.md`.
|
||||||
2. **Level-2 milestone/theme:** it is complete only when its direct checkboxes and **all** of its
|
2. **Level-2 milestone/theme:** it is complete only when its direct checkboxes and **all** of its
|
||||||
level-3 workstreams are complete. Verify the whole milestone, record its capabilities in
|
level-3 workstreams are complete. Verify the whole milestone, record its capabilities in
|
||||||
`docs/development-status.md` when it represents shipped functionality, and write the matching
|
`docs/project/development-status.md` when it represents shipped functionality, and write the matching
|
||||||
`CHANGELOG.md` entry.
|
`CHANGELOG.md` entry.
|
||||||
3. Move the **entire level-2 section**, including all level-3 headings and checklists, to
|
3. Move the **entire level-2 section**, including all level-3 headings and checklists, to
|
||||||
`DONE.md`. Remove it from `TODO.md` and add a completion date/note.
|
`DONE.md`. Remove it from `TODO.md` and add a completion date/note.
|
||||||
@@ -202,7 +207,7 @@ first, then versioned milestones in version order, then future/deferred work.
|
|||||||
complete, or split the unfinished work into a new smaller level-2 milestone first.
|
complete, or split the unfinished work into a new smaller level-2 milestone first.
|
||||||
|
|
||||||
When a completed milestone represents shipped functionality, also record the new capability in
|
When a completed milestone represents shipped functionality, also record the new capability in
|
||||||
`docs/development-status.md` so the implemented-features list stays accurate, and write a matching
|
`docs/project/development-status.md` so the implemented-features list stays accurate, and write a matching
|
||||||
entry in `CHANGELOG.md` (see "Maintain `CHANGELOG.md`" below).
|
entry in `CHANGELOG.md` (see "Maintain `CHANGELOG.md`" below).
|
||||||
|
|
||||||
### 4. Maintain `MEMORY.md`
|
### 4. Maintain `MEMORY.md`
|
||||||
@@ -212,7 +217,7 @@ Use `MEMORY.md` for information that should persist between sessions but does no
|
|||||||
Record items such as:
|
Record items such as:
|
||||||
|
|
||||||
- Important design and architecture decisions
|
- Important design and architecture decisions
|
||||||
- Notable implementation state and gotchas (the canonical implemented-features list lives in `docs/development-status.md`, not here)
|
- Notable implementation state and gotchas (the canonical implemented-features list lives in `docs/project/development-status.md`, not here)
|
||||||
- Known bugs and workarounds
|
- Known bugs and workarounds
|
||||||
- Commands needed to run, test, or build the project
|
- Commands needed to run, test, or build the project
|
||||||
- Decisions that future agents should not revisit unnecessarily
|
- Decisions that future agents should not revisit unnecessarily
|
||||||
@@ -262,7 +267,7 @@ The root-level `README.md` is the project’s public-facing technical and projec
|
|||||||
- Links to `PLAN.md`, `TODO.md`, `DONE.md`, `MEMORY.md`, and this file where appropriate
|
- Links to `PLAN.md`, `TODO.md`, `DONE.md`, `MEMORY.md`, and this file where appropriate
|
||||||
- Known limitations and contribution guidance
|
- Known limitations and contribution guidance
|
||||||
|
|
||||||
Update `README.md` whenever setup instructions, commands, project structure, or user-facing behavior changes. The README is intentionally concise and links to the `docs/` files; keep `docs/development-status.md` (and the other docs it links to) synchronized with the implementation rather than pasting detail back into the README.
|
Update `README.md` whenever setup instructions, commands, project structure, or user-facing behavior changes. The README is intentionally concise and links to the `docs/` files; keep `docs/project/development-status.md` (and the other docs it links to) synchronized with the implementation rather than pasting detail back into the README.
|
||||||
|
|
||||||
### 7. Maintain `CHANGELOG.md`
|
### 7. Maintain `CHANGELOG.md`
|
||||||
|
|
||||||
@@ -292,7 +297,7 @@ For each task:
|
|||||||
2. Inspect the relevant files and dependencies.
|
2. Inspect the relevant files and dependencies.
|
||||||
3. Make the smallest coherent change that completes the task.
|
3. Make the smallest coherent change that completes the task.
|
||||||
4. Run the relevant tests, checks, or manual verification.
|
4. Run the relevant tests, checks, or manual verification.
|
||||||
5. Update documentation if the change creates lasting context: add features to `docs/development-status.md`, adjust the README links or other `docs/` files as needed, and record decisions/gotchas in `MEMORY.md`.
|
5. Update documentation if the change creates lasting context: add features to `docs/project/development-status.md`, adjust the README links or other `docs/` files as needed, and record decisions/gotchas in `MEMORY.md`.
|
||||||
6. Mark the task complete.
|
6. Mark the task complete.
|
||||||
7. Keep completed level-3 workstreams in place until the parent milestone is complete; then move the entire level-2 milestone to `DONE.md` after recording its `CHANGELOG.md` entry.
|
7. Keep completed level-3 workstreams in place until the parent milestone is complete; then move the entire level-2 milestone to `DONE.md` after recording its `CHANGELOG.md` entry.
|
||||||
8. Commit each coherent, verified change as it is completed. Do not wait until a whole
|
8. Commit each coherent, verified change as it is completed. Do not wait until a whole
|
||||||
|
|||||||
@@ -4,6 +4,74 @@ 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]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- The red event banners are lit from the top down at night instead of reading as flat red cards.
|
||||||
|
- Hollywood and the TV Studio got the same queue treatment, and the TV Studio's props no longer sit
|
||||||
|
in the entrance steps.
|
||||||
|
- The Joke Shop has a readable queue: a velvet rope line leading to the check-in podium, a thicker
|
||||||
|
bike-rack barricade on the curb side, and a planter no longer clipping the palm foliage.
|
||||||
|
- Street lamps now throw a warm pool on the pavement instead of dimly washing the whole walkway.
|
||||||
|
- The flashlight actually lights what it points at. It was tuned to a beam so weak it changed the
|
||||||
|
frame by less than one 255th of a level; it now throws a visible pool on the door and the pavement
|
||||||
|
ahead, in both venues.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Street greenery now reads as leaves instead of green rocks: the planter shrubs and tree crowns
|
||||||
|
are built from leaf cards, which also cut their triangle count by about a third.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Removed every hat and hood from the NPC roster: the firefighter helmet is the only head gear
|
||||||
|
left, so no character hides its face behind a cap. The street performer no longer wears the
|
||||||
|
cone hat and carries the baton and board in the hands instead.
|
||||||
|
- Hands, head gear and carried items were re-fitted to the new characters: hand items sit in the
|
||||||
|
palm instead of floating at the wrist, the lanyard moved up to the sternum, back gear moved up to
|
||||||
|
shoulder-blade height, and the clipboard is carried by its top edge.
|
||||||
|
- NPCs now wear eleven different outfits instead of three: the modular outfit pack brought a formal
|
||||||
|
suit for the influencer, a punk jacket and mohawk, beach wear, farmer overalls and straw hat, an
|
||||||
|
adventurer jacket, a second casual jersey, and royal armour with a gold crown for the street
|
||||||
|
performer.
|
||||||
|
- NPCs no longer all share one hairstyle: the roster now uses short, buzz and long hair silhouettes
|
||||||
|
instead of a single shell in twelve colours.
|
||||||
|
- Eyes now have whites and pupils instead of flat dark rectangles.
|
||||||
|
- Every NPC now has a visible mouth; the Quaternius heads shipped without one, so the faces read as
|
||||||
|
brow-and-eye masks.
|
||||||
|
- Fixed the modular Worker characters: the guard, delivery, firefighter and crowd roles had holes
|
||||||
|
in the torso and an open crown, a continuous unibrow and no visible eyes. They now have a closed
|
||||||
|
torso, hair, two eyebrows and two eyes.
|
||||||
|
|
||||||
|
## [0.9.9] — 2026-11-06
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Raised the character mesh budget from 16,000 to 24,000 triangles and glTF
|
||||||
|
vertices so the Quaternius base and the role-dressed variants fit without
|
||||||
|
heavy decimation. Gear and prop budgets are unchanged.
|
||||||
|
- Replaced the whole NPC roster with the CC0 Quaternius characters. All twelve
|
||||||
|
characters (tourist, jacket, coat, vest, dress, hoodie, firefighter, guard and
|
||||||
|
the four crowd variants) now use one of three source outfits — casual tee,
|
||||||
|
hoodie or work clothes — dressed by role with the five tint slots and the gear
|
||||||
|
library. The procedural library and the MakeHuman head remain in the build as
|
||||||
|
the fallback.
|
||||||
|
- Characters stand with their arms down instead of a T/A pose, and the seated,
|
||||||
|
idle and walking poses swing from the shoulder and hip the way the animation
|
||||||
|
code intends on the new skeleton.
|
||||||
|
- Head gear (cap, hood, sunglasses, firefighter helmet) and the camera were
|
||||||
|
resized for the new head and arm. The camera now hangs from a wrist strap
|
||||||
|
instead of a neck strap that floated next to the head.
|
||||||
|
- The backpack straps were pulled in so they sit on the chest instead of
|
||||||
|
hovering in front of it.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Characters no longer render with black legs or black patches: the new base
|
||||||
|
carried a collapsed UV map that made the ambient-occlusion bake come out
|
||||||
|
black, and the roster is now unwrapped and baked correctly.
|
||||||
|
|
||||||
## [0.9.8] — 2026-11-04
|
## [0.9.8] — 2026-11-04
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ been cleared for public distribution.
|
|||||||
|
|
||||||
## 3D characters, gear and props
|
## 3D characters, gear and props
|
||||||
|
|
||||||
|
The local MakeHuman head prototype uses the CC0 MakeHuman/MPFB base mesh
|
||||||
|
(see [`docs/assets/makehuman-head-review.md`](docs/assets/makehuman-head-review.md)); it is a
|
||||||
|
development prototype, not a shipped character.
|
||||||
|
|
||||||
The character, gear and prop library is generated by project-owned scripts
|
The character, gear and prop library is generated by project-owned scripts
|
||||||
(`tools/blender_assets.py`, `tools/npc_pipeline.py`, `tools/model_pipeline.py`)
|
(`tools/blender_assets.py`, `tools/npc_pipeline.py`, `tools/model_pipeline.py`)
|
||||||
using Blender. The `.blend` working sources are developer artifacts and are not
|
using Blender. The `.blend` working sources are developer artifacts and are not
|
||||||
@@ -42,12 +46,22 @@ shipped derivative of CesiumMan or RiggedFigure must keep the attribution above.
|
|||||||
|
|
||||||
### MakeHuman head source
|
### MakeHuman head source
|
||||||
|
|
||||||
The decimated head used by the character head prototype is derived from the
|
The standalone MakeHuman head prototype is derived from the MakeHuman / MPFB base
|
||||||
MakeHuman / MPFB base mesh, **CC0** (`assets/models/blender_src/makehuman_head.glb`;
|
mesh, **CC0** (`assets/models/blender_src/makehuman_head.glb`; source
|
||||||
source `tmp/npc-research/makehuman/base.obj` with its bundled
|
<https://static.makehumancommunity.org/makehuman.html>, MakeHuman base mesh,
|
||||||
`LICENSE.md`/`LICENSE.ASSETS.md`). It is retargeted, decimated and re-weighted by
|
CC0 1.0). It is cut, retopologised and re-weighted by project scripts; the exported
|
||||||
project scripts; the exported character GLBs remain project assets. See ADR-0015
|
character GLBs remain project assets. The development source files were removed
|
||||||
and `docs/npc-model-sourcing.md`.
|
from `tmp/` after the 2026-11-05 pivot to Quaternius. The head is retained as a
|
||||||
|
tested fallback, not the active NPC base. See ADR-0017 and
|
||||||
|
`docs/assets/npc-model-sourcing.md`.
|
||||||
|
|
||||||
|
### Quaternius NPC base source
|
||||||
|
|
||||||
|
The active NPC base migration uses **Quaternius Ultimate Modular Characters** and
|
||||||
|
**Ultimate Modular Women** (CC0 1.0, <https://quaternius.com/>). The three
|
||||||
|
researched GLBs are development inputs and are not shipped directly; the baked,
|
||||||
|
retargeted character GLBs are project assets. See ADR-0017 and
|
||||||
|
`docs/assets/npc-model-sourcing.md` for the decision, source hashes and rollout status.
|
||||||
|
|
||||||
The venue geometry is authored procedurally in `src/game/world_builder.gd` as a
|
The venue geometry is authored procedurally in `src/game/world_builder.gd` as a
|
||||||
stylized reconstruction. The Joke Shop is a fictional stand-in for the real
|
stylized reconstruction. The Joke Shop is a fictional stand-in for the real
|
||||||
@@ -104,7 +118,7 @@ reference more directly, its attribution and licence must be added here.
|
|||||||
|
|
||||||
All runtime audio is procedural (crowd bed, radio crackle and interface cues).
|
All runtime audio is procedural (crowd bed, radio crackle and interface cues).
|
||||||
There are no external audio files, so there is no separate music/SFX licence to
|
There are no external audio files, so there is no separate music/SFX licence to
|
||||||
clear. See `docs/accessibility.md` for caption and volume behaviour.
|
clear. See `docs/design/accessibility.md` for caption and volume behaviour.
|
||||||
|
|
||||||
## Third-party names
|
## Third-party names
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ Completed task sections moved from `TODO.md`. Sections are moved only when every
|
|||||||
|
|
||||||
- [x] Commit `export_presets.cfg` with Linux, Windows, and macOS desktop presets.
|
- [x] Commit `export_presets.cfg` with Linux, Windows, and macOS desktop presets.
|
||||||
- [x] Add `tools/build_releases.sh` for headless release exports.
|
- [x] Add `tools/build_releases.sh` for headless release exports.
|
||||||
- [x] Add `docs/RELEASING.md` with template installation, build, and Gitea release steps.
|
- [x] Add `docs/process/RELEASING.md` with template installation, build, and Gitea release steps.
|
||||||
- [x] Add a prominent **Downloads** section at the top of `README.md` linking to the release page.
|
- [x] Add a prominent **Downloads** section at the top of `README.md` linking to the release page.
|
||||||
- [x] Add `tools/publish_release.sh` (Gitea API release + asset upload, requires `GITEA_TOKEN`).
|
- [x] Add `tools/publish_release.sh` (Gitea API release + asset upload, requires `GITEA_TOKEN`).
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ Completed task sections moved from `TODO.md`. Sections are moved only when every
|
|||||||
- [x] Tag builds automatically publish the Gitea release via `tools/publish_release.sh` using
|
- [x] Tag builds automatically publish the Gitea release via `tools/publish_release.sh` using
|
||||||
the `GITEA_TOKEN` secret.
|
the `GITEA_TOKEN` secret.
|
||||||
- [x] Remove the old `.github/workflows/ci.yml` to avoid double runs on hosts scanning both paths.
|
- [x] Remove the old `.github/workflows/ci.yml` to avoid double runs on hosts scanning both paths.
|
||||||
- [x] Document the CI flow in `docs/RELEASING.md`.
|
- [x] Document the CI flow in `docs/process/RELEASING.md`.
|
||||||
|
|
||||||
## Gameplay — Venue selection
|
## Gameplay — Venue selection
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ Completed task sections moved from `TODO.md`. Sections are moved only when every
|
|||||||
service; ~2 min of retry timeouts per run; Godot import is fast without it).
|
service; ~2 min of retry timeouts per run; Godot import is fast without it).
|
||||||
- [x] Add `GODOT_SILENCE_ROOT_WARNING=1` to both jobs.
|
- [x] Add `GODOT_SILENCE_ROOT_WARNING=1` to both jobs.
|
||||||
- [x] Confirmed in run 1090: zero `CacheService` lines, 54/54 tests pass, job succeeds.
|
- [x] Confirmed in run 1090: zero `CacheService` lines, 54/54 tests pass, job succeeds.
|
||||||
- [x] Document the cache situation and re-enable path in `docs/RELEASING.md`.
|
- [x] Document the cache situation and re-enable path in `docs/process/RELEASING.md`.
|
||||||
- [x] Ignore runner logs in `.gitignore` (`.gitea/logs/`).
|
- [x] Ignore runner logs in `.gitignore` (`.gitea/logs/`).
|
||||||
|
|
||||||
## Gameplay — Venue door-staff dialogue
|
## Gameplay — Venue door-staff dialogue
|
||||||
@@ -660,7 +660,7 @@ produces a 63 MB static bundle and it serves locally with HTTP 200s for html/was
|
|||||||
- [x] Publish the web zip with the desktop artifacts (`tools/publish_release.sh`).
|
- [x] Publish the web zip with the desktop artifacts (`tools/publish_release.sh`).
|
||||||
- [x] Cover the preset, the non-threaded choice, and the release wiring in
|
- [x] Cover the preset, the non-threaded choice, and the release wiring in
|
||||||
`src/test/tests/test_web_export.gd`.
|
`src/test/tests/test_web_export.gd`.
|
||||||
- [x] Document the artifact in `docs/RELEASING.md`, the README gallery/status, and `PLAN.md`.
|
- [x] Document the artifact in `docs/process/RELEASING.md`, the README gallery/status, and `PLAN.md`.
|
||||||
|
|
||||||
## Prop Texture Atlas
|
## Prop Texture Atlas
|
||||||
|
|
||||||
@@ -909,7 +909,7 @@ Goal: replace the outdated flat skyline backdrop (`assets/textures/skyline.png`,
|
|||||||
with dot windows) and the flat-looking surface tiles with AI-generated, more realistic
|
with dot windows) and the flat-looking surface tiles with AI-generated, more realistic
|
||||||
backgrounds and textures. Add a larger set of example 3D scene images as art direction, and
|
backgrounds and textures. Add a larger set of example 3D scene images as art direction, and
|
||||||
measure the in-game result against that target with the screenshot tools. Plan:
|
measure the in-game result against that target with the screenshot tools. Plan:
|
||||||
[`PLAN.md` → Visual Quality Direction → Realism pass](PLAN.md#realism-pass).
|
[`PLAN.md` → Visual Quality Direction → Realism pass](PLAN.md#presentation-and-controls).
|
||||||
|
|
||||||
**Rule for every step: never overwrite an existing image.** New outputs get new paths. When a
|
**Rule for every step: never overwrite an existing image.** New outputs get new paths. When a
|
||||||
path is taken, the tools pick the next free `-vN` suffix. Raw AI output stays on disk under
|
path is taken, the tools pick the next free `-vN` suffix. Raw AI output stays on disk under
|
||||||
@@ -1047,7 +1047,7 @@ reports to `docs/screens/realism/<run>/`.
|
|||||||
`docs/screens/realism/2026-11-01-adopt/` (3 judge repeats per shot) gives a like-for-like
|
`docs/screens/realism/2026-11-01-adopt/` (3 judge repeats per shot) gives a like-for-like
|
||||||
improvement on every sub-score: overall 0.8→1.0, lighting 0.8→1.0, materials 0.8→1.0,
|
improvement on every sub-score: overall 0.8→1.0, lighting 0.8→1.0, materials 0.8→1.0,
|
||||||
texture 0.8→1.0, backdrop 0.6→1.6, and the Pillow metric gap 0.444→0.348.
|
texture 0.8→1.0, backdrop 0.6→1.6, and the Pillow metric gap 0.444→0.348.
|
||||||
- [x] Update `README.md` (tool usage + gallery), `MEMORY.md` and `docs/architecture.md`.
|
- [x] Update `README.md` (tool usage + gallery), `MEMORY.md` and `docs/project/architecture.md`.
|
||||||
|
|
||||||
## Realism Follow-ups — Lighting, Flashlight, NPC Detail
|
## Realism Follow-ups — Lighting, Flashlight, NPC Detail
|
||||||
|
|
||||||
@@ -1087,7 +1087,7 @@ Completed 2026-11-01. The follow-ups left over after the texture/skyline adoptio
|
|||||||
bridge and tip, ears with lobes, and split upper/lower lips. Hands have four fingers plus a
|
bridge and tip, ears with lobes, and split upper/lower lips. Hands have four fingers plus a
|
||||||
thumb, and every sleeve ends in a cuff ring.
|
thumb, and every sleeve ends in a cuff ring.
|
||||||
- [x] Raised `CHAR_MAX_VERTS` 4000 → **5000** (documented in the code and
|
- [x] Raised `CHAR_MAX_VERTS` 4000 → **5000** (documented in the code and
|
||||||
`docs/blender-assets.md`) after measuring 16 avatars at ~6.9 ms of a 50 ms frame on a single
|
`docs/assets/blender-assets.md`) after measuring 16 avatars at ~6.9 ms of a 50 ms frame on a single
|
||||||
skinned mesh, so `npc_coat` fits at 4807 vertices; the character range is now 3,974–5,026
|
skinned mesh, so `npc_coat` fits at 4807 vertices; the character range is now 3,974–5,026
|
||||||
triangles and 3,744–4,807 vertices. Body decimation 0.36 → 0.26.
|
triangles and 3,744–4,807 vertices. Body decimation 0.36 → 0.26.
|
||||||
- [x] Rebuilt all 8 variants and re-baked their AO maps (`assets/models/blender/npc/*_ao.png`),
|
- [x] Rebuilt all 8 variants and re-baked their AO maps (`assets/models/blender/npc/*_ao.png`),
|
||||||
@@ -1114,14 +1114,14 @@ Completed 2026-11-01.
|
|||||||
- [x] Decide the canonical runtime image root (`assets/images/` for UI/scene art): recorded in
|
- [x] Decide the canonical runtime image root (`assets/images/` for UI/scene art): recorded in
|
||||||
`MEMORY.md` and [ADR-0014](docs/adr/0014-runtime-image-root.md).
|
`MEMORY.md` and [ADR-0014](docs/adr/0014-runtime-image-root.md).
|
||||||
- [x] Move the reference mockups from `docs/screens/designs/` into the runtime root (keep `docs/screens/designs/` as a docs-only copy or replace it with the new path).
|
- [x] Move the reference mockups from `docs/screens/designs/` into the runtime root (keep `docs/screens/designs/` as a docs-only copy or replace it with the new path).
|
||||||
- [x] Document one convention for game vs reference vs development images across `assets/textures/`, `assets/images/`, `assets/models/generated/`, `docs/screenshots/`, and `docs/screens/designs/` (in `docs/architecture.md`, ADR-0014).
|
- [x] Document one convention for game vs reference vs development images across `assets/textures/`, `assets/images/`, `assets/models/generated/`, `docs/screenshots/`, and `docs/screens/designs/` (in `docs/project/architecture.md`, ADR-0014).
|
||||||
- [x] Re-run `godot --headless --path . --import` to regenerate `.import` sidecars after any move.
|
- [x] Re-run `godot --headless --path . --import` to regenerate `.import` sidecars after any move.
|
||||||
- [x] Confirm `.gitignore` still excludes development-only outputs (concepts, Blender sources, raw AI fabrics) under the new layout; Blender `.blend` sources are now untracked and ignored.
|
- [x] Confirm `.gitignore` still excludes development-only outputs (concepts, Blender sources, raw AI fabrics) under the new layout; Blender `.blend` sources are now untracked and ignored.
|
||||||
|
|
||||||
### Documentation path updates
|
### Documentation path updates
|
||||||
|
|
||||||
- [x] Update `README.md` paths (screen-designs section, confirmed-assets links, the `assets/images/scenes` resize example).
|
- [x] Update `README.md` paths (screen-designs section, confirmed-assets links, the `assets/images/scenes` resize example).
|
||||||
- [x] Update `docs/architecture.md`, `PLAN.md`, and ADR references: docs/screens/designs/ is now explicitly the reference-only snapshot; runtime art lives in assets/images/ (ADR-0014).
|
- [x] Update `docs/project/architecture.md`, `PLAN.md`, and ADR references: docs/screens/designs/ is now explicitly the reference-only snapshot; runtime art lives in assets/images/ (ADR-0014).
|
||||||
- [x] Update `tools/screen_designs.py` docstrings and mark the old paths in `DONE.md` as historical.
|
- [x] Update `tools/screen_designs.py` docstrings and mark the old paths in `DONE.md` as historical.
|
||||||
|
|
||||||
### Code path updates
|
### Code path updates
|
||||||
@@ -1188,7 +1188,7 @@ architecture's version, runtime-art loader, asset/tooling blocks, Gitea CI/build
|
|||||||
Web deployment and release artifact list were brought up to date. `MEMORY.md` was cleaned of
|
Web deployment and release artifact list were brought up to date. `MEMORY.md` was cleaned of
|
||||||
obsolete uncommitted/active-pass claims and now points at the current follow-ups.
|
obsolete uncommitted/active-pass claims and now points at the current follow-ups.
|
||||||
|
|
||||||
- [x] Re-check `PLAN.md`/`MEMORY.md` against the current build, update `README.md` and `docs/architecture.md`, and compact the historical PLAN sections.
|
- [x] Re-check `PLAN.md`/`MEMORY.md` against the current build, update `README.md` and `docs/project/architecture.md`, and compact the historical PLAN sections.
|
||||||
|
|
||||||
## NPC gear fit (v0.6.1)
|
## NPC gear fit (v0.6.1)
|
||||||
|
|
||||||
@@ -1197,7 +1197,7 @@ Completed 2026-11-01. Eyes, bag and helmet now fit the measured body silhouette;
|
|||||||
The 2026-11-01 detail pass fixed the bodies but not the props worn on them. In the portrait
|
The 2026-11-01 detail pass fixed the bodies but not the props worn on them. In the portrait
|
||||||
capture (`--stages=day,portrait`, see the report in `docs/screens/realism/2026-11-01-npc/`) the
|
capture (`--stages=day,portrait`, see the report in `docs/screens/realism/2026-11-01-npc/`) the
|
||||||
sunglasses span the whole upper face and the shoulder bag cuts through `npc_coat`'s skirt. Blender sources for gear
|
sunglasses span the whole upper face and the shoulder bag cuts through `npc_coat`'s skirt. Blender sources for gear
|
||||||
live in `tools/blender_assets.py` (`_build_gear()`), the contract in `docs/blender-assets.md`
|
live in `tools/blender_assets.py` (`_build_gear()`), the contract in `docs/assets/blender-assets.md`
|
||||||
(gear budget 1500 tris, `GEAR_ATTACH` points in `NpcAvatar`).
|
(gear budget 1500 tris, `GEAR_ATTACH` points in `NpcAvatar`).
|
||||||
|
|
||||||
- [x] Measure the fit in Blender, not by eye: `python3 tools/blender_assets.py fit` prints each
|
- [x] Measure the fit in Blender, not by eye: `python3 tools/blender_assets.py fit` prints each
|
||||||
@@ -1270,7 +1270,7 @@ have no stage in the committed `docs/screenshots/` gallery, only in `capture_rea
|
|||||||
`src/test/capture_screenshots.gd` (`12-joke-shop.png`, `13-studio-arrival.png`) reuse the
|
`src/test/capture_screenshots.gd` (`12-joke-shop.png`, `13-studio-arrival.png`) reuse the
|
||||||
existing `joke_shop_queue` / `studio_arrival` designs. `check_screenshots.sh` is **13 good /
|
existing `joke_shop_queue` / `studio_arrival` designs. `check_screenshots.sh` is **13 good /
|
||||||
0 bad**; the new screenshots are 18.2 / 32.6 MAE against their references.
|
0 bad**; the new screenshots are 18.2 / 32.6 MAE against their references.
|
||||||
- [-] Update `docs/architecture.md` (venue geometry), `README.md` (gallery) and the screenshot
|
- [-] Update `docs/project/architecture.md` (venue geometry), `README.md` (gallery) and the screenshot
|
||||||
table when the stages land.
|
table when the stages land.
|
||||||
|
|
||||||
## Forward+ desktop preset and a volumetric flashlight (v0.7.1)
|
## Forward+ desktop preset and a volumetric flashlight (v0.7.1)
|
||||||
@@ -1296,7 +1296,7 @@ path.
|
|||||||
dirs) and record the diff in `docs/screens/realism/2026-11-01-forward-plus/`: entrance
|
dirs) and record the diff in `docs/screens/realism/2026-11-01-forward-plus/`: entrance
|
||||||
metric gap 1.568 → 1.187, two-shot mean 0.907 → 0.723. Judge scores are blocked by the
|
metric gap 1.568 → 1.187, two-shot mean 0.907 → 0.723. Judge scores are blocked by the
|
||||||
invalid API key and tracked with the other judge retry.
|
invalid API key and tracked with the other judge retry.
|
||||||
- [x] Add the preset to `tools/build_releases.sh` and `docs/RELEASING.md` as an optional
|
- [x] Add the preset to `tools/build_releases.sh` and `docs/process/RELEASING.md` as an optional
|
||||||
"desktop HQ" artifact, and note the runtime requirement (Vulkan driver) in `README.md`.
|
"desktop HQ" artifact, and note the runtime requirement (Vulkan driver) in `README.md`.
|
||||||
`gig-line-desktop-hq-<version>.zip` packages the Linux/Windows binaries, override.cfg and
|
`gig-line-desktop-hq-<version>.zip` packages the Linux/Windows binaries, override.cfg and
|
||||||
README; `publish_release.sh` uploads it when present.
|
README; `publish_release.sh` uploads it when present.
|
||||||
@@ -1327,7 +1327,7 @@ back when a provider rejects a request.
|
|||||||
- [x] Re-run the full screen-design judge and the Forward+ A/B judge with the valid
|
- [x] Re-run the full screen-design judge and the Forward+ A/B judge with the valid
|
||||||
`OPENROUTER_API_KEY`: screen designs are **13/13 match, 0 diff**; the Forward+ report
|
`OPENROUTER_API_KEY`: screen designs are **13/13 match, 0 diff**; the Forward+ report
|
||||||
records the selected model and ~$0.006 spend.
|
records the selected model and ~$0.006 spend.
|
||||||
- [x] Update `docs/asset-tooling.md`, `MEMORY.md`, `README.md` and `CHANGELOG.md`; the
|
- [x] Update `docs/assets/asset-tooling.md`, `MEMORY.md`, `README.md` and `CHANGELOG.md`; the
|
||||||
public catalogue picks the cheapest image+JSON model (`z-ai/glm-5.3-flash` at run time).
|
public catalogue picks the cheapest image+JSON model (`z-ai/glm-5.3-flash` at run time).
|
||||||
|
|
||||||
## Milestone 0.8.0 — First hour and content depth
|
## Milestone 0.8.0 — First hour and content depth
|
||||||
@@ -1343,7 +1343,7 @@ venues, and see enough authored variety that a second shift does not feel like a
|
|||||||
- [x] Write the tutorial beat sheet: menu → movement/look → focus and target cycling → action
|
- [x] Write the tutorial beat sheet: menu → movement/look → focus and target cycling → action
|
||||||
wheel → access inspection → polite direction → formal warning/body camera → radio →
|
wheel → access inspection → polite direction → formal warning/body camera → radio →
|
||||||
shift review. Eight beats and a safe compliant visitor are specified in
|
shift review. Eight beats and a safe compliant visitor are specified in
|
||||||
[`docs/gameplay.md#first-shift-tutorial`](docs/gameplay.md#first-shift-tutorial).
|
[`docs/design/gameplay.md#first-shift-tutorial`](docs/design/gameplay.md#first-shift-tutorial).
|
||||||
- [x] Add a tutorial state machine independent of the normal shift FSM. `Tutorial` in
|
- [x] Add a tutorial state machine independent of the normal shift FSM. `Tutorial` in
|
||||||
`src/game/tutorial.gd` owns the eight beats, accepts only the current beat's action,
|
`src/game/tutorial.gd` owns the eight beats, accepts only the current beat's action,
|
||||||
supports skip/restart and has deterministic headless tests. GameManager/UI wiring starts
|
supports skip/restart and has deterministic headless tests. GameManager/UI wiring starts
|
||||||
@@ -1544,7 +1544,7 @@ and supported by a stable CI/release baseline.
|
|||||||
|
|
||||||
- [x] Existing scenario-content, tutorial and campaign smokes cover the venue/action/review paths;
|
- [x] Existing scenario-content, tutorial and campaign smokes cover the venue/action/review paths;
|
||||||
the 0.9.5 release candidate adds the external first-hour pass.
|
the 0.9.5 release candidate adds the external first-hour pass.
|
||||||
- [x] `docs/getting-started.md` and `docs/release-qa.md#manual-smoke-checklist` list tutorial, campaign/checkpoint,
|
- [x] `docs/process/getting-started.md` and `docs/process/release-qa.md#manual-smoke-checklist` list tutorial, campaign/checkpoint,
|
||||||
session, scenario, audio, crowd, emergency, movement and performance smokes.
|
session, scenario, audio, crowd, emergency, movement and performance smokes.
|
||||||
- [x] Current gallery/judge baselines are green; the 0.9.5 release candidate refreshes the final
|
- [x] Current gallery/judge baselines are green; the 0.9.5 release candidate refreshes the final
|
||||||
gallery after content lock.
|
gallery after content lock.
|
||||||
@@ -1560,7 +1560,7 @@ and supported by a stable CI/release baseline.
|
|||||||
smoke requirement. This explicit matrix is documented.
|
smoke requirement. This explicit matrix is documented.
|
||||||
- [x] No project-wide upgrade in 0.9; the existing version-adaptive light-falloff shim remains
|
- [x] No project-wide upgrade in 0.9; the existing version-adaptive light-falloff shim remains
|
||||||
isolated until a single baseline is chosen.
|
isolated until a single baseline is chosen.
|
||||||
- [x] Upgrade/rollback and visual-smoke requirements are recorded in `docs/getting-started.md`
|
- [x] Upgrade/rollback and visual-smoke requirements are recorded in `docs/process/getting-started.md`
|
||||||
and `MEMORY.md`.
|
and `MEMORY.md`.
|
||||||
- [ ] Exit: one documented runtime version policy, consistent CI/local exports, and no untested
|
- [ ] Exit: one documented runtime version policy, consistent CI/local exports, and no untested
|
||||||
engine-specific rendering hacks.
|
engine-specific rendering hacks.
|
||||||
@@ -1589,7 +1589,7 @@ Goal: streamline the maps, refactor geometry to match the images in `docs/screen
|
|||||||
- [x] Remove unnecessary or hidden geometry to improve performance.
|
- [x] Remove unnecessary or hidden geometry to improve performance.
|
||||||
- [x] Ensure texture and material consistency across the map.
|
- [x] Ensure texture and material consistency across the map.
|
||||||
|
|
||||||
Completed: the Hollywood venue is rebuilt from the real 6840 Hollywood Blvd references (six-column Masonic/El Capitan facade, eight steps, neighbours, Ovation arcade, Walk of Fame, four-lane street). The map-budget test measures 58,884 triangles across 409 meshes; Day/Night menu variants start in `EARLY`/`LATE`; the realism judge gaps are 0.148 (day) and 0.278 (late). See `docs/venues.md#hollywood-boulevard`.
|
Completed: the Hollywood venue is rebuilt from the real 6840 Hollywood Blvd references (six-column Masonic/El Capitan facade, eight steps, neighbours, Ovation arcade, Walk of Fame, four-lane street). The map-budget test measures 58,884 triangles across 409 meshes; Day/Night menu variants start in `EARLY`/`LATE`; the realism judge gaps are 0.148 (day) and 0.278 (late). See `docs/design/venues.md#hollywood-boulevard`.
|
||||||
|
|
||||||
### Map 2 — Joke Shop
|
### Map 2 — Joke Shop
|
||||||
|
|
||||||
@@ -1601,7 +1601,7 @@ Completed: the Hollywood venue is rebuilt from the real 6840 Hollywood Blvd refe
|
|||||||
- [x] Remove unnecessary or hidden geometry to improve performance.
|
- [x] Remove unnecessary or hidden geometry to improve performance.
|
||||||
- [x] Ensure texture and material consistency across the map.
|
- [x] Ensure texture and material consistency across the map.
|
||||||
|
|
||||||
Completed 2026-11-02: the Joke Shop is rebuilt from the real Comedy Store block at 8433 Sunset Blvd (27 m black hall, signature canopy, circular blade sign, red curtains, west entrance, low-rise neighbours, dry hillside and opposite frontage). The map-budget test measures 22,680 triangles across 454 meshes. The day/late captures and real-site notes are in `docs/venues.md#the-joke-shop` and `docs/screens/concepts/joke_shop/`; the final gallery passed 13 good / 0 bad and the screen-design judge (13/13 match, 0 diff), with a 0.454 realism gap on the photoreal night reference.
|
Completed 2026-11-02: the Joke Shop is rebuilt from the real Comedy Store block at 8433 Sunset Blvd (27 m black hall, signature canopy, circular blade sign, red curtains, west entrance, low-rise neighbours, dry hillside and opposite frontage). The map-budget test measures 22,680 triangles across 454 meshes. The day/late captures and real-site notes are in `docs/design/venues.md#the-joke-shop` and `docs/screens/concepts/joke_shop/`; the final gallery passed 13 good / 0 bad and the screen-design judge (13/13 match, 0 diff), with a 0.454 realism gap on the photoreal night reference.
|
||||||
|
|
||||||
### Scenery Change (Day/Night) for Hollywood Boulevard
|
### Scenery Change (Day/Night) for Hollywood Boulevard
|
||||||
|
|
||||||
@@ -1646,7 +1646,7 @@ redesign.
|
|||||||
|
|
||||||
- [x] Do not run the release build, bump a release version or tag until the map exit criteria and
|
- [x] Do not run the release build, bump a release version or tag until the map exit criteria and
|
||||||
this NPC revisit are both signed off.
|
this NPC revisit are both signed off.
|
||||||
- [x] Record the sign-off in `docs/development-status.md` and `MEMORY.md`, then hand off to the
|
- [x] Record the sign-off in `docs/project/development-status.md` and `MEMORY.md`, then hand off to the
|
||||||
postponed integration/build milestone.
|
postponed integration/build milestone.
|
||||||
|
|
||||||
**Exit:** the final maps and lighting still present the NPCs clearly; no untriaged NPC regression
|
**Exit:** the final maps and lighting still present the NPCs clearly; no untriaged NPC regression
|
||||||
@@ -1663,20 +1663,20 @@ screen-design judge before any model/texture changes. No gameplay rules change.
|
|||||||
|
|
||||||
- [x] Inventory every screen/panel: start menu, venue menu, tutorial, HUD, pause,
|
- [x] Inventory every screen/panel: start menu, venue menu, tutorial, HUD, pause,
|
||||||
settings, Help, inspection, wand, radio/emergency, wheel, shift review,
|
settings, Help, inspection, wand, radio/emergency, wheel, shift review,
|
||||||
timeline and campaign/continue screens. Recorded in `docs/ui-copy.md`.
|
timeline and campaign/continue screens. Recorded in `docs/design/ui-copy.md`.
|
||||||
- [x] Record the canonical terms for admit/refuse, warning/blocking,
|
- [x] Record the canonical terms for admit/refuse, warning/blocking,
|
||||||
assistance/emergency, body camera, shift review and campaign; the current
|
assistance/emergency, body camera, shift review and campaign; the current
|
||||||
inspection/wand/radio/review labels use them (see `docs/ui-copy.md`).
|
inspection/wand/radio/review labels use them (see `docs/design/ui-copy.md`).
|
||||||
- [x] Audit all button labels for verb-first wording, capitalization, ordering,
|
- [x] Audit all button labels for verb-first wording, capitalization, ordering,
|
||||||
destructive-action confirmation and consistent confirm/cancel placement;
|
destructive-action confirmation and consistent confirm/cancel placement;
|
||||||
recorded in `docs/ui-copy.md` and fixed Quit/Apply wording.
|
recorded in `docs/design/ui-copy.md` and fixed Quit/Apply wording.
|
||||||
- [x] List every hardcoded player-facing string and route it through
|
- [x] List every hardcoded player-facing string and route it through
|
||||||
`content/strings.en.json`; remaining UI literals are numeric/debug-only or
|
`content/strings.en.json`; remaining UI literals are numeric/debug-only or
|
||||||
dynamic data. Placeholder validation covers the new keys.
|
dynamic data. Placeholder validation covers the new keys.
|
||||||
- [x] Review NPC/door-staff/radio/tutorial/help/review/campaign dialogue for
|
- [x] Review NPC/door-staff/radio/tutorial/help/review/campaign dialogue for
|
||||||
repetition, ambiguity, tone and localization length. (Reason contexts,
|
repetition, ambiguity, tone and localization length. (Reason contexts,
|
||||||
door-staff lines, radio/tutorial/help copy and length findings recorded in
|
door-staff lines, radio/tutorial/help copy and length findings recorded in
|
||||||
`docs/ui-copy.md`; longest dialogue line is 56 characters.)
|
`docs/design/ui-copy.md`; longest dialogue line is 56 characters.)
|
||||||
|
|
||||||
### Button and panel behavior
|
### Button and panel behavior
|
||||||
|
|
||||||
@@ -1684,15 +1684,15 @@ screen-design judge before any model/texture changes. No gameplay rules change.
|
|||||||
tutorial skip, venue continue, settings apply/cancel/reset, judge/review,
|
tutorial skip, venue continue, settings apply/cancel/reset, judge/review,
|
||||||
radio send/emergency hold and Help close. (Shared `UiStyles` states applied;
|
radio send/emergency hold and Help close. (Shared `UiStyles` states applied;
|
||||||
timeline boundary disabling and the keyboard-only F1 skip are documented in
|
timeline boundary disabling and the keyboard-only F1 skip are documented in
|
||||||
`docs/ui-copy.md`.)
|
`docs/design/ui-copy.md`.)
|
||||||
- [x] Verify keyboard-only and gamepad-only navigation: focus order, wrapping,
|
- [x] Verify keyboard-only and gamepad-only navigation: focus order, wrapping,
|
||||||
default focus, confirm/cancel behavior and no focus traps. (Focus rings,
|
default focus, confirm/cancel behavior and no focus traps. (Focus rings,
|
||||||
gamepad A/B UI bindings, default focus and per-modal cancel behavior are
|
gamepad A/B UI bindings, default focus and per-modal cancel behavior are
|
||||||
recorded in `docs/ui-copy.md`.)
|
recorded in `docs/design/ui-copy.md`.)
|
||||||
- [x] Verify every modal closes with Esc/right-click where documented, recaptures
|
- [x] Verify every modal closes with Esc/right-click where documented, recaptures
|
||||||
the mouse, and does not leave the guard frozen or the menu visible. (Single
|
the mouse, and does not leave the guard frozen or the menu visible. (Single
|
||||||
top-modal close path, menu/settings return handling and pointer recapture are
|
top-modal close path, menu/settings return handling and pointer recapture are
|
||||||
recorded in `docs/ui-copy.md`; session smoke covers menu Settings, Help
|
recorded in `docs/design/ui-copy.md`; session smoke covers menu Settings, Help
|
||||||
right-click and pause Settings.)
|
right-click and pause Settings.)
|
||||||
- [x] Test buttons at minimum/maximum HUD font scale and with 1.5–2× longer
|
- [x] Test buttons at minimum/maximum HUD font scale and with 1.5–2× longer
|
||||||
strings; fix clipping, overflow and overlapping layouts. (Target chip now
|
strings; fix clipping, overflow and overlapping layouts. (Target chip now
|
||||||
@@ -1720,9 +1720,9 @@ screen-design judge before any model/texture changes. No gameplay rules change.
|
|||||||
- [x] Ran `tools/check_screenshots.sh` and `screen_designs.py compare`: 21 good,
|
- [x] Ran `tools/check_screenshots.sh` and `screen_designs.py compare`: 21 good,
|
||||||
0 bad.
|
0 bad.
|
||||||
- [x] Ran the judge with automatic model selection: 21/21 match, 0 review, 0 diff.
|
- [x] Ran the judge with automatic model selection: 21/21 match, 0 review, 0 diff.
|
||||||
- [x] Recorded the judge model and result in `docs/ui-copy.md#screen-design-judge-report`; the
|
- [x] Recorded the judge model and result in `docs/design/ui-copy.md#screen-design-judge-report`; the
|
||||||
generated captures remain local/gitignored.
|
generated captures remain local/gitignored.
|
||||||
- [x] Add a short UI copy/button checklist to `docs/release-qa.md#manual-smoke-checklist`.
|
- [x] Add a short UI copy/button checklist to `docs/process/release-qa.md#manual-smoke-checklist`.
|
||||||
- [x] Exit: all screens have consistent terminology and button behavior, long
|
- [x] Exit: all screens have consistent terminology and button behavior, long
|
||||||
strings/scale pass, and the Python compare/judge gate has no unexplained
|
strings/scale pass, and the Python compare/judge gate has no unexplained
|
||||||
diff.
|
diff.
|
||||||
@@ -1742,10 +1742,10 @@ fallback behavior.
|
|||||||
produces 48 frames; `sheet_npc_baseline.jpg` is committed.)
|
produces 48 frames; `sheet_npc_baseline.jpg` is committed.)
|
||||||
- [x] Define acceptance criteria for proportions, face readability, hair, hands, shoes, clothing
|
- [x] Define acceptance criteria for proportions, face readability, hair, hands, shoes, clothing
|
||||||
silhouette, gear fit and animation at the gameplay camera height (1.7 m). (Eight criteria
|
silhouette, gear fit and animation at the gameplay camera height (1.7 m). (Eight criteria
|
||||||
in `docs/npc-visual-review.md`; the current 8,000-triangle/8,000-vertex library contract is explicit; the `npc_base` fallback remains 6,000/4,000.)
|
in the review evidence (since retired with the 0.9.9 roster pages); the current 8,000-triangle/8,000-vertex library contract is explicit; the `npc_base` fallback remains 6,000/4,000.)
|
||||||
- [x] Record the camera/lighting/background used for comparison so model changes can be judged
|
- [x] Record the camera/lighting/background used for comparison so model changes can be judged
|
||||||
consistently; keep the existing portrait capture path deterministic. (Neutral studio, fixed
|
consistently; keep the existing portrait capture path deterministic. (Neutral studio, fixed
|
||||||
orbit cameras, no HUD/crowd/animation; commands recorded in `docs/npc-visual-review.md`.)
|
orbit cameras, no HUD/crowd/animation; commands recorded in the retired review evidence.)
|
||||||
- [x] Identify the highest-impact gaps from the current portraits (e.g. face depth, hair mass,
|
- [x] Identify the highest-impact gaps from the current portraits (e.g. face depth, hair mass,
|
||||||
neck/shoulder transition, hand/foot shape, coat/dress hem) and rank them by player visibility.
|
neck/shoulder transition, hand/foot shape, coat/dress hem) and rank them by player visibility.
|
||||||
(P1: tourist duplicate bag, face depth, backpack straps; P2: hands/grips, clothing tiling,
|
(P1: tourist duplicate bag, face depth, backpack straps; P2: hands/grips, clothing tiling,
|
||||||
@@ -1755,7 +1755,7 @@ fallback behavior.
|
|||||||
the side-by-side after sheet without overwriting it.)
|
the side-by-side after sheet without overwriting it.)
|
||||||
|
|
||||||
Completed 2026-11-02: 48-frame neutral studio baseline, eight criteria, current fit and
|
Completed 2026-11-02: 48-frame neutral studio baseline, eight criteria, current fit and
|
||||||
triangle/vertex measurements, and ranked P1/P2 gaps are in `docs/npc-visual-review.md`. The
|
triangle/vertex measurements, and ranked P1/P2 gaps are in `docs/assets/3d-model-review.md`. The
|
||||||
baseline itself changed no character models; the first P1 gear fixes are recorded under Gear
|
baseline itself changed no character models; the first P1 gear fixes are recorded under Gear
|
||||||
and equipment fit.
|
and equipment fit.
|
||||||
|
|
||||||
@@ -1768,7 +1768,7 @@ and equipment fit.
|
|||||||
|
|
||||||
- [x] Audit all variants against a shared human proportion guide (head height, shoulder width,
|
- [x] Audit all variants against a shared human proportion guide (head height, shoulder width,
|
||||||
torso length, hip width, limb length, foot length) and correct the worst outliers.
|
torso length, hip width, limb length, foot length) and correct the worst outliers.
|
||||||
(`tools/npc_proportions.py` + `docs/npc-visual-review.md#proportion-audit`: all eight pass; no skeleton or
|
(`tools/npc_proportions.py` + `docs/assets/3d-model-review.md#character-measurements`: all eight pass; no skeleton or
|
||||||
mesh rescue was needed. Head and broad-build silhouettes are nearest their upper bounds.)
|
mesh rescue was needed. Head and broad-build silhouettes are nearest their upper bounds.)
|
||||||
- [x] Improve the neck and shoulder transition so the silhouette reads as one body rather than a
|
- [x] Improve the neck and shoulder transition so the silhouette reads as one body rather than a
|
||||||
thin post on a hanger. (Fuller neck base/top, lower shoulder root, degenerate-face cleanup;
|
thin post on a hanger. (Fuller neck base/top, lower shoulder root, degenerate-face cleanup;
|
||||||
@@ -1857,7 +1857,7 @@ and equipment fit.
|
|||||||
`blender_assets.py audit`, `fit`, character imports and the full Godot test suite.
|
`blender_assets.py audit`, `fit`, character imports and the full Godot test suite.
|
||||||
- [x] Recapture the portrait, character gallery and crowd-distance shots; compare old/new and run
|
- [x] Recapture the portrait, character gallery and crowd-distance shots; compare old/new and run
|
||||||
the Python screen-design judge.
|
the Python screen-design judge.
|
||||||
- [x] Update `docs/blender-assets.md`, architecture/status, `MEMORY.md` and the changelog with the
|
- [x] Update `docs/assets/blender-assets.md`, architecture/status, `MEMORY.md` and the changelog with the
|
||||||
new budgets, limitations and rebuild commands.
|
new budgets, limitations and rebuild commands.
|
||||||
- [x] Exit: all eight variants pass the portrait/readability criteria, gear and hems no longer
|
- [x] Exit: all eight variants pass the portrait/readability criteria, gear and hems no longer
|
||||||
clip in normal play, the 24-NPC budget remains green, and the visual judge has no unexplained
|
clip in normal play, the 24-NPC budget remains green, and the visual judge has no unexplained
|
||||||
@@ -2007,7 +2007,7 @@ target paths and leave a clean release-candidate handoff.
|
|||||||
final patch-level results and any remaining gaps. (README/PLAN/architecture
|
final patch-level results and any remaining gaps. (README/PLAN/architecture
|
||||||
now point at 0.9.6; the changelog and development status record the
|
now point at 0.9.6; the changelog and development status record the
|
||||||
integration build, performance numbers, judge results and the clean-worktree
|
integration build, performance numbers, judge results and the clean-worktree
|
||||||
export rule; `docs/RELEASING.md` documents the ignored-folder trap.)
|
export rule; `docs/process/RELEASING.md` documents the ignored-folder trap.)
|
||||||
- [x] Tag/version or otherwise freeze `0.9.6` as the integration checkpoint before
|
- [x] Tag/version or otherwise freeze `0.9.6` as the integration checkpoint before
|
||||||
the `0.10.0` release candidate. (Tag `v0.9.6` on `4bb2896`; Gitea run 1296
|
the `0.10.0` release candidate. (Tag `v0.9.6` on `4bb2896`; Gitea run 1296
|
||||||
passed checks and the full build and published seven assets.)
|
passed checks and the full build and published seven assets.)
|
||||||
@@ -2050,7 +2050,7 @@ must inherit the reviewed face/hand/gear baseline instead of multiplying whateve
|
|||||||
the existing Blender contract. (Measured Quaternius CC0, Kenney CC0, Khronos
|
the existing Blender contract. (Measured Quaternius CC0, Kenney CC0, Khronos
|
||||||
CesiumMan/RiggedFigure CC-BY and the MakeHuman CC0 base mesh; none is a drop-in.
|
CesiumMan/RiggedFigure CC-BY and the MakeHuman CC0 base mesh; none is a drop-in.
|
||||||
Results, local preview sheet and SHA-256 provenance are in
|
Results, local preview sheet and SHA-256 provenance are in
|
||||||
`docs/npc-model-sourcing.md`.)
|
`docs/assets/npc-model-sourcing.md`.)
|
||||||
- [x] Review the sourcing research with the project owner and choose Option A (procedural),
|
- [x] Review the sourcing research with the project owner and choose Option A (procedural),
|
||||||
Option B (Quaternius CC0 intake) or Option C (MakeHuman/MPFB body pipeline); record the
|
Option B (Quaternius CC0 intake) or Option C (MakeHuman/MPFB body pipeline); record the
|
||||||
decision in an ADR and in `MEMORY.md`. (2026-11-03: extend the procedural generator as the
|
decision in an ADR and in `MEMORY.md`. (2026-11-03: extend the procedural generator as the
|
||||||
@@ -2127,7 +2127,7 @@ must inherit the reviewed face/hand/gear baseline instead of multiplying whateve
|
|||||||
- [x] Gates with the expanded library: 24-NPC budget smoke 152,464 tris / 168 meshes / 6.94 ms
|
- [x] Gates with the expanded library: 24-NPC budget smoke 152,464 tris / 168 meshes / 6.94 ms
|
||||||
(under 50 ms), portrait baseline 12 variants × 6 views, `fit` clean, Godot 277/277, Python
|
(under 50 ms), portrait baseline 12 variants × 6 views, `fit` clean, Godot 277/277, Python
|
||||||
160/160. No release build is created for this unversioned track.
|
160/160. No release build is created for this unversioned track.
|
||||||
- [x] Docs: `docs/development-status.md`, `docs/3d-model-review.md` and the baseline sheet updated;
|
- [x] Docs: `docs/project/development-status.md`, `docs/assets/3d-model-review.md` and the baseline sheet updated;
|
||||||
`CREDITS.md` needs no change (the crowd variants are procedural, no new source). Accepted
|
`CREDITS.md` needs no change (the crowd variants are procedural, no new source). Accepted
|
||||||
visual limits: the crowd accessories (umbrella canopy, cup, sunglasses, beard) read at
|
visual limits: the crowd accessories (umbrella canopy, cup, sunglasses, beard) read at
|
||||||
full-body distance but not in the head-only portrait framing.
|
full-body distance but not in the head-only portrait framing.
|
||||||
@@ -2143,3 +2143,154 @@ must inherit the reviewed face/hand/gear baseline instead of multiplying whateve
|
|||||||
project-owned clothing; keep out of CI/build.)
|
project-owned clothing; keep out of CI/build.)
|
||||||
- [x] Body-shape diversity decision (2026-11-04, owner): **yes** — use MakeHuman for the next
|
- [x] Body-shape diversity decision (2026-11-04, owner): **yes** — use MakeHuman for the next
|
||||||
character pass. Promoted to the **MakeHuman character pipeline** track.
|
character pass. Promoted to the **MakeHuman character pipeline** track.
|
||||||
|
|
||||||
|
## NPC pose harness (v0.9.8)
|
||||||
|
|
||||||
|
Completed 2026-11-04. The pose harness bug that made every staged capture save a rest frame
|
||||||
|
was found and fixed; it unblocked the weights/pose evidence and the seated/walking deformation
|
||||||
|
fixes. User-facing changes are recorded under 0.9.7 and 0.9.8 in `CHANGELOG.md`.
|
||||||
|
|
||||||
|
Goal: `src/test/capture_npc_pose.gd` reports a pose but saves rest frames; the root cause is
|
||||||
|
narrowed to the skinned mesh ignoring its `Rig` parent transform. Fixing it unblocks the
|
||||||
|
weights/pose column of the 3D review; the evidence now feeds the Quaternius base bake.
|
||||||
|
|
||||||
|
*Skill route: `rigging`; evidence in `docs/assets/3d-model-review.md` §"Pose evidence is blocked".*
|
||||||
|
|
||||||
|
- [x] Root cause found (2026-11-04): the harness never disabled the avatar's `_physics_process`,
|
||||||
|
so `_advance_fsm` + `_move_toward_target` ran every tick and reset `arrived`/velocity, which
|
||||||
|
made `theater_pose()` return "idle" and reverted the pose to rest. (The earlier "moving the
|
||||||
|
`Rig` child does not render" probe was a red herring: it set `rig.position.y` inside `_shoot()`
|
||||||
|
in the same frame as `root.get_texture().get_image()`, so it never got a rendered frame.)
|
||||||
|
- [x] Harness rebuilt: `capture_npc_pose.gd` now calls `set_physics_process(false)`/
|
||||||
|
`set_process(false)` after staging the avatar; the pose survives because only the direct
|
||||||
|
`_animate()` ticks drive it. Verified: sit vs idle diff 5.63, walk vs idle diff 2.29, and the
|
||||||
|
vision judge confirms the seated frame reads as crouched.
|
||||||
|
- [x] Captured all poses for all 12 variants (idle / walk_contact / walk_pass / sit × full +
|
||||||
|
shoulder views = 96 frames) and built `sheet_pose.jpg`/`sheet_shoulder.jpg` under `tmp/`.
|
||||||
|
(No separate "wave" theater pose exists; the escalation raise-hand gesture is not a distinct
|
||||||
|
capture in this harness.)
|
||||||
|
|
||||||
|
## Milestone 0.9.7 — Character development (patch)
|
||||||
|
|
||||||
|
Completed 2026-11-04 and published as v0.9.7. The detailed character-development record already
|
||||||
|
lives under "Character development" above; this milestone checklist is kept verbatim for the
|
||||||
|
release record.
|
||||||
|
|
||||||
|
Goal: release the finished procedural character development — the realistic face on all eight
|
||||||
|
variants, the four crowd-variety characters and the per-role pools — as a **patch** on top of
|
||||||
|
0.9.6. This keeps the 3D model and map improvements out of the patch; they land together in the
|
||||||
|
0.10.0 minor.
|
||||||
|
|
||||||
|
- [x] Rig pose harness fixed and the weights/pose evidence captured (see the top track).
|
||||||
|
- [x] Character work done: 12-character library, realistic face, crowd variants, per-role pools,
|
||||||
|
24-NPC budget 6.94 ms (152,464 tris / 168 meshes).
|
||||||
|
- [x] QA + local build for 0.9.7: Godot 277/277, Python 161/161, audit 49 OK, fit/proportions
|
||||||
|
12/12, release smoke matrix green, gallery 21/0, clean worktree build (Linux 172 MB,
|
||||||
|
Windows 206 MB, macOS 159 MB, Web 111 MB, HQ 266 MB), checksums verified, Linux binary
|
||||||
|
launches headless. Tagged `v0.9.7` (CI build/publish follows).
|
||||||
|
|
||||||
|
**Exit:** met — 0.9.7 ships the 12-character library (face realism + crowd variety) with the pose
|
||||||
|
harness fixed; the runtime contract is unchanged. The Quaternius NPC base and the map rebuild are
|
||||||
|
not in this patch (they target 0.10.0).
|
||||||
|
|
||||||
|
## Milestone 0.9.9 — Quaternius NPC base swap (patch)
|
||||||
|
|
||||||
|
Goal: make one Quaternius-derived NPC render and animate correctly in Godot and ship it as the
|
||||||
|
pilot base, with the procedural library still selectable as the fallback. This is the first
|
||||||
|
versioned character milestone; it contains the rig correction that has been blocking the
|
||||||
|
ADR-0018 rollout.
|
||||||
|
|
||||||
|
**Why this is a patch:** it changes character presentation and animation quality but adds no new
|
||||||
|
player-facing system. The 0.10.0 minor is reserved for the release gates (see below), so a
|
||||||
|
blocked rig can no longer block the whole release.
|
||||||
|
|
||||||
|
**Completed 2026-11-06.** Shipped as `v0.9.9` (tagged, local release build with checksums)
|
||||||
|
and accepted by the owner after the follow-up fixes. Durable evidence: `docs/assets/3d-model-review.md`,
|
||||||
|
`docs/assets/blender-assets.md`, `docs/adr/0018-quaternius-stage2-runtime-rig.md`.
|
||||||
|
|
||||||
|
### Rig and export correction
|
||||||
|
|
||||||
|
- [x] Reproduce and record the failure: the `armature_apply` + `export_apply=True` bake wrote
|
||||||
|
wrong inverse bind matrices (Godot rendered A-pose while the rest was arm-down). Recorded
|
||||||
|
in `MEMORY.md`; `bake_armdown_clean.py` was the failing recipe.
|
||||||
|
- [x] Fix the arm-down bake so the exported skin matches the rest. `tmp/npc-research/bake_armdown_v2.py`
|
||||||
|
(pose-rotate → apply modifier → reset pose → edit-mode rotate arms → re-add modifier →
|
||||||
|
export `export_apply=False`) now yields a correct arm-down base: Blender deformed x ±0.221
|
||||||
|
and the rest bone tail points down. Still local (`tmp/`), not shipped.
|
||||||
|
- [x] Re-derive the pose composition for a non-180° rest. Superseded by the rig-agnostic
|
||||||
|
`_swing_bone()` below: the rest-relative `set_bone_pose_rotation` form was never exact,
|
||||||
|
because `get_bone_rest()` is parent-relative and already carries the importer's axis
|
||||||
|
conversion. Kept in `MEMORY.md` as a rejected approach.
|
||||||
|
- [x] Fix the skinning/rest bake end to end (commit `cd285b3`):
|
||||||
|
(1) the canonical base is **join-only** (`tmp/npc-research/build_base_minimal.py`: no
|
||||||
|
`remove_doubles` weld, no scale/ground transform, keep the Armature modifiers) — the weld
|
||||||
|
and the transform corrupted the Quaternius weights;
|
||||||
|
(2) the arm-down bake (`tmp/npc-research/bake_armdown_v5.py` — pose, read pose matrices,
|
||||||
|
apply modifier, **reset pose to identity**, set rest matrices, re-add modifier) bakes the
|
||||||
|
rest correctly (DEFORMED x −0.228/0.228, Godot bind pose arm-down);
|
||||||
|
(3) `NpcAvatar._swing_bone()` now writes the **global** bone pose from
|
||||||
|
`get_bone_global_rest()`, so one formula drives both the 62-joint Quaternius rig and the
|
||||||
|
13-core fallback (measured: posed bone axis matches the proxy pivot at dot 1.000 on the
|
||||||
|
Quaternius, and the procedural rigs are unchanged);
|
||||||
|
(4) `RIG_BONES` + `NpcAvatar.bone_name()` hold the only side mapping (the Quaternius labels
|
||||||
|
`L`/`R` opposite the project), and the hand proxy is `global_wrist − global_elbow`.
|
||||||
|
Verified in Godot: idle/sit/walk captures on npc_casual plus the unchanged procedural rigs.
|
||||||
|
- [x] Add regression tests: `test_shipped_rig_resolves_the_animation_joints` covers the joint map,
|
||||||
|
the baked arm-down rest, the down-pointing arm axis and the proxy side mapping; the Blender
|
||||||
|
audit/`inspect` and `npc_proportions` now understand both rigs. Godot 278/278, Python
|
||||||
|
167/167.
|
||||||
|
- [x] Give the Quaternius base the five tint slots: `build_base_minimal.py` renames the upstream
|
||||||
|
materials to `skin`/`cloth`/`pants`/`hair`/`accessory` and keeps `Eye`/`Eyebrows` as
|
||||||
|
fixed-colour detail. The source UV map is degenerate (every loop at 0,0), so the build now
|
||||||
|
Smart-UV-unwraps and repacks the layout — texel density went from an unmeasurable 0 to
|
||||||
|
73–74 px/m on the 256² maps and the 256² AO bake works again.
|
||||||
|
- [x] Idle and Walk verified on the 62-joint rig through the pose code, not the clips: the 24
|
||||||
|
upstream clips stay authoring reference only, because `_animate()` + `_sync_skeleton()`
|
||||||
|
already drive sitting, hand-raising and head turns, and playing clips would replace that
|
||||||
|
state machine rather than supplement it. Recorded in ADR-0018 and `MEMORY.md`.
|
||||||
|
- [x] Poses the clips do not cover are driven by the same proxy pivots (`_legs`, `_knees`,
|
||||||
|
`_arms`, `_elbows`, `_head`), which is why no clip retarget was needed.
|
||||||
|
- [x] Fallback stays tested: `_build_body()` still builds the 13-core rig, and
|
||||||
|
`test_forced_fallback_still_builds_the_procedural_rig` now asserts the hip swings and a hand
|
||||||
|
pivot exists on that path. No MPFB or Stage-1 proportion work reopened.
|
||||||
|
- [x] Backpack straps re-fitted for the Quaternius torso (`fb3e75a`) and the back attach raised to
|
||||||
|
shoulder-blade height; the camera kept its wrist strap.
|
||||||
|
|
||||||
|
### Silhouette and face gate (owner)
|
||||||
|
|
||||||
|
- [x] Re-run the silhouette gate at gameplay distance and in portrait against the current
|
||||||
|
`npc_casual`, front / three-quarter / profile. ADR-0018 removed the proportion warp, so
|
||||||
|
source proportions are accepted by definition (head 13.4 % of height, measured by
|
||||||
|
`npc_proportions`).
|
||||||
|
- [x] Owner visual signoff obtained (2026-11-06) on the roster, the faces, the head gear and the
|
||||||
|
hand/back gear. The review page and its sheets were retired after acceptance; the measurements
|
||||||
|
live on in `docs/assets/3d-model-review.md` and `docs/assets/blender-assets.md`.
|
||||||
|
- [x] Face-fidelity comparison was made and the full swap chosen; the comparison sheets were
|
||||||
|
retired with the review pages, and the decision is recorded in the follow-up section of
|
||||||
|
[`docs/adr/0018-quaternius-stage2-runtime-rig.md`](docs/adr/0018-quaternius-stage2-runtime-rig.md).
|
||||||
|
- [x] **Owner decision:** option (a) full swap (2026-11-05). Applied: all twelve characters are
|
||||||
|
baked from the three Quaternius sources inside 24,000 tris / 24,000 glTF vertices
|
||||||
|
(`a6ccd86`), and the gate was re-run.
|
||||||
|
- [x] Record the decision and its consequence in `MEMORY.md`,
|
||||||
|
`docs/assets/npc-model-sourcing.md#shipped-roster-099-owner-chose-the-full-swap` and the
|
||||||
|
follow-up decision section of
|
||||||
|
[`docs/adr/0018-quaternius-stage2-runtime-rig.md`](docs/adr/0018-quaternius-stage2-runtime-rig.md).
|
||||||
|
- [x] Owner visual signoff on the shipped roster (2026-11-06): accepted.
|
||||||
|
|
||||||
|
### Pilot rollout
|
||||||
|
|
||||||
|
- [x] Map the five tint slots onto the Quaternius materials and unwrap the degenerate source
|
||||||
|
UV map; bake the 256² AO and check texel density (73–74 px/m).
|
||||||
|
- [x] Re-fit every gear attach point against the Quaternius skeleton and test each piece on the
|
||||||
|
character (the 0.9.10 *Prop and gear fit pass* below carries the measurements).
|
||||||
|
- [x] Wired the approved base into all twelve roles, with the procedural library as the instant
|
||||||
|
fallback; no runtime download or optional dependency.
|
||||||
|
- [x] Ran `inspect` (clean), `audit` (12/12), `fit` (OK), `npc_proportions` (measured), the 24-NPC
|
||||||
|
budget smoke (175,264 tris, 0.87 ms) and the capture gates before/after the fixes.
|
||||||
|
- [x] Released `0.9.9`: `config/version` 0.9.9, `CHANGELOG.md` entry, local build with checksums,
|
||||||
|
commit, tag `v0.9.9` and push. Owner accepted the roster on 2026-11-06.
|
||||||
|
|
||||||
|
**Exit:** one committed Quaternius GLB renders arm-down with correct skinning, plays Idle and
|
||||||
|
Walk on the 62-joint rig, poses correctly under the new composition, passes the owner face and
|
||||||
|
silhouette gate, fits the 18 gear pieces, stays inside budget, and ships as `0.9.9` with the
|
||||||
|
procedural library still available as a fallback.
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Session memory for durable decisions, gotchas, and commands. Implementation history lives in
|
Session memory for durable decisions, gotchas, and commands. Implementation history lives in
|
||||||
`DONE.md`, user-facing changes in `CHANGELOG.md`, the live task list in `TODO.md`, and the
|
`DONE.md`, user-facing changes in `CHANGELOG.md`, the live task list in `TODO.md`, and the
|
||||||
canonical implemented-features list in `docs/development-status.md`.
|
canonical implemented-features list in `docs/project/development-status.md`.
|
||||||
|
|
||||||
## Decisions
|
## Decisions
|
||||||
|
|
||||||
@@ -10,6 +10,11 @@ canonical implemented-features list in `docs/development-status.md`.
|
|||||||
the licence gate. Downloads live in `tmp/research/` (gitignored): DDG image search, street-view
|
the licence gate. Downloads live in `tmp/research/` (gitignored): DDG image search, street-view
|
||||||
frames, neighbouring buildings — never committed, never shipped. Promotion into
|
frames, neighbouring buildings — never committed, never shipped. Promotion into
|
||||||
`docs/screens/refs/` always passes the sidecar licence + privacy gate and `CREDITS.md`.
|
`docs/screens/refs/` always passes the sidecar licence + privacy gate and `CREDITS.md`.
|
||||||
|
- **AI-assisted asset review loop (2026-11-04):** head/face shape decisions use a concept +
|
||||||
|
judge loop — generate a target concept (`generate_textures.generate_image`, Seedream) and use
|
||||||
|
`tools/describe_image.py` as the vision judge, iterating until the judge's specific fixes
|
||||||
|
converge. Durable evidence: `docs/assets/3d-model-review.md` §AI-driven head rework; the
|
||||||
|
retired head-review page was removed in the 2026-11-06 docs restructure.
|
||||||
- **Project agent skills (2026-11-03):** two tracked skills live in `.agents/skills/`:
|
- **Project agent skills (2026-11-03):** two tracked skills live in `.agents/skills/`:
|
||||||
`gig-line-blender-asset-contract` and `gig-line-release-qa`. They are guidance only,
|
`gig-line-blender-asset-contract` and `gig-line-release-qa`. They are guidance only,
|
||||||
add no runtime dependency and are referenced from `tools/README.md`. The third-party
|
add no runtime dependency and are referenced from `tools/README.md`. The third-party
|
||||||
@@ -19,7 +24,7 @@ canonical implemented-features list in `docs/development-status.md`.
|
|||||||
restaged for a late-night arrival. `VENUE_SPECS["tv_studio"]` is a 30.0 m variant of the 29.6 m
|
restaged for a late-night arrival. `VENUE_SPECS["tv_studio"]` is a 30.0 m variant of the 29.6 m
|
||||||
Hollywood facade. One reference board serves both venues; never create a separate TV Studio board.
|
Hollywood facade. One reference board serves both venues; never create a separate TV Studio board.
|
||||||
- **Jimmy Kimmel Live = starting point:** the Hollywood first shift and the TV Studio arrival both
|
- **Jimmy Kimmel Live = starting point:** the Hollywood first shift and the TV Studio arrival both
|
||||||
begin at the El Capitan block. Stated in `docs/venues.md#hollywood-boulevard` and `docs/gameplay.md`.
|
begin at the El Capitan block. Stated in `docs/design/venues.md#hollywood-boulevard` and `docs/design/gameplay.md`.
|
||||||
- **Street-view limitation:** Google Street View panoramas need a Google API key or manual browser
|
- **Street-view limitation:** Google Street View panoramas need a Google API key or manual browser
|
||||||
capture, so the local reference sets use DDG street-level photos instead.
|
capture, so the local reference sets use DDG street-level photos instead.
|
||||||
- **Image-recitation filter:** Gemini image models reject well-known branded facades (Comedy Store
|
- **Image-recitation filter:** Gemini image models reject well-known branded facades (Comedy Store
|
||||||
@@ -45,28 +50,48 @@ canonical implemented-features list in `docs/development-status.md`.
|
|||||||
(94 skills + shared `references/`), gitignored, kept out of Godot's scanner by
|
(94 skills + shared `references/`), gitignored, kept out of Godot's scanner by
|
||||||
`.agents/.gdignore`. Keep the pack flat when updating (`cp -a <pack>/.claude/skills/. ...`).
|
`.agents/.gdignore`. Keep the pack flat when updating (`cp -a <pack>/.claude/skills/. ...`).
|
||||||
Pi gates project `.agents/skills` behind project trust.
|
Pi gates project `.agents/skills` behind project trust.
|
||||||
- **NPC model sourcing (ADR-0015):** CC0 acceptable for shipped assets; CC-BY only with
|
|
||||||
attribution in `CREDITS.md`; no service assets with redistribution restrictions. The procedural
|
|
||||||
generator is the primary path. Quaternius and MakeHuman were evaluated as references only, not
|
|
||||||
shipped bases (Quaternius: 62-bone T-pose rig mismatch; MakeHuman: needs retopology + custom
|
|
||||||
rig + clothing).
|
|
||||||
- **Gaussian splatting (unversioned):** offline/development-only until an ADR proves licence,
|
- **Gaussian splatting (unversioned):** offline/development-only until an ADR proves licence,
|
||||||
privacy, Compatibility/Web cost and mesh collision. Accepted photo channels: team captures,
|
privacy, Compatibility/Web cost and mesh collision. Accepted photo channels: team captures,
|
||||||
permissioned user/volunteer photos, clearly licensed downloads; every set needs a
|
permissioned user/volunteer photos, clearly licensed downloads; every set needs a
|
||||||
provenance/consent sidecar. No runtime splat dependency in 0.10.0.
|
provenance/consent sidecar. No runtime splat dependency in 0.10.0.
|
||||||
- **0.10.0 balance protocol:** `docs/release-qa.md#balance-acceptance` defines targets/denominators for the
|
- **0.10.0 balance protocol:** `docs/process/release-qa.md#balance-acceptance` defines targets/denominators for the
|
||||||
36 venue/difficulty/phase cells, seeds 1–100, and access/emergency error rates. Gotcha:
|
36 venue/difficulty/phase cells, seeds 1–100, and access/emergency error rates. Gotcha:
|
||||||
`_read_npc_truth()` is type-derived, not behaviour-derived; the emergency-fairness review must
|
`_read_npc_truth()` is type-derived, not behaviour-derived; the emergency-fairness review must
|
||||||
account for that oracle mismatch.
|
account for that oracle mismatch.
|
||||||
- **Blender MCP is optional (2026-11-04):** setup and safe part workflow are in
|
- **Blender MCP is optional (2026-11-04):** setup and safe part workflow are in
|
||||||
`docs/asset-tooling.md#optional-interactive-blender-mcp`. The headless flatpak scripts remain authoritative; MCP is
|
`docs/assets/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 Quaternius base bake and
|
||||||
|
the 12-variant clothing detail. 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.
|
||||||
|
- **Quaternius is the NPC base (2026-11-05, owner):** ADR-0017 supersedes the generator-first
|
||||||
|
sourcing decision. The CC0 Quaternius Ultimate Modular character pack is the primary NPC mesh
|
||||||
|
and animation source. Stage 1 bakes a proportion-warped, 13-core-contract `npc_base` so
|
||||||
|
`NpcAvatar`, gear and animations keep working; the 62-joint/24-clip source rig is authoring
|
||||||
|
input, not a runtime dependency. If the warp fails the silhouette gate, Stage 2 needs a new ADR
|
||||||
|
for a 62-joint runtime, not a hybrid. The MakeHuman head and procedural `npc_base` remain
|
||||||
|
tested fallbacks until the Quaternius rollout ships. Quaternius source: CC0, attribution in
|
||||||
|
`CREDITS.md`; the three researched GLBs and licence notes are kept in
|
||||||
|
`tmp/npc-research/quaternius/`. MPFB/MakeHuman body work is closed; do not add new work there.
|
||||||
|
- **Quaternius bake keeps source detail (2026-11-05, owner):** during the contract bake (§2),
|
||||||
|
keep the Quaternius mesh as close to source as possible — no unnecessary decimation or LOD
|
||||||
|
reduction. The canonical base is only 3,199 verts / 6,206 tris, far under the 24,000 cap, so
|
||||||
|
there is no budget reason to decimate before the silhouette gate. Do not reuse the old
|
||||||
|
7,000-triangle or MPFB decimation targets.
|
||||||
|
- **Quaternius runtime rig (2026-11-05, owner, ADR-0018 option 2):** the Stage 1 proportion warp
|
||||||
|
failed the silhouette gate (arm ×1.63 / leg ×0.74 / torso ×1.61; vision judge: paddle hands,
|
||||||
|
lost forearms, stretched shins). The owner chose to **adopt the Quaternius 62-joint rig at
|
||||||
|
runtime** instead of warping: `NpcAvatar` maps the Quaternius joint names, gear attach points
|
||||||
|
are re-derived from the Quaternius skeleton (hip ≈0.87, shoulder ≈0.148/1.39, wrist ≈0.99,
|
||||||
|
knee ≈0.52) and the mesh keeps source LOD (arm-down rest pose baked). **The 24 upstream clips are
|
||||||
|
not played**: `_animate()` drives the proxies and `_sync_skeleton()` writes the bone poses, which
|
||||||
|
is what the FSM already needed for sitting, hand-raising and head turns. Playing the clips would
|
||||||
|
replace that state machine, not supplement it, so all 24 stay unused and the clips are authoring
|
||||||
|
reference only.
|
||||||
- **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.
|
||||||
@@ -83,10 +108,129 @@ canonical implemented-features list in `docs/development-status.md`.
|
|||||||
avatars. Head-turn offsets use `+basis.z` for the same reason.
|
avatars. Head-turn offsets use `+basis.z` for the same reason.
|
||||||
- **Release blockers (still open):** macOS unsigned, AI image provider terms/commercial rights not
|
- **Release blockers (still open):** macOS unsigned, AI image provider terms/commercial rights not
|
||||||
cleared, storefront/rating approval pending, external playtests and full hardware matrix pending.
|
cleared, storefront/rating approval pending, external playtests and full hardware matrix pending.
|
||||||
Recorded in `CREDITS.md`, `PRIVACY.md`, `docs/accessibility.md`, `docs/known-limitations.md`.
|
Recorded in `CREDITS.md`, `PRIVACY.md`, `docs/design/accessibility.md`, `docs/design/known-limitations.md`.
|
||||||
|
|
||||||
|
- **Release roadmap (2026-11-05, owner):** `0.9.9` Quaternius pilot base (rig/export fix,
|
||||||
|
rest-relative pose math, owner face/silhouette gate), `0.9.10` 12-role roster, `0.9.11`
|
||||||
|
scheduled venue/prop/lighting polish, `0.9.12` performance/Web/accessibility verification,
|
||||||
|
`0.10.0` public-readiness minor, then `0.10.1`–`0.10.3` fixes, `0.11.0` replay + fourth venue +
|
||||||
|
localization foundation, `0.12.0` signed/storefront builds + save v2, `0.13.x` content complete
|
||||||
|
and release candidates, `1.0.0` stable. The full gap analysis and roadmap live in `PLAN.md`; the
|
||||||
|
character track is versioned now, so a blocked rig cannot block the release. Planning only —
|
||||||
|
none of these versions is built yet.
|
||||||
|
- **Quaternius face/readability gate (2026-11-05):** the base is 6.2k tris total and replaces a
|
||||||
|
library with a sculpted realistic face, so the 0.9.9 gate is a product decision, not just an
|
||||||
|
art check. Owner picks full swap / crowd-only / extra head detail. Do not lower character
|
||||||
|
fidelity silently.
|
||||||
|
- **Pose composition is rest-relative (resolved 2026-11-05):** see `_swing_bone()` in the gotchas —
|
||||||
|
the rest-relative `set_bone_pose_rotation` form was abandoned; the global-pose write replaced it.
|
||||||
|
- **Full roster swap (2026-11-05, owner):** at the `0.9.9` face gate the owner chose option (a),
|
||||||
|
full swap. All twelve public character names are baked from the three CC0 Quaternius sources
|
||||||
|
(`casual`, `hoodie`, `worker`); variety comes from the five tint slots, the outfit rules and the
|
||||||
|
gear library. The procedural library + MakeHuman head stay in the tree as the tested fallback
|
||||||
|
(`build --source procedural`), not in the shipped roster. Silhouette variety is the known
|
||||||
|
regression — three meshes for twelve roles — and the modular part library is the `0.9.10` fix.
|
||||||
|
- **Emissive materials can carry a per-material night energy.** `set_night_mode` used to write one
|
||||||
|
multiplier into every `_marquee_emissive` entry, which flattens any gradient. It now reads
|
||||||
|
`mat.get_meta("night_energy", 2.0)`, so a multi-strip panel can keep its top-to-bottom ratio
|
||||||
|
(the event banners: 2.6 → 1.4).
|
||||||
|
- **`placement_problems()` was only gated for the Joke Shop.** Its test validated one venue's prop
|
||||||
|
list, so the TV Studio carried six violations (props inside the steps/door exclusion and off the
|
||||||
|
sidewalk) unnoticed. `test_every_venue_placement_clears_the_sidewalk_and_the_approach` now runs the
|
||||||
|
validator on all three venues. When adding a venue or a prop, that test is the gate.
|
||||||
|
- **Venue lights must keep `omni_attenuation == 1.0`** — `test_world.test_venue_lights_use_physical_falloff`
|
||||||
|
enforces physical falloff on every Omni/Spot in all three venues, so a "pool" cannot come from
|
||||||
|
sharpening the curve. Use `omni_range` + energy instead: 10 m / energy 8 gives a brighter pool and
|
||||||
|
a darker gap than the old 16 m / 2.2.
|
||||||
|
- **Tune lights against a measurement, not a look (2026-11-06):** the shipped flashlight changed the
|
||||||
|
late-night frame by 0.1/255 and nobody noticed. `capture_realism.gd --stages=late --flashlight`
|
||||||
|
renders the same frame with the lamp on and off; mean luminance of the aimed region and the near
|
||||||
|
pavement is now the acceptance number. Current: energy 10, range 45 m, cone 24°, tilted 5° down →
|
||||||
|
13.5 → 29.7 aimed, 3.7 → 11.7 near ground.
|
||||||
|
- **Docs live in category folders (2026-11-06):** `docs/project/` (architecture, development status),
|
||||||
|
`docs/design/` (gameplay, venues, ui-copy, accessibility, known-limitations), `docs/assets/`
|
||||||
|
(asset tooling, blender assets, npc sourcing, 3d-model-review, makehuman head), `docs/process/`
|
||||||
|
(getting started, release QA, releasing), plus `docs/adr/`, `docs/screens/`, `docs/screenshots/`.
|
||||||
|
Write to the new paths; `docs/*.md` at the root no longer exists apart from `README.md`.
|
||||||
|
- **Foliage is leaf cards, not sphere stacks (2026-11-06):** `_shrub()` is one low-poly inner mass
|
||||||
|
plus 18–53 two-triangle cards scattered on the canopy shell by a jittered Fibonacci sequence, each
|
||||||
|
rotated onto the canopy normal and tilted off it. No alpha texture, so the flat-colour library and
|
||||||
|
the Compatibility renderer are unaffected — and it is ~35 % cheaper than the sphere stack it
|
||||||
|
replaced. If a shrub ever reads as a rock again, the cards were probably rotated to the normal
|
||||||
|
without the random tilt (`spread`).
|
||||||
|
- **Roster is eleven outfits over twelve roles (2026-11-06):** hoodie, Casual, Worker, Suit,
|
||||||
|
Adventurer, Beach, Casual_2, Farmer, King, Punk (Swat is intaken but unused — it faces Godot −Z and
|
||||||
|
every yaw attempt broke the skin: node rotation turns the skin with it, object rotation collapses
|
||||||
|
it, and data-space rotation after `transform_apply` still loses the head). Per-family slot maps
|
||||||
|
live in `QUATERNIUS_SOURCES`; a family
|
||||||
|
that cannot paint a slot (Farmer has no hair) gets `patch_slots`, which buries a 4 cm triangle so
|
||||||
|
the material survives the export and the contract holds.
|
||||||
|
- **FBX modular parts need five fixes before they are a base (2026-11-06):** (1) every FBX file
|
||||||
|
carries its own armature — keep one and repoint the meshes; (2) FBX adds `_end` leaf bones and a
|
||||||
|
`neutral_bone` root, and **Godot refuses the GLB entirely** (`resource_format_binary` / missing
|
||||||
|
`.scn`) until they are stripped to the 62 joints; (3) bake object transforms before export or the
|
||||||
|
glTF node transforms change the rest pose and the head renders several times too large;
|
||||||
|
(4) the pack reuses one fabric material for jacket and trousers — copy it per leg mesh
|
||||||
|
(`*_legs`) so the slot map can send it to `pants`; (5) imported parts share seams, so dissolve
|
||||||
|
and drop zero-area triangles or the audit fails.
|
||||||
|
- **`tmp/` needs a `.gdignore`.** Godot scans the project tree, so a downloaded asset pack under
|
||||||
|
`tmp/quaternius-intake/` gets imported (it flooded the import log and broke `--import` for the
|
||||||
|
rest of the project). An empty `tmp/.gdignore` stops it; capture output there is unaffected.
|
||||||
|
- **Modular part intake is a one-time manual download (2026-11-06, owner):** the upstream pack is a
|
||||||
|
Google Drive folder, so the owner downloads it once into the gitignored
|
||||||
|
`tmp/quaternius-intake/` and `tools/quaternius_parts.py` does the rest
|
||||||
|
(`inventory` → `extract` → `verify`). A part must be one skinned mesh on the 62-joint rig; a GLB
|
||||||
|
exported *without* an armature has no `JOINTS_0` and validates as bone-less, so `extract` keeps
|
||||||
|
the armature and `build` drops it again at join time.
|
||||||
|
- **Hair variety is built in-project (2026-11-06):** the upstream modular pack is a Google Drive
|
||||||
|
folder, so it cannot be fetched reproducibly; `QUATERNIUS_HAIR_PARTS` reshapes the one hair shell
|
||||||
|
each base ships (`short` identity, `buzz` squash, `long` stretch, `bald` removal) and the role's
|
||||||
|
existing `CHARACTERS[...]["hair"]` picks it. `bald` is restricted to bases whose skin closes the
|
||||||
|
skull. Outfit variety still needs the pack or new garments.
|
||||||
|
- **No hats except the firefighter helmet (2026-11-06, owner):** the iconography is not worth the
|
||||||
|
cost — a cap or hood on this head hides the face, and every hat needed a lift+scale hack to clear
|
||||||
|
the 0.228 m hair shell. `ACCESSORIES` maps no role to `cap`/`hood`, the guard/vest per-character
|
||||||
|
caps are gone, the performer cone was removed, and the primitive cap/hood fallbacks were deleted
|
||||||
|
with their `GEAR_OFFSETS`/`GEAR_SCALE` compensation. `firefighter_helmet` is the only head item.
|
||||||
|
Do not re-add head gear without an owner decision and a fit measurement.
|
||||||
|
- **Mouths are authored, not upstream (2026-11-06):** none of the three Quaternius heads has a mouth
|
||||||
|
material, so the faces read as brow-and-eye masks. `_add_quaternius_mouth()` places a small lip
|
||||||
|
block on the measured skin surface (front-most skin vertex in the 1.600–1.632 m band, ±35 mm of
|
||||||
|
centre) at 1.616 m. One rule covers all three bases; it runs before the slot map, so match the
|
||||||
|
material as `_base_name(m.name).lower() == "skin"`.
|
||||||
|
- **One character source, one fallback:** no new NPC source without an ADR. MPFB body work stays
|
||||||
|
closed, the Stage-1 proportion warp is not reopened, and the procedural `npc_base` + MakeHuman
|
||||||
|
head stay tested until the Quaternius base passes its gate.
|
||||||
|
|
||||||
## Gotchas / Known Issues
|
## Gotchas / Known Issues
|
||||||
|
|
||||||
|
- **Blender material-list edits corrupt polygons silently.** Two separate bugs, same root:
|
||||||
|
`obj.data.materials.clear()` resets **every polygon to slot 0**, so the per-face indices must be
|
||||||
|
captured *before* the clear and reassigned after; and `IDMaterials.pop(index=)` repoints the
|
||||||
|
polygons that used the slot, which once painted a whole face with the eye material. The safe
|
||||||
|
pattern is `_purge_unused_materials()`: read the per-face material **names**, rebuild the slot
|
||||||
|
list from the names, then write the indices back by name.
|
||||||
|
- **A zero-user material still owns its name.** Removing a slot leaves the datablock behind, so a
|
||||||
|
donor material renamed to the freed name lands as `Eye.001` and every `m.name == "Eye"` rule
|
||||||
|
silently misses it. Purge the datablocks (`bpy.data.materials.remove(m)` when `m.users == 0`) or
|
||||||
|
match on `_base_name()`.
|
||||||
|
- **A duplicated detail face has to be offset along its own normal.** Copying the eye quad into a
|
||||||
|
pupil and nudging it in world `-Y` vanished: the eye plane is tilted, so the "front" nudge went
|
||||||
|
backwards and the pupil sat inside the sclera. Offsetting along `face.normal * 0.0032` fixed it.
|
||||||
|
Also scale the depth axis when shrinking a copy, or it flattens onto the parent plane.
|
||||||
|
- **Blender node colours are linear; Godot tonemaps them.** A mouth lip at `0.16` linear rendered as
|
||||||
|
salmon/mauve. Divide by roughly 3–4 versus the intended sRGB value: the hair uses 0.027 linear,
|
||||||
|
the lip 0.055/0.018/0.02.
|
||||||
|
- **The modular Quaternius Worker has no torso under its vest and no crown under its hard hat.**
|
||||||
|
Deleting either material leaves real holes (that is what shipped in the first 0.9.9 build: guard
|
||||||
|
and firefighter showed the inside of the head and torso). Remap instead of deleting; the only
|
||||||
|
geometry the build removes is the Worker brow bar, which is replaced by a donor part.
|
||||||
|
- **Head gear authored for the 0.315 m procedural head is wrong on the 0.20 m Quaternius head.** Gear
|
||||||
|
is authored around the head *centre* (1.62) while the attach node is the Head *bone* (1.587), and
|
||||||
|
the Quaternius centre is 1.69 — a 7 cm error put every cap brim across the brows, which I spent
|
||||||
|
several passes misreading as a mesh hole (the band was pure black and no material had faces
|
||||||
|
there). `HEAD_GEAR_LIFT = 0.103` fixes the common case. With the hats removed this only affects
|
||||||
|
the firefighter helmet.
|
||||||
- **Two character builders — do not confuse them.** `tools/blender_assets.py` is the real builder
|
- **Two character builders — do not confuse them.** `tools/blender_assets.py` is the real builder
|
||||||
for the **eight library characters, 18 gear pieces and props** (it has the 0.9.4 face/hand
|
for the **eight library characters, 18 gear pieces and props** (it has the 0.9.4 face/hand
|
||||||
sculpting in `_face()`/`_hands_and_shoes()`); `tools/npc_pipeline.py` builds **only**
|
sculpting in `_face()`/`_hands_and_shoes()`); `tools/npc_pipeline.py` builds **only**
|
||||||
@@ -105,6 +249,44 @@ canonical implemented-features list in `docs/development-status.md`.
|
|||||||
out of a portrait frame (park the rest of the crowd away instead).
|
out of a portrait frame (park the rest of the crowd away instead).
|
||||||
- Blender: `bisect_plane` and thin bevels leave zero-area triangles (Godot "non-finite normal in
|
- Blender: `bisect_plane` and thin bevels leave zero-area triangles (Godot "non-finite normal in
|
||||||
LOD generation"); `_clean()` + a weld after bisect fixes them and the audit rejects them.
|
LOD generation"); `_clean()` + a weld after bisect fixes them and the audit rejects them.
|
||||||
|
- Quaternius arm-down bake (working recipe, `tmp/npc-research/bake_armdown_v5.py`): pose-rotate
|
||||||
|
`UpperArm.L/R` −90° local X → read the pose matrices → apply the Armature modifier → **reset the
|
||||||
|
pose to identity** → set each arm bone's rest matrix from its pose matrix → re-add the modifier →
|
||||||
|
export `export_apply=False`. Missing the pose reset double-applies the arm-down (mesh ±0.53
|
||||||
|
instead of ±0.23). `armature_apply` in Blender 5.2 is broken (deforms the mesh but does not bake
|
||||||
|
the rest). The canonical base must be **join-only** (`build_base_minimal.py`: no `remove_doubles`
|
||||||
|
weld, no scale/ground transform, keep the Armature modifiers) — the weld and the scale/ground
|
||||||
|
transform corrupt the skin weights (arm poses to ±0.51 instead of −0.23).
|
||||||
|
- Quaternius `NpcAvatar` wiring (commits `2a6f29f`, `cd285b3`): `RIG_BONES` +
|
||||||
|
`NpcAvatar.bone_name(joint, side)` hold the **only** side mapping — the Quaternius labels `L`/`R`
|
||||||
|
opposite the project, so proxy side 0 (`-x`) drives `UpperLeg.R`/`UpperArm.R` while side 1 drives
|
||||||
|
the `.L` bones. The arm/elbow swing axis is `Vector3.LEFT` (legs stay `RIGHT`). The hand proxy is
|
||||||
|
`global_wrist − global_elbow` (subtracting the parent-relative `elbow.position` misplaces
|
||||||
|
handheld gear). Old 13-core names resolve through the same table.
|
||||||
|
- **Bone posing must write the global pose** (`NpcAvatar._swing_bone`): `reset_bone_pose()` then
|
||||||
|
`set_bone_global_pose(Transform3D(Basis(swing * global_rot), current_origin))`, conjugated with
|
||||||
|
`get_bone_global_rest()`. Both rejected alternatives fail: the rest-relative
|
||||||
|
`set_bone_pose_rotation(rest * Quaternion(rest⁻¹·axis, angle))` swings about the parent-relative
|
||||||
|
rest (the glTF importer already folded the axis conversion into it) and splayed the Quaternius
|
||||||
|
arms sideways; the plain `rest⁻¹ * swing * rest` conjugation flips the limbs 180°. Verified by
|
||||||
|
measuring `get_bone_global_pose()` after the call — posed bone axis matches the proxy pivot at
|
||||||
|
dot 1.000 on the Quaternius and the procedural rigs render unchanged.
|
||||||
|
Two caveats: children need the parent's swing passed in (the write is absolute), and
|
||||||
|
`set_bone_global_pose()` is a **no-op outside the scene tree**, so the headless runner (tests run
|
||||||
|
in `_initialize()`) cannot assert on it.
|
||||||
|
- **The Quaternius source UV map is degenerate** — every loop at (0,0), flat-colour materials, no
|
||||||
|
atlas. The AO/texture bake silently produces a 100 % black map, which tints every AO'd slot
|
||||||
|
(skin, hair, accessory) black in Godot: a black leg is the symptom. `build_base_minimal.py` now
|
||||||
|
Smart-UV-unwraps and repacks the layout (texel density 0 → 73–74 px/m on 256²), and the base
|
||||||
|
pipeline is two explicit steps with distinct files: `build_base_minimal.py`
|
||||||
|
(`quaternius/Casual_Hoodie.glb` → `quaternius_tpose.glb`, joins without welding, renames the
|
||||||
|
materials to the five tint slots, unwraps) then `bake_armdown_v5.py` (`quaternius_tpose.glb` →
|
||||||
|
`quaternius_base.glb` + `assets/models/blender_src/npc_casual.blend`). Re-running v5 on its own
|
||||||
|
output double-bakes the rest.
|
||||||
|
- Hand gear must be self-contained: the camera carried a 0.42 m neck-strap loop that floats when the
|
||||||
|
item is parented to the wrist. Hand items get a short wrist strap, not a neck strap. The backpack
|
||||||
|
straps were authored for the wider procedural chest and floated ~5 cm proud of the Quaternius
|
||||||
|
torso; the chest points now sit at x 0.12 / Godot z 0.15, which fits both.
|
||||||
- Image models have per-model size floors/caps (Seedream needs 1920+; `GEN_SIZE=2048`, do not
|
- Image models have per-model size floors/caps (Seedream needs 1920+; `GEN_SIZE=2048`, do not
|
||||||
lower; gpt-5-image-mini caps lower). `generate_image` applies model-specific sizing; concept
|
lower; gpt-5-image-mini caps lower). `generate_image` applies model-specific sizing; concept
|
||||||
generation defaults to `--request-size 1536`.
|
generation defaults to `--request-size 1536`.
|
||||||
@@ -169,6 +351,8 @@ canonical implemented-features list in `docs/development-status.md`.
|
|||||||
- Character checks: `python3 tools/blender_assets.py inspect|audit|fit`,
|
- Character checks: `python3 tools/blender_assets.py inspect|audit|fit`,
|
||||||
`python3 tools/npc_proportions.py`
|
`python3 tools/npc_proportions.py`
|
||||||
- Docs: `python3 tools/check_docs.py` (every tracked image must be linked from its folder README)
|
- Docs: `python3 tools/check_docs.py` (every tracked image must be linked from its folder README)
|
||||||
|
- Head/part pipeline: `python3 tools/npc_parts.py build|extract|assemble|inspect|sheet|compare`
|
||||||
|
(Blender subcommands run under flatpak). Head sources: `build_character(head="face"|"proto"|"mh")`.
|
||||||
- Reference research: `python3 tools/refcollect.py search <q> --slug <block> --limit N`
|
- Reference research: `python3 tools/refcollect.py search <q> --slug <block> --limit N`
|
||||||
(local-only), `tools/refboard.py` (Commons), `tools/three_up.py compose/rows`,
|
(local-only), `tools/refboard.py` (Commons), `tools/three_up.py compose/rows`,
|
||||||
`tools/scene_concepts.py generate/anchor/realism`
|
`tools/scene_concepts.py generate/anchor/realism`
|
||||||
@@ -176,18 +360,55 @@ canonical implemented-features list in `docs/development-status.md`.
|
|||||||
## Open Questions
|
## Open Questions
|
||||||
|
|
||||||
- Whether the responder avatar should be playable/controllable or purely scripted.
|
- Whether the responder avatar should be playable/controllable or purely scripted.
|
||||||
- Localization target languages beyond English.
|
- Quaternius scope: full 12-role swap, crowd-only, or extra head detail (owner decision at 0.9.9).
|
||||||
- macOS notarization approach for broad distribution.
|
- Localization target languages beyond English (0.11.0/0.12.0).
|
||||||
|
- macOS notarization approach for broad distribution (0.12.0).
|
||||||
|
- Fourth-venue choice for 0.11.0 (candidate: TCL Chinese Theatre forecourt).
|
||||||
|
|
||||||
## Current State
|
## Current State
|
||||||
|
|
||||||
The playable build covers the three venues, tutorial/campaign/checkpoints, the 0.9.3–0.9.6
|
v0.9.9 is published. The build covers the three venues, the shift loop, tutorial/campaign/
|
||||||
polish/texture/integration passes and the Blender + realism asset pipeline (see `DONE.md` and
|
checkpoints, the 0.9.3–0.9.8 polish/texture/integration/character passes and the Blender +
|
||||||
`CHANGELOG.md`). The 12-character library (realistic face + four crowd variants) and the
|
realism asset pipeline (see `DONE.md` and `CHANGELOG.md`). The 12-character procedural library
|
||||||
Comedy Store map rebuild are complete. **Priority (2026-11-04, owner):** 1) the **Blender NPC
|
(realistic face + four crowd variants) and the Comedy Store map rebuild are complete.
|
||||||
model overhaul** (head/face/hands, local part pipeline), 2) finish the MakeHuman character + the
|
|
||||||
3D model and map improvements, 3) ship it all together in the **0.10.0 minor**. The 0.9.7/0.9.8
|
**Planning pivot (2026-11-05, owner):** the character and map work was re-sequenced into
|
||||||
character patches are published; `TODO.md` is the priority source. Test counts as of 2026-11-04:
|
patches (`0.9.9`–`0.9.12`) with `0.10.0` as the public-readiness minor. The gap analysis and the
|
||||||
Godot 277/277, Python 162/162, `check_docs` OK.
|
three release roadmaps now live in `PLAN.md`; `TODO.md` is the executable task list. ADR-0017
|
||||||
|
Stage 1 (proportion warp) is dead; ADR-0018 option 2 (62-joint runtime) is accepted.
|
||||||
|
|
||||||
|
**Full roster (0.9.9, commits `a6ccd86` … `9fd4824`):** all twelve characters run on the
|
||||||
|
Quaternius bases (62 joints, 73–74 px/m texel density), built by the shipped
|
||||||
|
`tools/blender_assets.py` two-pass pipeline (`_quaternius_tpose_glb` → `_bake_quaternius_rest`).
|
||||||
|
The owner signed the roster off **with follow-ups** and rejected three review rows; the Worker
|
||||||
|
body defects (holes, unibrow, missing eyes) and the head-gear seating are fixed, every hat except
|
||||||
|
the firefighter helmet is removed, and every head has an authored mouth. Gates: `audit` 12/12,
|
||||||
|
`inspect` clean, `fit` OK, 24-NPC budget 174,976 tris / 0.85 ms, Godot 278/278, Python 167/167.
|
||||||
|
The owner **accepted the roster on 2026-11-06** and the review page plus its sheets were then
|
||||||
|
retired; durable evidence lives in `docs/assets/3d-model-review.md` and `docs/assets/blender-assets.md`. Release
|
||||||
|
packaging was fixed the same day:
|
||||||
|
excluding `tmp/`, `build/`, `docs/`, `tools/`, `src/test/` and `.agents/` from the export presets
|
||||||
|
cut the Linux binary from 426 MB to 273 MB, and `tools/build_releases.sh` writes a SHA256SUMS file.
|
||||||
|
|
||||||
|
**Open after the swap:** hand-held gear and role props are still authored for the old body (wrist
|
||||||
|
y 0.78 → 1.017, arm shorter), so the clipboard and umbrella are oversized; the eyes have no whites;
|
||||||
|
the arms graze the torso on the `worker` base; roster variety is three meshes for twelve roles. The
|
||||||
|
prop/gear fit pass is queued in `TODO.md` under 0.9.10.
|
||||||
|
|
||||||
|
**Quaternius pilot (2026-11-05, commits `cd285b3`, `fb3e75a`, `90f189a`):** `npc_casual` ships as
|
||||||
|
the Quaternius base. It renders arm-down, carries the five tint slots, plays the Idle/Walk/Sit pose
|
||||||
|
code on the 62-joint rig, and the procedural rigs are visually unchanged. Verified: `inspect`
|
||||||
|
(no issues), `audit` OK (6,206 tris / 12,988 verts, 62 bones), `fit` head 0.201 m, texel density
|
||||||
|
73–74 px/m, `npc_proportions` measured, 24-NPC budget smoke OK (168 meshes, 162,304 tris,
|
||||||
|
0.82 ms avg frame). The face/silhouette gate sheet and the three options are in
|
||||||
|
the face-gate decision (owner chose the full swap).
|
||||||
|
|
||||||
|
Test counts as of 2026-11-06: Python 167/167, Godot 278/278, `check_docs` OK.
|
||||||
|
|
||||||
|
**Docs layout (2026-11-06):** `docs/` is grouped into `project/`, `design/`, `assets/` and
|
||||||
|
`process/`; `adr/`, `screens/`, `screenshots/` and `blender_previews/` are unchanged.
|
||||||
|
`docs/README.md` is the index and every category folder has a README (required by
|
||||||
|
`tools/check_docs.py`). The retired `docs/screens/head-review/` page and its sheets were deleted;
|
||||||
|
the MakeHuman fallback head is documented in `docs/assets/makehuman-head-review.md`.
|
||||||
|
|
||||||
<!-- b64: RWFzdGVyIGVnZzogYSByYXJlIHJhZGlvIHRyYW5zbWlzc2lvbiAiwr9Ew7NuZGUgZXN0w6EgbGEgbW90YT8iIGZpcmVzIHZpYSBHYW1lTWFuYWdlci5fbWF5YmVfcmFkaW9fZWFzdGVyX2VnZyAoMi41JSBjaGFuY2UgYWZ0ZXIgYSBzdWNjZXNzZnVsIHJhZGlvIGNhbGwpLiBTdHJpbmcga2V5IHJhZGlvLmVhc3Rlcl9lZ2cgaW4gY29udGVudC9zdHJpbmdzLmVuLmpzb24uIERvIG5vdCByZW1vdmUu -->
|
<!-- b64: RWFzdGVyIGVnZzogYSByYXJlIHJhZGlvIHRyYW5zbWlzc2lvbiAiwr9Ew7NuZGUgZXN0w6EgbGEgbW90YT8iIGZpcmVzIHZpYSBHYW1lTWFuYWdlci5fbWF5YmVfcmFkaW9fZWFzdGVyX2VnZyAoMi41JSBjaGFuY2UgYWZ0ZXIgYSBzdWNjZXNzZnVsIHJhZGlvIGNhbGwpLiBTdHJpbmcga2V5IHJhZGlvLmVhc3Rlcl9lZ2cgaW4gY29udGVudC9zdHJpbmdzLmVuLmpzb24uIERvIG5vdCByZW1vdmUu -->
|
||||||
@@ -16,20 +16,91 @@ The game is about **judgment, communication, access verification, and proportion
|
|||||||
|
|
||||||
## Development Priorities
|
## Development Priorities
|
||||||
|
|
||||||
The active planning order is set in [`TODO.md`](TODO.md) and in `AGENTS.md`:
|
The active task order is in [`TODO.md`](TODO.md); the gap analysis and the release roadmap are
|
||||||
|
below. The current order is:
|
||||||
|
|
||||||
1. **Character development (unversioned).** Expand the owned procedural character library with
|
1. **0.9.9–0.9.12 patches.** Finish the character base (the accepted Quaternius 62-joint runtime),
|
||||||
crowd, age, build, hair and outfit variety. Keep the frozen bone/tint/gear contract; see
|
roll it out to the 12 roles, close the scheduled venue/prop/lighting polish, and verify
|
||||||
[ADR-0015](docs/adr/0015-npc-model-variety-sourcing.md) and
|
performance, Web and accessibility.
|
||||||
[`docs/npc-model-sourcing.md`](docs/npc-model-sourcing.md). Quaternius is a reference;
|
2. **0.10.0 minor.** Public readiness: external playtests, balance acceptance, legal/storefront
|
||||||
MakeHuman is deferred to a separate local pipeline.
|
approval, the platform matrix and the documentation/picture lock.
|
||||||
2. **Local map development (unversioned).** Move beyond stylized venue reconstruction with
|
3. **0.10.x patches → 0.11.0.** Content and systems depth: live body-camera replay, a fourth
|
||||||
licensed OpenStreetMap and 3D building data, downloaded reference imagery for photoreal
|
venue and the localization foundation.
|
||||||
facades, AI-assisted composition, and a Gaussian-splatting evaluation that stays in the
|
4. **0.12.0 → 1.0.0.** Platform/distribution, content complete, release candidates and the stable
|
||||||
development pipeline unless it proves runtime-safe.
|
release.
|
||||||
3. **Versioned release hardening.** The 0.10.0 release candidate and later semantic versions come
|
|
||||||
after the unversioned development tracks in planning order. Versions are assigned only when a
|
Versions are assigned only when a track's scope is accepted into a release (see
|
||||||
track's scope is accepted into a release.
|
[Release Roadmap](#release-roadmap)). Unversioned tracks — the 3D review evidence base,
|
||||||
|
maintenance and the Gaussian-splatting study — do not receive a placeholder version.
|
||||||
|
|
||||||
|
## Plan Evaluation (2026-11-05)
|
||||||
|
|
||||||
|
The game plan itself is sound and largely built: three venues, the escalation ladder, access
|
||||||
|
artifacts, the radio/report system, the shift review and the campaign loop all exist and are
|
||||||
|
tested. What needed fixing was the **delivery plan**, not the design.
|
||||||
|
|
||||||
|
- **Character sourcing churned.** The project moved procedural → MakeHuman → Quaternius, and the
|
||||||
|
Quaternius Stage-1 warp failed its own gate. That leaves a correct decision (ADR-0018) with a
|
||||||
|
half-finished implementation. The plan now makes the rig correction one small version, gates the
|
||||||
|
roster behind a face/readability decision, and keeps exactly one fallback.
|
||||||
|
- **One milestone carried too much.** The old 0.10.0 mixed character work, map work and every
|
||||||
|
public-release gate, so one blocked export blocked the release. Character and venue polish are
|
||||||
|
now patches; 0.10.0 is only the release gate.
|
||||||
|
- **Unversioned work had no deadline.** The 3D review backlog could grow without bound. It is now
|
||||||
|
capped: the ranked venue/prop/lighting items are scheduled into 0.9.11, the budget checks into
|
||||||
|
0.9.12, and everything else is an explicit accept or deferred. Gaussian splatting stays
|
||||||
|
unscheduled because no product need justifies its risk yet.
|
||||||
|
- **Legal, signing and storefront work is release work, not polish.** It now has named checkboxes
|
||||||
|
in 0.10.0 and 1.0.0 instead of living in prose.
|
||||||
|
- **What is deliberately not planned:** new genres or mechanics, a live-service model, or a
|
||||||
|
runtime splat renderer. The de-escalation-first, rare-emergency design stays frozen.
|
||||||
|
|
||||||
|
Feasibility: the remaining character work is small in geometry terms (6.2k triangles against a
|
||||||
|
24k cap) and larger in rig/export terms; the venue work is polish; most release gates are
|
||||||
|
evidence gathering rather than engineering. The main schedule risk is external review and
|
||||||
|
approval, not code.
|
||||||
|
|
||||||
|
## Character Creation Re-Evaluation (2026-11-05)
|
||||||
|
|
||||||
|
**Where it stands.** The shipped library is 12 procedural Blender variants (4.7k–5.8k triangles
|
||||||
|
each) with a sculpted face, five tint slots and 18 gear pieces. The owner then chose the CC0
|
||||||
|
**Quaternius Ultimate Modular Characters** as the primary source. Stage 1 (warp the Quaternius
|
||||||
|
mesh onto the 13-core contract) failed its silhouette gate — arm ×1.63, leg ×0.74, torso ×1.61,
|
||||||
|
judged distorted. [ADR-0018](docs/adr/0018-quaternius-stage2-runtime-rig.md) therefore adopts the
|
||||||
|
source **62-joint rig at runtime**: no warp, source LOD (3,199 verts / 6,206 tris), source
|
||||||
|
Idle/Walk clips, and gear pivots re-derived from the Quaternius skeleton.
|
||||||
|
|
||||||
|
**What is already built.** The canonical `quaternius_base.glb` (welded, grounded, arm-down rest),
|
||||||
|
the 62→13 joint map, the material→five-slot map, the clip inventory (24 clips; Idle and Walk in
|
||||||
|
scope) and the `NpcAvatar` joint-name mapping with rest-derived gear pivots.
|
||||||
|
|
||||||
|
**What actually blocks it.** Two technical items about the export and the pose math, not the art:
|
||||||
|
|
||||||
|
1. the arm-down GLB renders in A-pose in Godot because the bake writes wrong inverse bind
|
||||||
|
matrices; and
|
||||||
|
2. `_pose_bone()` composes rotations as `rest * Quaternion(axis, angle)`, which only cancels for
|
||||||
|
the old 180° rest, not the Quaternius ~76° rest.
|
||||||
|
|
||||||
|
**Re-evaluation findings.**
|
||||||
|
|
||||||
|
- Triangle budget is not the problem (6.2k against a 24k cap). Do not decimate the source.
|
||||||
|
- **Face fidelity is the real risk.** The 0.9.7 library has a sculpted realistic face; the
|
||||||
|
Quaternius head is low-poly. A blanket swap would regress every close-up. The plan therefore
|
||||||
|
makes the owner choose at 0.9.9 between (a) a full swap, (b) Quaternius for crowd roles with the
|
||||||
|
procedural library for named roles, or (c) extra head subdivision/hair cards on the Quaternius
|
||||||
|
head.
|
||||||
|
- **Animation** becomes clip-driven, which removes the hand-built pose composition as the main
|
||||||
|
path. Poses the clips do not cover (seated, raise-hand, head turn) must be decided explicitly
|
||||||
|
rather than patched per scene.
|
||||||
|
- **One fallback, no third source.** The procedural `npc_base` and the MakeHuman head stay tested
|
||||||
|
until the new base passes the gate. MPFB body work stays closed and the Stage-1 warp is not
|
||||||
|
reopened. A new character source needs a new ADR.
|
||||||
|
- **Sequence matters.** Fix the rig first (0.9.9), then the roster (0.9.10). Rolling a broken rig
|
||||||
|
across 12 variants would waste the whole pass.
|
||||||
|
|
||||||
|
**Reversal condition.** If the skin cannot be exported correctly without a new exporter path, or
|
||||||
|
if the owner rejects the low-poly face in every option, the plan falls back to the procedural
|
||||||
|
library and retires Quaternius with a recorded ADR. That decision is made at 0.9.9, not later.
|
||||||
|
|
||||||
## Core Gameplay Loop
|
## Core Gameplay Loop
|
||||||
|
|
||||||
@@ -169,7 +240,7 @@ The action wheel prioritizes de-escalation: Stop, Look, Point, No, Ask, Inspect,
|
|||||||
|
|
||||||
The visual direction is readable stylized realism:
|
The visual direction is readable stylized realism:
|
||||||
|
|
||||||
- **Character direction:** 8 skinned NPC variants, 18 gear pieces and 20 street/venue props, with four crowd-variety variants prototyped. The generator-first expansion is the active character track ([ADR-0015](docs/adr/0015-npc-model-variety-sourcing.md)); Quaternius is a reference and MakeHuman is deferred to a local pipeline.
|
- **Character direction:** 12 skinned NPC variants, 18 gear pieces and 20 street/venue props. The active character track is the Quaternius base at runtime ([ADR-0018](docs/adr/0018-quaternius-stage2-runtime-rig.md)): the CC0 source mesh keeps its proportions on the 62-joint rig, Idle/Walk run as clips, and the procedural library stays as the tested fallback until the face/silhouette gate passes. See [Character Creation Re-Evaluation](#character-creation-re-evaluation-2026-11-05).
|
||||||
- **Realism pass:** AI-assisted per-phase skyline panoramas, v2 surface tiles with normal maps, wet asphalt at night, a warm day haze, phase-specific sun/exposure/fog, a tight flashlight spot (no beam geometry), and denser foliage.
|
- **Realism pass:** AI-assisted per-phase skyline panoramas, v2 surface tiles with normal maps, wet asphalt at night, a warm day haze, phase-specific sun/exposure/fog, a tight flashlight spot (no beam geometry), and denser foliage.
|
||||||
- **Local map direction:** the venues are currently stylized reconstructions. The local-map track evaluates licensed OpenStreetMap/3D building data, licensed reference photography, AI-assisted composition and Gaussian splatting as a development tool; online data and splat rendering are not runtime dependencies.
|
- **Local map direction:** the venues are currently stylized reconstructions. The local-map track evaluates licensed OpenStreetMap/3D building data, licensed reference photography, AI-assisted composition and Gaussian splatting as a development tool; online data and splat rendering are not runtime dependencies.
|
||||||
- **References and QA:** runtime UI art lives in `assets/images/ui/`; reference/art-direction sets live in `docs/screens/designs/` and `docs/screens/concepts/`; captures live in `docs/screenshots/`; realism runs live in `docs/screens/realism/`. `screen_designs.py compare/judge` and `tools/check_screenshots.sh` guard drift.
|
- **References and QA:** runtime UI art lives in `assets/images/ui/`; reference/art-direction sets live in `docs/screens/designs/` and `docs/screens/concepts/`; captures live in `docs/screenshots/`; realism runs live in `docs/screens/realism/`. `screen_designs.py compare/judge` and `tools/check_screenshots.sh` guard drift.
|
||||||
@@ -177,7 +248,7 @@ The visual direction is readable stylized realism:
|
|||||||
|
|
||||||
The active planning order — unversioned character and local-map development first, then the versioned 0.10.0 release-candidate hardening and later releases — is tracked in [`TODO.md`](TODO.md); this plan stays at the product/design level.
|
The active planning order — unversioned character and local-map development first, then the versioned 0.10.0 release-candidate hardening and later releases — is tracked in [`TODO.md`](TODO.md); this plan stays at the product/design level.
|
||||||
|
|
||||||
Primary decisions: [ADR-0007](docs/adr/0007-locomotion-and-input-layers.md), [ADR-0008](docs/adr/0008-cone-focus-and-head-ring.md), [ADR-0009](docs/adr/0009-radial-action-menu.md), [ADR-0010](docs/adr/0010-procedural-npc-presentation.md), [ADR-0011](docs/adr/0011-aim-free-selection-and-precision-walk.md), [ADR-0012](docs/adr/0012-surface-materials-and-generated-props.md), [ADR-0013](docs/adr/0013-blender-authored-npc-characters.md), [ADR-0015](docs/adr/0015-npc-model-variety-sourcing.md).
|
Primary decisions: [ADR-0007](docs/adr/0007-locomotion-and-input-layers.md), [ADR-0008](docs/adr/0008-cone-focus-and-head-ring.md), [ADR-0009](docs/adr/0009-radial-action-menu.md), [ADR-0010](docs/adr/0010-procedural-npc-presentation.md), [ADR-0011](docs/adr/0011-aim-free-selection-and-precision-walk.md), [ADR-0012](docs/adr/0012-surface-materials-and-generated-props.md), [ADR-0013](docs/adr/0013-blender-authored-npc-characters.md), [ADR-0015](docs/adr/0015-npc-model-variety-sourcing.md), [ADR-0017](docs/adr/0017-quaternius-npc-base.md).
|
||||||
|
|
||||||
## Tech Stack
|
## Tech Stack
|
||||||
|
|
||||||
@@ -194,7 +265,107 @@ Primary decisions: [ADR-0007](docs/adr/0007-locomotion-and-input-layers.md), [AD
|
|||||||
|
|
||||||
## Versioning and Delivery
|
## Versioning and Delivery
|
||||||
|
|
||||||
`config/version` in `project.godot` is the single version source (currently `0.9.8`). Releases are tagged `v<version>`; the CI pipeline builds and publishes the standard artifacts plus the optional Desktop HQ zip. Version bumps follow [Semantic Versioning](https://semver.org/): every major, minor and patch increment needs a changelog entry, a local `tools/build_releases.sh` build, and artifact/checksum verification before tagging. Unversioned development tracks do not receive a version until their scope enters a release. See [`docs/RELEASING.md`](docs/RELEASING.md) and [`README.md`](README.md) for commands.
|
`config/version` in `project.godot` is the single version source (currently `0.9.9`). Releases are tagged `v<version>`; the CI pipeline builds and publishes the standard artifacts plus the optional Desktop HQ zip. Version bumps follow [Semantic Versioning](https://semver.org/): every major, minor and patch increment needs a changelog entry, a local `tools/build_releases.sh` build, and artifact/checksum verification before tagging. Unversioned development tracks do not receive a version until their scope enters a release. See [`docs/process/RELEASING.md`](docs/process/RELEASING.md) and [`README.md`](README.md) for commands.
|
||||||
|
|
||||||
|
## Gap Analysis
|
||||||
|
|
||||||
|
**Published baseline:** v0.9.8 (2026-11-04) — three playable venues, tutorial/campaign/checkpoint
|
||||||
|
resume, the access/radio/escalation loop, shift review, the 12-character Blender library, 277
|
||||||
|
Godot + 162 Python tests, a 21/21 screen-design judge and Compatibility/Web/Desktop HQ builds.
|
||||||
|
|
||||||
|
**Current source:** 0.9.8. The 0.10.0-rc.1 package built on 2026-11-03 is stale and is superseded
|
||||||
|
by the patch sequence below; it is not a published release.
|
||||||
|
|
||||||
|
| Area | Remaining gap | Milestone |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Character base | Quaternius arm-down skin export, rest-relative pose composition, face/silhouette acceptance | 0.9.9 |
|
||||||
|
| Character roster | 12-role mapping, modular outfits, gear fit, AO/texels, budget evidence | 0.9.10 |
|
||||||
|
| Venue and asset polish | Ranked prop/foliage/lighting/set-dressing fixes, collider verification | 0.9.11 |
|
||||||
|
| Performance and Web | Frame/memory/load evidence after the content changes, LOD/impostor verification | 0.9.12 |
|
||||||
|
| Onboarding and balance | External first-time-player evidence, balance sweeps/tuning, content lock | 0.10.0 |
|
||||||
|
| Accessibility and localization | Acceptance pass, caption coverage, pseudo-locale/length checks | 0.9.12 / 0.10.0 |
|
||||||
|
| QA and release engineering | Full smoke matrix, clean build/checksum verification, target-matrix launches | 0.10.0 |
|
||||||
|
| Legal, signing, storefront | macOS signing/notarization, AI-provider rights, storefront/rating approval, privacy sign-off | 0.10.0 / 0.12.0 |
|
||||||
|
| Systems and content depth | Live incident replay, fourth venue, localization foundation | 0.11.0 |
|
||||||
|
| Distribution | Signed storefront builds, frozen save contract, launch languages, hardware matrix | 0.12.0 |
|
||||||
|
| Stable release | Content complete, accessibility audit, release candidates, 1.0.0 decision | 0.13.0 / 1.0.0 |
|
||||||
|
| Future | More venues/seasonal content, image-to-mesh props, other deferred ideas | Unscheduled |
|
||||||
|
|
||||||
|
The 0.9.3 UI, 0.9.4 animation, 0.9.5 texture, 0.9.6 integration, 0.9.7 character development and
|
||||||
|
0.9.8 deformation fixes are complete in [`DONE.md`](DONE.md); they are not remaining gaps. The
|
||||||
|
2026-11-01 documentation audit is also closed.
|
||||||
|
|
||||||
|
## Release Roadmap
|
||||||
|
|
||||||
|
Every version below follows the release procedure in `AGENTS.md`. Patch versions contain fixes and
|
||||||
|
polish; minor versions add user-facing features; the major version is the stable release with a
|
||||||
|
compatibility promise. Each version's executable checklist is in [`TODO.md`](TODO.md).
|
||||||
|
|
||||||
|
### Roadmap to 0.10.0
|
||||||
|
|
||||||
|
The goal of this line is to finish the character and venue work and clear every public-release
|
||||||
|
gate. The character track is versioned rather than unversioned so a blocked rig cannot hold the
|
||||||
|
whole release.
|
||||||
|
|
||||||
|
| Version | Type | Scope | Exit criterion |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 0.9.9 | patch | Quaternius pilot: correct skin export, rest-relative pose math, Idle/Walk verification, owner face/silhouette gate, one-role (or crowd-only) rollout | A Quaternius NPC renders and animates correctly and ships behind a tested procedural fallback |
|
||||||
|
| 0.9.10 | patch | 12-role roster, modular outfits, five slots, AO/texels, gear fit, 12×6 baseline | The full roster passes contract, gear, budget and owner-baseline gates |
|
||||||
|
| 0.9.11 | patch | Scheduled 3D review fixes: props/foliage, gear silhouette, venue shape language, lighting, set dressing, colliders | Every scheduled P1/P2 item is fixed or accepted with a measurement |
|
||||||
|
| 0.9.12 | patch | Performance/Web/LOD/memory verification plus accessibility and pseudo-locale checks | No regression against the pre-character baselines |
|
||||||
|
| 0.10.0 | minor | Public readiness: external playtests, balance acceptance, legal/storefront/signing decisions, platform matrix, docs and picture lock | 0.10.0 is content-locked, externally played, legally reviewed, documented and reproducibly built |
|
||||||
|
|
||||||
|
### Roadmap to 0.11.0
|
||||||
|
|
||||||
|
This line turns a stable 0.10.x into a deeper game: the incident timeline becomes a live replay, a
|
||||||
|
fourth venue enters the campaign, and the text catalogue becomes a real localization pipeline.
|
||||||
|
|
||||||
|
| Version | Type | Scope | Exit criterion |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 0.10.1 | patch | Onboarding and accessibility issues deferred from the 0.10.0 playtests | First-hour and accessibility defects closed |
|
||||||
|
| 0.10.2 | patch | Balance/fairness sweeps, review-text and difficulty-progression tuning | Every balance-acceptance cell is in target or explicitly accepted |
|
||||||
|
| 0.10.3 | patch | Save/checkpoint edge cases, gamepad/remap, pause/resume, small quality-of-life fixes | No known P1 stability defect remains |
|
||||||
|
| 0.11.0 | minor | Live body-camera replay, fourth venue (candidate: TCL Chinese Theatre forecourt), localization foundation with one secondary language | The new systems ship without regressing performance, accessibility or balance |
|
||||||
|
|
||||||
|
### Roadmap to 1.0.0
|
||||||
|
|
||||||
|
This line is about distribution, contracts and completeness: signed builds on the launch stores, a
|
||||||
|
frozen save format, finished content and release candidates.
|
||||||
|
|
||||||
|
| Version | Type | Scope | Exit criterion |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 0.11.1 | patch | Replay/venue/localization fixes from wider play | No P1 defect in the 0.11.0 feature set |
|
||||||
|
| 0.11.2 | patch | New-venue balance, campaign pacing and content readability | The 0.11.x line is stable enough to freeze its contracts |
|
||||||
|
| 0.12.0 | minor | macOS signing/notarization, storefront packages/metadata/ratings, save-format v2 freeze, hardware matrix, launch languages | Signed, storefront-ready builds exist on every launch platform |
|
||||||
|
| 0.12.1 | patch | Signing, installer, metadata and save-migration fixes from storefront dry runs | Every storefront build installs, launches and migrates cleanly |
|
||||||
|
| 0.13.0 | minor | Content complete: all planned venues/events/dialogue, audio decision, final tutorial, accessibility audit, balance freeze | All planned content is implemented and frozen |
|
||||||
|
| 0.13.1 | patch | Release candidate 1: full smoke/performance/save/accessibility matrix | A candidate passes every gate except final approval |
|
||||||
|
| 0.13.2 | patch | Release candidate 2: verify fixes, freeze release notes/credits/privacy/known limitations | The final candidate is reproducible and documented |
|
||||||
|
| 1.0.0 | major | Stable release: legal/storefront/rating approval, hardware/accessibility/localization sign-off, no P0/P1, publish on every platform | 1.0.0 is published with verified checksums and no open blocker |
|
||||||
|
|
||||||
|
## Roadmap Dependencies and Risks
|
||||||
|
|
||||||
|
- Content volume is the largest schedule risk; tutorial and campaign work must not outrun the
|
||||||
|
event/dialogue matrix.
|
||||||
|
- The vision judge is a dev-time aid with an external key and budget; CI must never make it a hard
|
||||||
|
gate.
|
||||||
|
- Godot engine changes can alter lighting and imports; do not combine an engine baseline move with
|
||||||
|
a content or feature milestone.
|
||||||
|
- Signed macOS builds, AI provenance and storefront approval are release blockers, not polish.
|
||||||
|
- The character pipeline is the current critical path. The rig/export fix must be proven on one
|
||||||
|
variant before the roster rollout; otherwise 0.9.10 multiplies a defect.
|
||||||
|
- Photo-derived map assets add a provenance risk: downloaded or user-supplied photos can carry
|
||||||
|
unclear licences, identifiable people, plates and property restrictions. No photo- or
|
||||||
|
splat-derived asset ships without a completed sidecar, consent/licence review and redaction.
|
||||||
|
- Gaussian-splat training is GPU/disk-heavy and the toolchain churns; keep it offline,
|
||||||
|
version-pinned and outside CI, and never make a runtime splat renderer a release dependency.
|
||||||
|
- The Blender skill pack is local, unversioned guidance; it can drift from the project contract or
|
||||||
|
assume Blender MCP. Re-verify every adopted technique with `inspect`/`audit`/`fit` and never make
|
||||||
|
a skill, asset pack or tool version a build or CI dependency.
|
||||||
|
- The 3D re-evaluation can expand without bound. Cap it with the scorecard ranking: P0/P1 only, one
|
||||||
|
asset family per commit, and an explicit accept for everything else.
|
||||||
|
- Keep the de-escalation-first rules and rare-emergency design unchanged while adding progression,
|
||||||
|
difficulty and feedback.
|
||||||
|
|
||||||
## Design Direction
|
## Design Direction
|
||||||
|
|
||||||
@@ -206,4 +377,5 @@ The game should feel like a tense workplace simulation with occasional crisis mo
|
|||||||
|
|
||||||
- A rare Bob Dobbs cameo (Easter-egg appearance; placement note in `MEMORY.md`).
|
- A rare Bob Dobbs cameo (Easter-egg appearance; placement note in `MEMORY.md`).
|
||||||
- Specific unusual NPC behaviors, such as slapping their own face, using hands as scissors, or interacting with props unexpectedly.
|
- Specific unusual NPC behaviors, such as slapping their own face, using hands as scissors, or interacting with props unexpectedly.
|
||||||
- Live 3D body-camera replay; additional venues or seasonal events; real voice/dialogue audio; an image-to-mesh prop pipeline.
|
- A fifth venue or seasonal events after the 0.11.0 fourth venue proves the venue pipeline.
|
||||||
|
- Real voice/dialogue audio if the 0.13.0 audio decision does not fund it; an image-to-mesh prop pipeline remains unscheduled.
|
||||||
@@ -14,7 +14,7 @@ Player data is written only to Godot's local `user://` directory:
|
|||||||
|
|
||||||
Those files stay on the player's machine unless the player copies them. Deleting
|
Those files stay on the player's machine unless the player copies them. Deleting
|
||||||
the files (or the `Gig Line` user directory) resets the profile. See
|
the files (or the `Gig Line` user directory) resets the profile. See
|
||||||
[`docs/getting-started.md`](docs/getting-started.md#save-data-and-migration) for
|
[`docs/process/getting-started.md`](docs/process/getting-started.md#save-data) for
|
||||||
locations, migration and rollback instructions.
|
locations, migration and rollback instructions.
|
||||||
|
|
||||||
The repository's development tools can call OpenRouter when a developer supplies
|
The repository's development tools can call OpenRouter when a developer supplies
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ The central design goal is simple:
|
|||||||
|
|
||||||
## Development Priorities
|
## Development Priorities
|
||||||
|
|
||||||
The active planning order lives in [`TODO.md`](TODO.md) and [`AGENTS.md`](AGENTS.md):
|
The active planning order lives in [`PLAN.md`](PLAN.md) (gap analysis and release roadmap), [`TODO.md`](TODO.md) (executable checklist) and [`AGENTS.md`](AGENTS.md):
|
||||||
|
|
||||||
1. **3D model and local map re-evaluation** — score every shipped asset, then evaluate licensed OpenStreetMap/3D data, reference-derived photoreal facades, AI-assisted composition and a Gaussian-splatting development evaluation.
|
1. **`0.9.9`–`0.9.12` patches** — finish the Quaternius NPC base on the accepted 62-joint runtime, roll it out to the 12 roles, close the scheduled venue/prop/lighting polish, then verify performance, Web and accessibility.
|
||||||
2. **Character development** — crowd, age, build, hair and outfit variety on the owned procedural library, keeping the frozen NPC contract. Source evaluation and the licence decision are in [`docs/npc-model-sourcing.md`](docs/npc-model-sourcing.md).
|
2. **`0.10.0` minor** — public readiness: external playtests, balance acceptance, legal/storefront/signing decisions, the platform matrix and the documentation/picture lock.
|
||||||
3. **Versioned release hardening** — the 0.10.0 release candidate and later semantic versions follow the unversioned development tracks.
|
3. **`0.10.x` → `0.11.0`** — live incident replay, a fourth venue and the localization foundation.
|
||||||
|
4. **`0.12.0` → `1.0.0`** — signed storefront builds, a frozen save contract, content complete, release candidates and the stable release.
|
||||||
|
|
||||||
Versions are assigned only when a track's scope is accepted into a release. Every major, minor and patch version requires a changelog entry, a local release build and artifact verification before tagging.
|
Versions are assigned only when a track's scope is accepted into a release. Every major, minor and patch version requires a changelog entry, a local release build and artifact verification before tagging.
|
||||||
|
|
||||||
@@ -33,23 +34,25 @@ Versions are assigned only when a track's scope is accepted into a release. Ever
|
|||||||
> Downloads are public (no sign-in required) since the host's instance-wide
|
> Downloads are public (no sign-in required) since the host's instance-wide
|
||||||
> `REQUIRE_SIGNIN_VIEW` was disabled on 2026-10-31.
|
> `REQUIRE_SIGNIN_VIEW` was disabled on 2026-10-31.
|
||||||
>
|
>
|
||||||
> **Latest published: v0.9.8** — the character-development patch: the
|
> **Latest published: v0.9.9** — the character-roster patch: all twelve NPCs now
|
||||||
|
> use the CC0 Quaternius base with the five tint slots, role gear and baked maps.
|
||||||
|
> Superseded: v0.9.8, the character-development patch: the
|
||||||
> 12-character library, realistic face pass, four crowd-variety variants and the
|
> 12-character library, realistic face pass, four crowd-variety variants and the
|
||||||
> wrist/hip/knee deformation fixes. Previous 0.9.x patches added the
|
> wrist/hip/knee deformation fixes. Previous 0.9.x patches added the
|
||||||
> Hollywood/Joke Shop maps, UI/accessibility polish, NPC visual optimization,
|
> Hollywood/Joke Shop maps, UI/accessibility polish, NPC visual optimization,
|
||||||
> texture/material refinement and integration checkpoint.
|
> texture/material refinement and integration checkpoint.
|
||||||
>
|
>
|
||||||
> **Current source: v0.9.8** — tagged from the same commit. The 0.10.0
|
> **Current source: v0.9.8** — tagged from the same commit. The 0.10.0
|
||||||
> development track remains gated on the NPC overhaul, MakeHuman/local-map work
|
> development track remains gated on the Quaternius NPC rollout, local-map work
|
||||||
> and release approvals.
|
> and release approvals.
|
||||||
> Releases are built automatically when a `vX.Y.Z` tag is pushed
|
> Releases are built automatically when a `vX.Y.Z` tag is pushed
|
||||||
> (see [`docs/RELEASING.md`](docs/RELEASING.md)); manual builds use
|
> (see [`docs/process/RELEASING.md`](docs/process/RELEASING.md)); manual builds use
|
||||||
> `./tools/build_releases.sh`. Installer/AppImage packaging runs in the same pipeline
|
> `./tools/build_releases.sh`. Installer/AppImage packaging runs in the same pipeline
|
||||||
> (NSIS + appimagetool) and uploads with the portable binaries.
|
> (NSIS + appimagetool) and uploads with the portable binaries.
|
||||||
>
|
>
|
||||||
> macOS builds are unsigned: right-click → Open, or clear the quarantine with
|
> macOS builds are unsigned: right-click → Open, or clear the quarantine with
|
||||||
> `xattr -dr com.apple.quarantine gig-line-macos.zip`. Build instructions and
|
> `xattr -dr com.apple.quarantine gig-line-macos.zip`. Build instructions and
|
||||||
> the release pipeline live in [`docs/RELEASING.md`](docs/RELEASING.md).
|
> the release pipeline live in [`docs/process/RELEASING.md`](docs/process/RELEASING.md).
|
||||||
|
|
||||||
If you are here to develop or test locally instead of downloading, jump to
|
If you are here to develop or test locally instead of downloading, jump to
|
||||||
[Setup and Run](#setup-and-run) below.
|
[Setup and Run](#setup-and-run) below.
|
||||||
@@ -95,19 +98,21 @@ Every capture is rendered from the current build by [`tools/check_screenshots.sh
|
|||||||
|
|
||||||
### 3D asset progress
|
### 3D asset progress
|
||||||
|
|
||||||
The character, gear and prop libraries are authored procedurally in Blender and audited before use;
|
The character roster is built from the CC0 Quaternius bases (ADR-0017/ADR-0018) and audited
|
||||||
the sheets below track their visual progress.
|
before use; the procedural library and the MakeHuman head stay as the tested fallback. The
|
||||||
|
sheets below show the
|
||||||
|
current library and will be replaced after the 12 × 6 baseline review.
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
|  | **Character library.** Eight skinned variants (4.5–5.5k triangles each) with five tint slots, attach-point gear and baked maps. |
|
|  | **Character library.** Twelve role-dressed variants (4.5–6.4k triangles each) on three CC0 Quaternius bases, with five tint slots, attach-point gear and baked maps. |
|
||||||
|  | **Street and venue props.** Twenty library props with colliders, navigation avoidance and colour atlases. |
|
|  | **Street and venue props.** Twenty library props with colliders, navigation avoidance and colour atlases. |
|
||||||
|  | **Neutral baseline.** 8 characters × 6 views (front, three-quarter, profile, back, full body, crowd) used for the 0.9.4 pass and the current re-evaluation. |
|
|  | **Neutral baseline.** 8 characters × 6 views (front, three-quarter, profile, back, full body, crowd) used for the 0.9.4 pass and the current re-evaluation. |
|
||||||
|  | **Texture refinement.** 128 → 256 px NPC maps and a 4× fabric weave, shown before/after on the same camera. |
|
|  | **Texture refinement.** 128 → 256 px NPC maps and a 4× fabric weave, shown before/after on the same camera. |
|
||||||
|  | **Crowd variety prototypes.** Four approved looks (bun/slim, bald/broad, coat/umbrella, hood/cup) queued for the roster build. |
|
|  | **Crowd variety prototypes.** Four approved looks (bun/slim, bald/broad, coat/umbrella, hood/cup) queued for the roster build. |
|
||||||
|
|
||||||
More sheets and the review criteria are in [`docs/blender_previews/`](docs/blender_previews/README.md)
|
More sheets and the review criteria are in [`docs/blender_previews/`](docs/blender_previews/README.md)
|
||||||
and [`docs/3d-model-review.md`](docs/3d-model-review.md).
|
and [`docs/assets/3d-model-review.md`](docs/assets/3d-model-review.md).
|
||||||
|
|
||||||
## Game Overview
|
## Game Overview
|
||||||
|
|
||||||
@@ -117,7 +122,7 @@ tickets or credentials, and escalate only when necessary. The game rewards calm
|
|||||||
resolution over force. The venue menu splits Hollywood Boulevard into Day and
|
resolution over force. The venue menu splits Hollywood Boulevard into Day and
|
||||||
Night rows; the full mechanics — the three venues, the six-level
|
Night rows; the full mechanics — the three venues, the six-level
|
||||||
escalation model, and the core systems — are in
|
escalation model, and the core systems — are in
|
||||||
[`docs/gameplay.md`](docs/gameplay.md); the design rationale lives in
|
[`docs/design/gameplay.md`](docs/design/gameplay.md); the design rationale lives in
|
||||||
[`PLAN.md`](PLAN.md).
|
[`PLAN.md`](PLAN.md).
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
@@ -125,13 +130,13 @@ escalation model, and the core systems — are in
|
|||||||
A venue-driven simulation: shared systems (movement, perception, interaction,
|
A venue-driven simulation: shared systems (movement, perception, interaction,
|
||||||
access verification, escalation, radio, crowd, reputation, evidence, shift
|
access verification, escalation, radio, crowd, reputation, evidence, shift
|
||||||
review) driven by per-venue scenario data, on Godot 4 + GDScript. The full
|
review) driven by per-venue scenario data, on Godot 4 + GDScript. The full
|
||||||
arc42-style document is [`docs/architecture.md`](docs/architecture.md);
|
arc42-style document is [`docs/project/architecture.md`](docs/project/architecture.md);
|
||||||
decisions are recorded as ADRs in [`docs/adr/`](docs/adr/).
|
decisions are recorded as ADRs in [`docs/adr/`](docs/adr).
|
||||||
|
|
||||||
## Tech Stack
|
## Tech Stack
|
||||||
|
|
||||||
- **Engine:** Godot 4.7.2 · **Language:** GDScript
|
- **Engine:** Godot 4.7.2 · **Language:** GDScript
|
||||||
- **NPCs:** Blender-authored skinned library (`assets/models/blender/`) with procedural fallbacks; lightweight FSMs on `NpcProfile`
|
- **NPCs:** CC0 Quaternius skinned library (`assets/models/blender/`, ADR-0018) with a tested procedural fallback; lightweight FSMs on `NpcProfile`
|
||||||
- **World:** procedural `WorldBuilder` + generated prop models
|
- **World:** procedural `WorldBuilder` + generated prop models
|
||||||
- **Art:** v2 skyline/surface textures in `assets/textures/ai/game_ready/v2/picks/`; UI/scene art in `assets/images/`
|
- **Art:** v2 skyline/surface textures in `assets/textures/ai/game_ready/v2/picks/`; UI/scene art in `assets/images/`
|
||||||
- **Asset tooling:** `asset_pipeline.py`, `model_pipeline.py`, `npc_pipeline.py`, `blender_assets.py`, `scene_concepts.py`, `screen_designs.py`, `check_screenshots.sh`
|
- **Asset tooling:** `asset_pipeline.py`, `model_pipeline.py`, `npc_pipeline.py`, `blender_assets.py`, `scene_concepts.py`, `screen_designs.py`, `check_screenshots.sh`
|
||||||
@@ -139,7 +144,7 @@ decisions are recorded as ADRs in [`docs/adr/`](docs/adr/).
|
|||||||
- **Targets:** Windows, Linux, macOS, Web
|
- **Targets:** Windows, Linux, macOS, Web
|
||||||
|
|
||||||
The asset pipelines, model tools, and screenshot gates are documented in
|
The asset pipelines, model tools, and screenshot gates are documented in
|
||||||
[`docs/asset-tooling.md`](docs/asset-tooling.md).
|
[`docs/assets/asset-tooling.md`](docs/assets/asset-tooling.md).
|
||||||
|
|
||||||
## Setup and Run
|
## Setup and Run
|
||||||
|
|
||||||
@@ -152,35 +157,36 @@ godot --headless --path . --script res://src/test/test_runner.gd # run all tes
|
|||||||
```
|
```
|
||||||
|
|
||||||
Full setup, every run/test/smoke command, and the controls table are in
|
Full setup, every run/test/smoke command, and the controls table are in
|
||||||
[`docs/getting-started.md`](docs/getting-started.md).
|
[`docs/process/getting-started.md`](docs/process/getting-started.md).
|
||||||
|
|
||||||
## Project Documentation
|
## Project Documentation
|
||||||
|
|
||||||
- [`PLAN.md`](PLAN.md) — Game design plan, development priorities and scenario details.
|
- [`PLAN.md`](PLAN.md) — Game design plan, development priorities and scenario details.
|
||||||
- [`TODO.md`](TODO.md) — Priority-ordered tasks: character and local-map development, release milestones, and future work.
|
- [`TODO.md`](TODO.md) — Priority-ordered tasks: character and local-map development, release milestones, and future work.
|
||||||
- [`docs/README.md`](docs/README.md) — Documentation index, current priorities and visual previews.
|
- [`docs/README.md`](docs/README.md) — Documentation index, current priorities and visual previews.
|
||||||
- [`docs/npc-model-sourcing.md`](docs/npc-model-sourcing.md) — Character-source evaluation, licence rules and the character-development plan.
|
- [`docs/assets/npc-model-sourcing.md`](docs/assets/npc-model-sourcing.md) — Character-source evaluation, licence rules and the character-development plan.
|
||||||
|
- [`docs/assets/makehuman-head-review.md`](docs/assets/makehuman-head-review.md) — Local MakeHuman head prototype, provenance and review verdict.
|
||||||
- [`AGENTS.md`](AGENTS.md) — Development, commit, build and collaboration workflow.
|
- [`AGENTS.md`](AGENTS.md) — Development, commit, build and collaboration workflow.
|
||||||
- [`DONE.md`](DONE.md) — Completed task sections.
|
- [`DONE.md`](DONE.md) — Completed task sections.
|
||||||
- [`MEMORY.md`](MEMORY.md) — Persistent session notes.
|
- [`MEMORY.md`](MEMORY.md) — Persistent session notes.
|
||||||
- [`CHANGELOG.md`](CHANGELOG.md) — User-facing changes by version.
|
- [`CHANGELOG.md`](CHANGELOG.md) — User-facing changes by version.
|
||||||
- [`docs/architecture.md`](docs/architecture.md) — arc42-style architecture documentation.
|
- [`docs/project/architecture.md`](docs/project/architecture.md) — arc42-style architecture documentation.
|
||||||
- [`docs/gameplay.md`](docs/gameplay.md) — Gameplay systems, venues, and the escalation model.
|
- [`docs/design/gameplay.md`](docs/design/gameplay.md) — Gameplay systems, venues, and the escalation model.
|
||||||
- [`docs/venues.md`](docs/venues.md) — Real-site references, game mapping and limitations for Hollywood, the Joke Shop and the TV Studio.
|
- [`docs/design/venues.md`](docs/design/venues.md) — Real-site references, game mapping and limitations for Hollywood, the Joke Shop and the TV Studio.
|
||||||
- [`docs/asset-tooling.md`](docs/asset-tooling.md) — Asset pipelines, model tools, and screenshot gates.
|
- [`docs/assets/asset-tooling.md`](docs/assets/asset-tooling.md) — Asset pipelines, model tools, and screenshot gates.
|
||||||
- [`tools/README.md`](tools/README.md) — Tool inventory, categories, test commands and AI-skill evaluation.
|
- [`tools/README.md`](tools/README.md) — Tool inventory, categories, test commands and AI-skill evaluation.
|
||||||
- [`.agents/skills/gig-line-blender-asset-contract`](.agents/skills/gig-line-blender-asset-contract/SKILL.md) — tracked AI skill for Blender/NPC/gear asset work.
|
- [`.agents/skills/gig-line-blender-asset-contract`](.agents/skills/gig-line-blender-asset-contract/SKILL.md) — tracked AI skill for Blender/NPC/gear asset work.
|
||||||
- [`.agents/skills/gig-line-release-qa`](.agents/skills/gig-line-release-qa/SKILL.md) — tracked AI skill for release and visual-QA work.
|
- [`.agents/skills/gig-line-release-qa`](.agents/skills/gig-line-release-qa/SKILL.md) — tracked AI skill for release and visual-QA work.
|
||||||
- [`docs/getting-started.md`](docs/getting-started.md) — Setup, run/test commands, and controls.
|
- [`docs/process/getting-started.md`](docs/process/getting-started.md) — Setup, run/test commands, and controls.
|
||||||
- [`docs/development-status.md`](docs/development-status.md) — Implemented features and what's next.
|
- [`docs/project/development-status.md`](docs/project/development-status.md) — Implemented features and what's next.
|
||||||
- [`docs/accessibility.md`](docs/accessibility.md) — Accessibility features, known gaps and statement.
|
- [`docs/design/accessibility.md`](docs/design/accessibility.md) — Accessibility features, known gaps and statement.
|
||||||
- [`docs/known-limitations.md`](docs/known-limitations.md) — Release-candidate blockers and accepted limitations.
|
- [`docs/design/known-limitations.md`](docs/design/known-limitations.md) — Release-candidate blockers and accepted limitations.
|
||||||
- [`docs/release-qa.md`](docs/release-qa.md) — Manual smoke checklist and release-candidate balance protocol.
|
- [`docs/process/release-qa.md`](docs/process/release-qa.md) — Manual smoke checklist and release-candidate balance protocol.
|
||||||
- [`CREDITS.md`](CREDITS.md) — Credits, AI/reference provenance and licensing notes.
|
- [`CREDITS.md`](CREDITS.md) — Credits, AI/reference provenance and licensing notes.
|
||||||
- [`PRIVACY.md`](PRIVACY.md) — Local-only data, save files and development API use.
|
- [`PRIVACY.md`](PRIVACY.md) — Local-only data, save files and development API use.
|
||||||
- [`docs/blender-assets.md`](docs/blender-assets.md) — Blender asset library: characters, gear, props, attach points.
|
- [`docs/assets/blender-assets.md`](docs/assets/blender-assets.md) — Blender asset library: characters, gear, props, attach points.
|
||||||
- [`docs/npc-visual-review.md`](docs/npc-visual-review.md) — 0.9.4 NPC baseline, acceptance criteria and ranked visual gaps; 0.9.5 texture comparison is in [`docs/blender_previews/sheet_texture_refinement_0.9.5.jpg`](docs/blender_previews/sheet_texture_refinement_0.9.5.jpg).
|
- [`docs/assets/npc-model-sourcing.md`](docs/assets/npc-model-sourcing.md) — character sources, the shipped roster table and the build steps; 0.9.5 texture comparison is in [`docs/blender_previews/sheet_texture_refinement_0.9.5.jpg`](docs/blender_previews/sheet_texture_refinement_0.9.5.jpg).
|
||||||
- [`docs/adr/`](docs/adr/) — Architecture Decision Records.
|
- [`docs/adr/`](docs/adr) — Architecture Decision Records.
|
||||||
|
|
||||||
## Development Status
|
## Development Status
|
||||||
|
|
||||||
@@ -189,12 +195,12 @@ v0.9.8 is the current source version: the character-development patch with the
|
|||||||
and save-migration/release hardening. It sits on the 0.9.6 integration
|
and save-migration/release hardening. It sits on the 0.9.6 integration
|
||||||
checkpoint, 0.9.5 texture refinement, 0.9.4 NPC visual optimization, 0.9.3
|
checkpoint, 0.9.5 texture refinement, 0.9.4 NPC visual optimization, 0.9.3
|
||||||
UI/accessibility polish, 0.9.2 Hollywood/Joke Shop maps and the 0.9.x engine
|
UI/accessibility polish, 0.9.2 Hollywood/Joke Shop maps and the 0.9.x engine
|
||||||
baseline. The active priorities are the Blender NPC head/face/hand overhaul,
|
baseline. The active work is the `0.9.9`–`0.9.12` patch line (Quaternius NPC
|
||||||
MakeHuman body intake and the 3D model/map re-evaluation; the 0.10.0 release
|
base, roster, venue/asset polish, performance) followed by the `0.10.0`
|
||||||
candidate follows those tracks. See
|
public-readiness minor. See
|
||||||
[`docs/development-status.md`](docs/development-status.md) for the implemented list
|
[`docs/project/development-status.md`](docs/project/development-status.md) for the implemented list
|
||||||
and [`TODO.md`](TODO.md) for the priority-ordered roadmap. Manual verification uses
|
and [`TODO.md`](TODO.md) for the priority-ordered roadmap. Manual verification uses
|
||||||
[`docs/release-qa.md`](docs/release-qa.md).
|
[`docs/process/release-qa.md`](docs/process/release-qa.md).
|
||||||
|
|
||||||
## Credits, Privacy and Accessibility
|
## Credits, Privacy and Accessibility
|
||||||
|
|
||||||
@@ -203,8 +209,8 @@ network service, and saves stay in Godot's local `user://` folder. The
|
|||||||
body-camera overlay is simulated. Asset provenance, AI-assisted image usage and
|
body-camera overlay is simulated. Asset provenance, AI-assisted image usage and
|
||||||
credits are recorded in [`CREDITS.md`](CREDITS.md); the local-data policy is in
|
credits are recorded in [`CREDITS.md`](CREDITS.md); the local-data policy is in
|
||||||
[`PRIVACY.md`](PRIVACY.md); accessibility features and gaps are in
|
[`PRIVACY.md`](PRIVACY.md); accessibility features and gaps are in
|
||||||
[`docs/accessibility.md`](docs/accessibility.md); and release-candidate blockers
|
[`docs/design/accessibility.md`](docs/design/accessibility.md); and release-candidate blockers
|
||||||
are listed in [`docs/known-limitations.md`](docs/known-limitations.md).
|
are listed in [`docs/design/known-limitations.md`](docs/design/known-limitations.md).
|
||||||
|
|
||||||
## Development Workflow
|
## Development Workflow
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,12 @@
|
|||||||
"attach": "back",
|
"attach": "back",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.161,
|
0.15,
|
||||||
0.296,
|
0.296,
|
||||||
0.212
|
0.172
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.161,
|
-0.15,
|
||||||
-0.12,
|
-0.12,
|
||||||
-0.319
|
-0.319
|
||||||
]
|
]
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
],
|
],
|
||||||
"path": "assets/models/blender/npc_gear/backpack.glb",
|
"path": "assets/models/blender/npc_gear/backpack.glb",
|
||||||
"triangles": 380,
|
"triangles": 380,
|
||||||
"vertices": 408
|
"vertices": 410
|
||||||
},
|
},
|
||||||
"bench": {
|
"bench": {
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
@@ -98,14 +98,14 @@
|
|||||||
"attach": "hand",
|
"attach": "hand",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.106,
|
0.065,
|
||||||
0.376,
|
0.06,
|
||||||
0.143
|
0.143
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.106,
|
-0.065,
|
||||||
-0.053,
|
-0.053,
|
||||||
-0.055
|
0.005
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc_gear",
|
"category": "npc_gear",
|
||||||
@@ -114,42 +114,20 @@
|
|||||||
"lens"
|
"lens"
|
||||||
],
|
],
|
||||||
"path": "assets/models/blender/npc_gear/camera.glb",
|
"path": "assets/models/blender/npc_gear/camera.glb",
|
||||||
"triangles": 318,
|
"triangles": 312,
|
||||||
"vertices": 406
|
"vertices": 422
|
||||||
},
|
|
||||||
"cap": {
|
|
||||||
"attach": "head",
|
|
||||||
"bounds_godot": {
|
|
||||||
"max": [
|
|
||||||
0.168,
|
|
||||||
0.209,
|
|
||||||
0.258
|
|
||||||
],
|
|
||||||
"min": [
|
|
||||||
-0.168,
|
|
||||||
0.037,
|
|
||||||
-0.186
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"category": "npc_gear",
|
|
||||||
"materials": [
|
|
||||||
"plastic_black"
|
|
||||||
],
|
|
||||||
"path": "assets/models/blender/npc_gear/cap.glb",
|
|
||||||
"triangles": 328,
|
|
||||||
"vertices": 285
|
|
||||||
},
|
},
|
||||||
"clipboard": {
|
"clipboard": {
|
||||||
"attach": "hand",
|
"attach": "hand",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.115,
|
0.11,
|
||||||
0.05,
|
-0.07,
|
||||||
0.053
|
0.053
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.115,
|
-0.11,
|
||||||
-0.265,
|
-0.375,
|
||||||
0.036
|
0.036
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -166,12 +144,12 @@
|
|||||||
"crowd_barrier": {
|
"crowd_barrier": {
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
1.116,
|
1.12,
|
||||||
1.066,
|
1.07,
|
||||||
0.307
|
0.307
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-1.122,
|
-1.128,
|
||||||
-0.014,
|
-0.014,
|
||||||
-0.307
|
-0.307
|
||||||
]
|
]
|
||||||
@@ -264,14 +242,14 @@
|
|||||||
"attach": "head",
|
"attach": "head",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
|
0.166,
|
||||||
0.26,
|
0.26,
|
||||||
0.245,
|
0.166
|
||||||
0.26
|
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.26,
|
-0.166,
|
||||||
0.035,
|
0.125,
|
||||||
-0.351
|
-0.225
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc_gear",
|
"category": "npc_gear",
|
||||||
@@ -329,28 +307,6 @@
|
|||||||
"triangles": 268,
|
"triangles": 268,
|
||||||
"vertices": 400
|
"vertices": 400
|
||||||
},
|
},
|
||||||
"hood": {
|
|
||||||
"attach": "head",
|
|
||||||
"bounds_godot": {
|
|
||||||
"max": [
|
|
||||||
0.184,
|
|
||||||
0.236,
|
|
||||||
0.123
|
|
||||||
],
|
|
||||||
"min": [
|
|
||||||
-0.184,
|
|
||||||
-0.146,
|
|
||||||
-0.225
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"category": "npc_gear",
|
|
||||||
"materials": [
|
|
||||||
"plastic_grey"
|
|
||||||
],
|
|
||||||
"path": "assets/models/blender/npc_gear/hood.glb",
|
|
||||||
"triangles": 804,
|
|
||||||
"vertices": 649
|
|
||||||
},
|
|
||||||
"lanyard": {
|
"lanyard": {
|
||||||
"attach": "chest",
|
"attach": "chest",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
@@ -428,16 +384,17 @@
|
|||||||
"vertices": 648
|
"vertices": 648
|
||||||
},
|
},
|
||||||
"npc_casual": {
|
"npc_casual": {
|
||||||
|
"base": "hoodie",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.321,
|
0.262,
|
||||||
1.824,
|
1.866,
|
||||||
0.189
|
0.287
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.321,
|
-0.262,
|
||||||
0,
|
-0.004,
|
||||||
-0.178
|
-0.091
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
@@ -445,11 +402,13 @@
|
|||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Eyebrows",
|
||||||
|
"sclera",
|
||||||
"hair",
|
"hair",
|
||||||
"rubber"
|
"pants",
|
||||||
|
"mouth",
|
||||||
|
"pupil"
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_casual.glb",
|
"path": "assets/models/blender/npc/npc_casual.glb",
|
||||||
@@ -466,32 +425,36 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5034,
|
"triangles": 6242,
|
||||||
"vertices": 4607
|
"vertices": 13100
|
||||||
},
|
},
|
||||||
"npc_coat": {
|
"npc_coat": {
|
||||||
|
"base": "suit",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.332,
|
0.255,
|
||||||
1.824,
|
1.809,
|
||||||
0.189
|
0.279
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.332,
|
-0.255,
|
||||||
0,
|
-0.001,
|
||||||
-0.18
|
-0.083
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
"layer": "coat",
|
"layer": "coat",
|
||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
|
"Tie",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
"White",
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Eyebrows",
|
||||||
"hair",
|
"hair",
|
||||||
"rubber"
|
"sclera",
|
||||||
|
"pants",
|
||||||
|
"pupil"
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_coat.glb",
|
"path": "assets/models/blender/npc/npc_coat.glb",
|
||||||
@@ -507,20 +470,21 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 6046,
|
"triangles": 6582,
|
||||||
"vertices": 5645
|
"vertices": 13607
|
||||||
},
|
},
|
||||||
"npc_crowd_a": {
|
"npc_crowd_a": {
|
||||||
|
"base": "beach",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.288,
|
0.252,
|
||||||
1.825,
|
1.805,
|
||||||
0.189
|
0.277
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.288,
|
-0.252,
|
||||||
0,
|
-0.005,
|
||||||
-0.195
|
-0.088
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
@@ -528,11 +492,13 @@
|
|||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Eyebrows",
|
||||||
|
"sclera",
|
||||||
"hair",
|
"hair",
|
||||||
"rubber"
|
"Earrings",
|
||||||
|
"pants",
|
||||||
|
"pupil"
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_crowd_a.glb",
|
"path": "assets/models/blender/npc/npc_crowd_a.glb",
|
||||||
@@ -547,32 +513,38 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5284,
|
"triangles": 6602,
|
||||||
"vertices": 4908
|
"vertices": 13557
|
||||||
},
|
},
|
||||||
"npc_crowd_b": {
|
"npc_crowd_b": {
|
||||||
|
"base": "farmer",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.358,
|
0.256,
|
||||||
1.809,
|
1.81,
|
||||||
0.189
|
0.28
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.358,
|
-0.256,
|
||||||
0,
|
-0.0,
|
||||||
-0.155
|
-0.11
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
"layer": "none",
|
"layer": "none",
|
||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
|
"LightBlue",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
"Beige",
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Eyebrows",
|
||||||
"hair",
|
"Beige.001",
|
||||||
"rubber"
|
"Red",
|
||||||
|
"sclera",
|
||||||
|
"pants",
|
||||||
|
"pupil",
|
||||||
|
"hair"
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_crowd_b.glb",
|
"path": "assets/models/blender/npc/npc_crowd_b.glb",
|
||||||
@@ -587,32 +559,40 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 4812,
|
"triangles": 5512,
|
||||||
"vertices": 4550
|
"vertices": 11291
|
||||||
},
|
},
|
||||||
"npc_crowd_c": {
|
"npc_crowd_c": {
|
||||||
|
"base": "adventurer",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.332,
|
0.255,
|
||||||
1.824,
|
1.809,
|
||||||
0.189
|
0.279
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.332,
|
-0.255,
|
||||||
0,
|
-0.001,
|
||||||
-0.18
|
-0.256
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
"layer": "coat",
|
"layer": "coat",
|
||||||
"materials": [
|
"materials": [
|
||||||
|
"Brown",
|
||||||
|
"LightGreen",
|
||||||
|
"Gold",
|
||||||
|
"Green",
|
||||||
"skin",
|
"skin",
|
||||||
|
"Tie",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
"White",
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Eyebrows",
|
||||||
"hair",
|
"hair",
|
||||||
"rubber"
|
"sclera",
|
||||||
|
"pants",
|
||||||
|
"pupil"
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_crowd_c.glb",
|
"path": "assets/models/blender/npc/npc_crowd_c.glb",
|
||||||
@@ -627,20 +607,21 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5690,
|
"triangles": 9526,
|
||||||
"vertices": 5510
|
"vertices": 19501
|
||||||
},
|
},
|
||||||
"npc_crowd_d": {
|
"npc_crowd_d": {
|
||||||
|
"base": "worker",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.293,
|
0.262,
|
||||||
1.856,
|
1.866,
|
||||||
0.189
|
0.287
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.293,
|
-0.262,
|
||||||
0,
|
-0.004,
|
||||||
-0.225
|
-0.087
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
@@ -648,11 +629,15 @@
|
|||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Eyebrows",
|
||||||
|
"Moustache",
|
||||||
|
"pants",
|
||||||
|
"Brows",
|
||||||
|
"sclera",
|
||||||
"hair",
|
"hair",
|
||||||
"rubber"
|
"mouth",
|
||||||
|
"pupil"
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_crowd_d.glb",
|
"path": "assets/models/blender/npc/npc_crowd_d.glb",
|
||||||
@@ -667,32 +652,38 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5810,
|
"triangles": 6290,
|
||||||
"vertices": 5444
|
"vertices": 13188
|
||||||
},
|
},
|
||||||
"npc_dress": {
|
"npc_dress": {
|
||||||
|
"base": "king",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.288,
|
0.249,
|
||||||
1.825,
|
1.809,
|
||||||
0.208
|
0.269
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.288,
|
-0.249,
|
||||||
0,
|
-0.001,
|
||||||
-0.208
|
-0.083
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
"layer": "dress",
|
"layer": "dress",
|
||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
|
"Blue",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
"Beige",
|
||||||
|
"Metal_Dark",
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
|
||||||
"hair",
|
"hair",
|
||||||
"rubber"
|
"Gold",
|
||||||
|
"sclera",
|
||||||
|
"pants",
|
||||||
|
"Metal_Dark_legs",
|
||||||
|
"pupil"
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_dress.glb",
|
"path": "assets/models/blender/npc/npc_dress.glb",
|
||||||
@@ -706,20 +697,21 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5540,
|
"triangles": 11126,
|
||||||
"vertices": 5073
|
"vertices": 22516
|
||||||
},
|
},
|
||||||
"npc_firefighter": {
|
"npc_firefighter": {
|
||||||
|
"base": "worker",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.37,
|
0.262,
|
||||||
1.819,
|
1.866,
|
||||||
0.213
|
0.287
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.37,
|
-0.262,
|
||||||
0,
|
-0.004,
|
||||||
-0.213
|
-0.087
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
@@ -727,13 +719,15 @@
|
|||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Eyebrows",
|
||||||
|
"Moustache",
|
||||||
|
"pants",
|
||||||
|
"Brows",
|
||||||
|
"sclera",
|
||||||
"hair",
|
"hair",
|
||||||
"hivis",
|
"mouth",
|
||||||
"reflective",
|
"pupil"
|
||||||
"rubber"
|
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_firefighter.glb",
|
"path": "assets/models/blender/npc/npc_firefighter.glb",
|
||||||
@@ -747,20 +741,21 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5888,
|
"triangles": 6290,
|
||||||
"vertices": 5785
|
"vertices": 13188
|
||||||
},
|
},
|
||||||
"npc_guard": {
|
"npc_guard": {
|
||||||
|
"base": "worker",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.361,
|
0.262,
|
||||||
1.819,
|
1.866,
|
||||||
0.189
|
0.287
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.361,
|
-0.262,
|
||||||
0,
|
-0.004,
|
||||||
-0.172
|
-0.087
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
@@ -768,15 +763,15 @@
|
|||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Eyebrows",
|
||||||
|
"Moustache",
|
||||||
|
"pants",
|
||||||
|
"Brows",
|
||||||
|
"sclera",
|
||||||
"hair",
|
"hair",
|
||||||
"rubber",
|
"mouth",
|
||||||
"leather",
|
"pupil"
|
||||||
"steel",
|
|
||||||
"patch",
|
|
||||||
"plastic_black"
|
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_guard.glb",
|
"path": "assets/models/blender/npc/npc_guard.glb",
|
||||||
@@ -791,32 +786,38 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5670,
|
"triangles": 6290,
|
||||||
"vertices": 5671
|
"vertices": 13188
|
||||||
},
|
},
|
||||||
"npc_hoodie": {
|
"npc_hoodie": {
|
||||||
|
"base": "punk",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.326,
|
0.241,
|
||||||
1.856,
|
1.806,
|
||||||
0.189
|
0.263
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.326,
|
-0.241,
|
||||||
0,
|
-0.004,
|
||||||
-0.225
|
-0.147
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
"layer": "hood",
|
"layer": "hood",
|
||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
|
"White",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"sclera",
|
||||||
|
"Eyebrows",
|
||||||
|
"Red_Dark",
|
||||||
"hair",
|
"hair",
|
||||||
"rubber"
|
"Earrings",
|
||||||
|
"Skin_legs",
|
||||||
|
"pants",
|
||||||
|
"pupil"
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_hoodie.glb",
|
"path": "assets/models/blender/npc/npc_hoodie.glb",
|
||||||
@@ -832,20 +833,21 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5864,
|
"triangles": 5524,
|
||||||
"vertices": 5325
|
"vertices": 11257
|
||||||
},
|
},
|
||||||
"npc_jacket": {
|
"npc_jacket": {
|
||||||
|
"base": "casual_2",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.332,
|
0.255,
|
||||||
1.824,
|
1.809,
|
||||||
0.189
|
0.279
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.332,
|
-0.255,
|
||||||
0,
|
-0.001,
|
||||||
-0.178
|
-0.164
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
@@ -853,11 +855,13 @@
|
|||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Skin_Darker",
|
||||||
|
"Eyebrows",
|
||||||
"hair",
|
"hair",
|
||||||
"rubber"
|
"sclera",
|
||||||
|
"pants",
|
||||||
|
"pupil"
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_jacket.glb",
|
"path": "assets/models/blender/npc/npc_jacket.glb",
|
||||||
@@ -873,34 +877,38 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5432,
|
"triangles": 5800,
|
||||||
"vertices": 5225
|
"vertices": 11866
|
||||||
},
|
},
|
||||||
"npc_vest": {
|
"npc_vest": {
|
||||||
|
"base": "worker",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.321,
|
0.262,
|
||||||
1.819,
|
1.789,
|
||||||
0.189
|
0.287
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.321,
|
-0.262,
|
||||||
0,
|
-0.004,
|
||||||
-0.172
|
-0.083
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc",
|
"category": "npc",
|
||||||
"layer": "vest",
|
"layer": "vest",
|
||||||
"materials": [
|
"materials": [
|
||||||
"skin",
|
"skin",
|
||||||
|
"Worker_Yellow",
|
||||||
"cloth",
|
"cloth",
|
||||||
"pants",
|
|
||||||
"accessory",
|
"accessory",
|
||||||
"eye_white",
|
"Eyebrows",
|
||||||
|
"Moustache",
|
||||||
|
"pants",
|
||||||
|
"Brows",
|
||||||
|
"sclera",
|
||||||
"hair",
|
"hair",
|
||||||
"rubber",
|
"mouth",
|
||||||
"hivis",
|
"pupil"
|
||||||
"reflective"
|
|
||||||
],
|
],
|
||||||
"mesh_node": "npc_base",
|
"mesh_node": "npc_base",
|
||||||
"path": "assets/models/blender/npc/npc_vest.glb",
|
"path": "assets/models/blender/npc/npc_vest.glb",
|
||||||
@@ -914,8 +922,8 @@
|
|||||||
"accessory",
|
"accessory",
|
||||||
"hair"
|
"hair"
|
||||||
],
|
],
|
||||||
"triangles": 5532,
|
"triangles": 6290,
|
||||||
"vertices": 5195
|
"vertices": 13186
|
||||||
},
|
},
|
||||||
"palm_tree": {
|
"palm_tree": {
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
@@ -967,7 +975,7 @@
|
|||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.5,
|
0.5,
|
||||||
1.08,
|
1.118,
|
||||||
0.5
|
0.5
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
@@ -985,8 +993,8 @@
|
|||||||
],
|
],
|
||||||
"path": "assets/models/blender/props/planter_box.glb",
|
"path": "assets/models/blender/props/planter_box.glb",
|
||||||
"replaces": "generated/planter_box.glb",
|
"replaces": "generated/planter_box.glb",
|
||||||
"triangles": 1324,
|
"triangles": 818,
|
||||||
"vertices": 2780
|
"vertices": 1701
|
||||||
},
|
},
|
||||||
"protest_sign": {
|
"protest_sign": {
|
||||||
"attach": "hand",
|
"attach": "hand",
|
||||||
@@ -1041,14 +1049,14 @@
|
|||||||
"round_planter": {
|
"round_planter": {
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.432,
|
0.399,
|
||||||
1.12,
|
1.175,
|
||||||
0.36
|
0.36
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.36,
|
-0.36,
|
||||||
0,
|
0,
|
||||||
-0.363
|
-0.376
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "props",
|
"category": "props",
|
||||||
@@ -1058,8 +1066,8 @@
|
|||||||
"foliage_dark"
|
"foliage_dark"
|
||||||
],
|
],
|
||||||
"path": "assets/models/blender/props/round_planter.glb",
|
"path": "assets/models/blender/props/round_planter.glb",
|
||||||
"triangles": 1240,
|
"triangles": 808,
|
||||||
"vertices": 2418
|
"vertices": 1522
|
||||||
},
|
},
|
||||||
"scba_tank": {
|
"scba_tank": {
|
||||||
"attach": "back",
|
"attach": "back",
|
||||||
@@ -1213,14 +1221,14 @@
|
|||||||
"street_tree": {
|
"street_tree": {
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
1.179,
|
1.15,
|
||||||
3.62,
|
3.634,
|
||||||
1.102
|
1.053
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.941,
|
-1.041,
|
||||||
0,
|
0,
|
||||||
-1.082
|
-1.08
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "props",
|
"category": "props",
|
||||||
@@ -1232,21 +1240,21 @@
|
|||||||
],
|
],
|
||||||
"path": "assets/models/blender/props/street_tree.glb",
|
"path": "assets/models/blender/props/street_tree.glb",
|
||||||
"replaces": "WorldBuilder cone trees",
|
"replaces": "WorldBuilder cone trees",
|
||||||
"triangles": 2592,
|
"triangles": 1506,
|
||||||
"vertices": 5620
|
"vertices": 3330
|
||||||
},
|
},
|
||||||
"sunglasses": {
|
"sunglasses": {
|
||||||
"attach": "head",
|
"attach": "head",
|
||||||
"bounds_godot": {
|
"bounds_godot": {
|
||||||
"max": [
|
"max": [
|
||||||
0.101,
|
0.065,
|
||||||
0.059,
|
0.141,
|
||||||
0.158
|
0.101
|
||||||
],
|
],
|
||||||
"min": [
|
"min": [
|
||||||
-0.101,
|
-0.065,
|
||||||
0.011,
|
0.11,
|
||||||
0.003
|
0.002
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"category": "npc_gear",
|
"category": "npc_gear",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 52 KiB |
@@ -0,0 +1,33 @@
|
|||||||
|
# Quaternius build sources (CC0 1.0)
|
||||||
|
|
||||||
|
These are the **build inputs** for the shipped NPC roster, not runtime assets.
|
||||||
|
`blender_src/.gdignore` keeps Godot from importing this directory.
|
||||||
|
|
||||||
|
Source: Quaternius *Ultimate Modular Characters* and *Ultimate Modular Women*
|
||||||
|
(<https://quaternius.com/packs/ultimatemodularcharacters.html>), licence CC0 1.0,
|
||||||
|
attribution recorded in the repository `CREDITS.md`.
|
||||||
|
|
||||||
|
| File | SHA-256 | Bones | Meshes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `Casual.glb` | `bc2d84fba249ebaa0629cb9d133ad37234196e4b8004aa205a6397abed04e05c` | 62 | 4 skinned + Icosphere helper |
|
||||||
|
| `Casual_Hoodie.glb` | `f5b722199f7628b24550989af4230f65d5230727df9c326fd2b3e360effe5249` | 62 | 4 skinned + Icosphere helper |
|
||||||
|
| `Worker.glb` | `8d0f454336c2effc5c08f63a177af3a82d1a7af025ca9588b40e4c90c4703534` | 62 | 4 skinned + Icosphere helper |
|
||||||
|
|
||||||
|
Each file also carries 24 animation clips; the build exports **no** animation data, so
|
||||||
|
the shipped GLBs contain the mesh, the 62-joint skin and the material slots only.
|
||||||
|
|
||||||
|
Reproducing the shipped characters:
|
||||||
|
|
||||||
|
flatpak run org.blender.Blender --background \
|
||||||
|
--python "$PWD/tools/blender_assets.py" -- build --only npc
|
||||||
|
|
||||||
|
Upstream quirks the build compensates for (see `docs/assets/npc-model-sourcing.md`):
|
||||||
|
|
||||||
|
1. every mesh ships a **degenerate UV map** (all loops at `0,0`) with flat-colour
|
||||||
|
materials, so the build Smart-UV-unwraps and repacks before export;
|
||||||
|
2. the meshes must be joined **without welding** — `remove_doubles` corrupts the
|
||||||
|
skin weights;
|
||||||
|
3. the rest pose is a T-pose, so the arm-down rest is baked by
|
||||||
|
`_bake_quaternius_rest()`;
|
||||||
|
4. the upstream material names differ per file, so each source carries a slot map
|
||||||
|
down to the project's five tint slots.
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# Quaternius modular parts
|
||||||
|
|
||||||
|
Build inputs for outfit, hair and accessory variety. Committed like the three whole-body
|
||||||
|
sources, so `build` works from a fresh checkout without the upstream pack.
|
||||||
|
|
||||||
|
## Where they come from
|
||||||
|
|
||||||
|
The upstream *Ultimate Modular Characters* pack is distributed as a Google Drive folder
|
||||||
|
(<https://drive.google.com/drive/folders/1USAAquX2JJWuA2m6zol0KUkFe3UkZ8zX>, CC0 1.0). It cannot be
|
||||||
|
fetched reproducibly by a script, so the owner downloads it **once** into the gitignored
|
||||||
|
`tmp/quaternius-intake/`. Everything after that is scripted:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
python3 tools/quaternius_parts.py inventory --dir tmp/quaternius-intake
|
||||||
|
python3 tools/quaternius_parts.py extract \
|
||||||
|
--file tmp/quaternius-intake/<file>.glb --mesh <mesh> --part <part>
|
||||||
|
python3 tools/quaternius_parts.py verify --dir assets/models/blender_src/quaternius/parts
|
||||||
|
```
|
||||||
|
|
||||||
|
`inventory` and `verify` run outside Blender; `extract` needs Blender, because it rewrites the skin.
|
||||||
|
The pack itself is never committed — only the parts that are actually used, each with its SHA-256
|
||||||
|
recorded here and in `CREDITS.md`.
|
||||||
|
|
||||||
|
## Part contract
|
||||||
|
|
||||||
|
A part is **one skinned mesh on the 62-joint rig**:
|
||||||
|
|
||||||
|
- one mesh object, parented to the rig's armature, carrying `JOINTS_0`/`WEIGHTS_0`;
|
||||||
|
- the standard joint names (`Hips`, `Chest`, `Head`, `UpperArm.L`, …). The rig check in
|
||||||
|
`quaternius_parts.py verify` fails a part that is missing any of them, because
|
||||||
|
`NpcAvatar` maps those bones;
|
||||||
|
- materials named after a contract slot (`skin`, `cloth`, `pants`, `hair`, `accessory`) so the
|
||||||
|
runtime tint reaches them, or a fixed-colour detail name that is deliberately not tinted;
|
||||||
|
- triangles counted against the character budget: base body plus every joined part must stay
|
||||||
|
inside 24,000 triangles and 24,000 glTF vertices.
|
||||||
|
|
||||||
|
The builder drops the part's own armature when it joins the mesh onto a base body, because the base
|
||||||
|
already owns the skeleton and two armatures would duplicate every bone. Weights survive the join
|
||||||
|
because Blender merges vertex groups by name.
|
||||||
|
|
||||||
|
## Assigning parts to a role
|
||||||
|
|
||||||
|
```python
|
||||||
|
"npc_vest": {"layer": "vest", "base": "worker", "parts": ["hivis_vest"], ...}
|
||||||
|
```
|
||||||
|
|
||||||
|
`build` joins those parts after the body join and before the material slot map, so the part's
|
||||||
|
materials go through the same slot mapping as the base. The T-pose cache is keyed on the part list.
|
||||||
|
|
||||||
|
## Kept parts
|
||||||
|
|
||||||
|
| Part | Source file | SHA-256 | Tris |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| _(none yet — the pack has not been intaken)_ | | | |
|
||||||
@@ -1,42 +1,43 @@
|
|||||||
# Gig Line Documentation
|
# Gig Line Documentation
|
||||||
|
|
||||||
This folder holds the project documentation, visual references and generated QA evidence.
|
Documentation is grouped by category. Product intent, the gap analysis and the release roadmap
|
||||||
|
live in [`../PLAN.md`](../PLAN.md); the executable task list is [`../TODO.md`](../TODO.md); the
|
||||||
|
workflow rules are in [`../AGENTS.md`](../AGENTS.md).
|
||||||
|
|
||||||
## Current priorities
|
## Categories
|
||||||
|
|
||||||
1. [Blender NPC model overhaul](../TODO.md#blender-npc-model-overhaul-top-priority) — part-based head/face/hands pipeline and 16,000-budget contract.
|
| Folder | Contents |
|
||||||
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.
|
| [`project/`](project/README.md) | Architecture (arc42) and the implemented-features status |
|
||||||
|
| [`design/`](design/README.md) | Gameplay, venues, UI copy, accessibility and known limitations |
|
||||||
|
| [`assets/`](assets/README.md) | Blender library, asset tooling, NPC sourcing and the 3D model review |
|
||||||
|
| [`process/`](process/README.md) | Setup/controls, release QA and the release runbook |
|
||||||
|
| [`adr/`](adr/README.md) | Architecture Decision Records |
|
||||||
|
| [`screens/`](screens/README.md) | Licensed references, concepts and screen designs |
|
||||||
|
| [`blender_previews/`](blender_previews/README.md) | Committed character/gear/prop preview sheets |
|
||||||
|
| [`screenshots/`](screenshots/README.md) | The committed in-game gallery |
|
||||||
|
|
||||||
## Start here
|
## Start here
|
||||||
|
|
||||||
- [`../PLAN.md`](../PLAN.md) — product, design intent and development priorities
|
- [`../PLAN.md`](../PLAN.md) — product, design pillars, gap analysis and the roadmap to 1.0.0
|
||||||
- [`../TODO.md`](../TODO.md) — priority-ordered active tasks and roadmap
|
- [`../TODO.md`](../TODO.md) — milestone-ordered active tasks
|
||||||
- [`npc-model-sourcing.md`](npc-model-sourcing.md) — character-source evaluation, licence rules and the character-development plan
|
- [`project/architecture.md`](project/architecture.md) — system architecture and ownership
|
||||||
- [`architecture.md`](architecture.md) — arc42 system architecture
|
- [`project/development-status.md`](project/development-status.md) — what the build supports now
|
||||||
- [`getting-started.md`](getting-started.md) — setup, run/test commands and controls
|
- [`design/gameplay.md`](design/gameplay.md) — the playable loop and escalation model
|
||||||
- [`asset-tooling.md`](asset-tooling.md) — image/model pipelines and screenshot gates
|
- [`design/venues.md`](design/venues.md) — venue mapping and real-site evidence
|
||||||
- [`../tools/README.md`](../tools/README.md) — tool inventory, categories and test runner
|
- [`assets/npc-model-sourcing.md`](assets/npc-model-sourcing.md) — the active NPC base and licence
|
||||||
- [`gameplay.md`](gameplay.md) — controls, venues and escalation
|
rules
|
||||||
- [`venues.md`](venues.md) — Hollywood, Joke Shop and TV Studio real-site mapping
|
- [`assets/3d-model-review.md`](assets/3d-model-review.md) — asset measurements and scorecard
|
||||||
- [`npc-visual-review.md`](npc-visual-review.md) — NPC visual baseline, acceptance criteria and ranked gaps
|
- [`process/getting-started.md`](process/getting-started.md) — setup, run/test and controls
|
||||||
- [`3d-model-review.md`](3d-model-review.md) — 3D model re-evaluation: measurements, scorecard and ranked gaps
|
- [`../tools/README.md`](../tools/README.md) — tool inventory and test runner
|
||||||
- [`development-status.md`](development-status.md) — implemented features, current gaps and active planning
|
- [`../CREDITS.md`](../CREDITS.md) — credits, AI/reference provenance and licensing
|
||||||
- [`accessibility.md`](accessibility.md) — accessibility statement and known gaps
|
- [`../PRIVACY.md`](../PRIVACY.md) — local-only data and save files
|
||||||
- [`known-limitations.md`](known-limitations.md) — release-candidate blockers and accepted limits
|
|
||||||
- [`release-qa.md`](release-qa.md) — manual smoke checklist and balance-acceptance protocol
|
|
||||||
- [`../CREDITS.md`](../CREDITS.md) — credits and asset provenance
|
|
||||||
- [`../PRIVACY.md`](../PRIVACY.md) — privacy note
|
|
||||||
- [`ui-copy.md`](ui-copy.md) — screen, copy and button inventory
|
|
||||||
- [`RELEASING.md`](RELEASING.md) — export, CI and publishing workflow
|
|
||||||
- [`adr/README.md`](adr/README.md) — architecture decisions
|
|
||||||
|
|
||||||
## Visual references
|
## Current work
|
||||||
|
|
||||||
- [`screens/README.md`](screens/README.md) — concepts, designs, screenshots and realism runs
|
v0.9.9 shipped the Quaternius NPC roster. The active patch line is `0.9.10` (roster follow-ups:
|
||||||
- [`blender_previews/README.md`](blender_previews/README.md) — character/gear/prop previews
|
outfit families, the Swat base orientation, per-slot atlases) through `0.9.12`, followed by the
|
||||||
- [`screenshots/README.md`](screenshots/README.md) — committed game gallery
|
`0.10.0` public-readiness minor. See [`../TODO.md`](../TODO.md) for the live checklist.
|
||||||
- [`ui-copy.md`](ui-copy.md#screen-design-judge-report) — screen/button inventory and latest judge result
|
|
||||||
|
|
||||||
## Quick preview
|
## Quick preview
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
# ADR-0015: NPC model variety sourcing
|
# ADR-0015: NPC model variety sourcing
|
||||||
|
|
||||||
- **Status:** Accepted (planning)
|
- **Status:** Superseded by [ADR-0017](0017-quaternius-npc-base.md) (2026-11-05)
|
||||||
- **Date:** 2026-11-03
|
- **Date:** 2026-11-03
|
||||||
|
|
||||||
|
## Superseded
|
||||||
|
|
||||||
|
ADR-0017 replaces the generator-first decision below: Quaternius is now the
|
||||||
|
primary NPC base. The evaluation, licence rules and consequences remain as the
|
||||||
|
record of the 2026-11-03 decision.
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
The library has eight skinned characters, and role/seed selection reuses them
|
The library has eight skinned characters, and role/seed selection reuses them
|
||||||
@@ -15,7 +21,7 @@ A review compared free/open-source sources against that contract. Quaternius
|
|||||||
Ultimate Modular (CC0), Kenney Blocky Characters (CC0), Khronos CesiumMan and
|
Ultimate Modular (CC0), Kenney Blocky Characters (CC0), Khronos CesiumMan and
|
||||||
RiggedFigure (CC BY 4.0) and the MakeHuman base mesh (CC0) were imported and
|
RiggedFigure (CC BY 4.0) and the MakeHuman base mesh (CC0) were imported and
|
||||||
measured. None was a drop-in; the full results are in
|
measured. None was a drop-in; the full results are in
|
||||||
[`docs/npc-model-sourcing.md`](../npc-model-sourcing.md).
|
[`docs/assets/npc-model-sourcing.md`](../assets/npc-model-sourcing.md).
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
@@ -80,4 +86,4 @@ measured. None was a drop-in; the full results are in
|
|||||||
- MakeHuman is now an active local development pipeline (body retarget plus project-owned
|
- MakeHuman is now an active local development pipeline (body retarget plus project-owned
|
||||||
head/hands), while the procedural library remains the shipped path and CI fallback.
|
head/hands), while the procedural library remains the shipped path and CI fallback.
|
||||||
- Blender MCP is optional interactive tooling only; it is not a build, CI, test or runtime
|
- Blender MCP is optional interactive tooling only; it is not a build, CI, test or runtime
|
||||||
dependency. Setup is in [`docs/asset-tooling.md#optional-interactive-blender-mcp`](../asset-tooling.md#optional-interactive-blender-mcp).
|
dependency. Setup is in [`docs/assets/asset-tooling.md#optional-interactive-blender-mcp`](../assets/asset-tooling.md#optional-interactive-blender-mcp).
|
||||||
@@ -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.
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# ADR-0017: Quaternius NPC base
|
||||||
|
|
||||||
|
- **Status:** Accepted
|
||||||
|
- **Date:** 2026-11-05
|
||||||
|
- **Supersedes:** ADR-0015 (generator-first character sourcing)
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The current NPC library is built by the project-owned procedural generator. It
|
||||||
|
keeps the contract and ships, but the body, neck, hands and shoes need a
|
||||||
|
bespoke part pipeline to read as human. The MakeHuman head and MPFB body
|
||||||
|
prototypes improved detail but added a second authoring path, a 19,747-triangle
|
||||||
|
prototype and unresolved neck/shoulder seams.
|
||||||
|
|
||||||
|
The CC0 **Quaternius Ultimate Modular Characters** pack already provides a
|
||||||
|
coherent low-poly human silhouette, 21 modular outfits and 24 animation clips.
|
||||||
|
The researched GLBs (`Casual`, `Casual_Hoodie`, `Worker`) measure 4 meshes, 62
|
||||||
|
joints and 24 clips each. The owner directed that Quaternius become the NPC
|
||||||
|
base. The full evaluation is in [`docs/assets/npc-model-sourcing.md`](../assets/npc-model-sourcing.md).
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
1. **Quaternius is the primary NPC mesh and animation source.** Keep the
|
||||||
|
licence and SHA-256 provenance for the three researched GLBs.
|
||||||
|
2. **Stage 1 keeps the runtime contract.** Bake a canonical Quaternius base onto
|
||||||
|
the existing 13-core contract, five tint slots, 24,000/24,000 budget,
|
||||||
|
grounded −Y front and one `npc_base` skinned mesh. Retarget Idle and Walk;
|
||||||
|
discard the combat/gun/sword clips. `NpcAvatar`, gear attach points and the
|
||||||
|
pose composition remain the runtime interface.
|
||||||
|
3. **The 62-joint rig is an authoring source, not a runtime dependency.** It is
|
||||||
|
not shipped and Quaternius is not loaded by CI, build or runtime.
|
||||||
|
4. **Stage 2 needs its own ADR.** If the proportion warp fails the silhouette,
|
||||||
|
deformation or gear gate, stop and decide whether to adopt the 62-joint rig
|
||||||
|
at runtime. Do not ship a hybrid rig or a second gear offset system.
|
||||||
|
5. **Close the MakeHuman/MPFB body work.** The accepted MakeHuman head and the
|
||||||
|
procedural `npc_base` stay as tested fallbacks until the Quaternius rollout
|
||||||
|
ships. No new MPFB development.
|
||||||
|
6. **Commit baked assets only.** The release consumes committed GLBs, maps and
|
||||||
|
the manifest; Quaternius and Blender remain development tools.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
### Positive
|
||||||
|
|
||||||
|
- A human base, modular outfits and a coherent animation set are already
|
||||||
|
authored and CC0.
|
||||||
|
- The bespoke neck, hand and shoe pipelines are no longer on the critical path.
|
||||||
|
- The runtime contract and gear stay stable during the mesh migration.
|
||||||
|
|
||||||
|
### Negative
|
||||||
|
|
||||||
|
- A 62-joint T-pose does not share the arm-down 13-core rest pose or
|
||||||
|
proportions; the proportion warp is the main risk.
|
||||||
|
- Quaternius' animation quality is only available after retargeting, unless
|
||||||
|
Stage 2 is accepted.
|
||||||
|
- The migration touches all 12 variants, their AO maps, manifest entries and
|
||||||
|
baseline captures at once.
|
||||||
|
|
||||||
|
## Alternatives
|
||||||
|
|
||||||
|
- **Keep the procedural generator as the primary path.** Rejected by the owner:
|
||||||
|
the human silhouette remains the weak point and the bespoke part pipeline is
|
||||||
|
larger than the Quaternius bake.
|
||||||
|
- **Adopt the 62-joint rig immediately.** Deferred to Stage 2 because it changes
|
||||||
|
`NpcAvatar`, pose composition and gear offsets at the same time as the mesh.
|
||||||
|
- **Continue the MPFB body.** Rejected: it needs a separate head/neck/hand
|
||||||
|
pipeline and still has unresolved surface seams.
|
||||||
|
- **Use a service character generator (Mixamo, Ready Player Me).** Rejected:
|
||||||
|
redistribution and runtime terms are not a CC0 basis.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# ADR-0018: Quaternius Stage 2 — adopt source proportions at runtime
|
||||||
|
|
||||||
|
- **Status:** Accepted (2026-11-05, owner chose option 2)
|
||||||
|
- **Date:** 2026-11-05
|
||||||
|
- **Supersedes:** ADR-0017 decision 2 (Stage 1 keeps the 13-core contract)
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
ADR-0017 made Quaternius the NPC base and staged the migration: Stage 1 bakes a
|
||||||
|
proportion-warped mesh onto the existing 13-core contract; Stage 2 adopts the
|
||||||
|
62-joint rig at runtime only if the warp fails.
|
||||||
|
|
||||||
|
The Stage 1 proportion warp was executed and measured (`docs/assets/npc-model-sourcing.md`
|
||||||
|
§Rest-pose and proportion-warp measurement). The arm-down rest pose bakes cleanly, but the
|
||||||
|
warp to the contract proportions does not:
|
||||||
|
|
||||||
|
| Joint | Quaternius | Contract | Delta |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Hips height | 0.869 | 0.62 | −0.249 |
|
||||||
|
| Shoulder x | 0.148 | 0.27 | +0.122 |
|
||||||
|
| 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 distorted: paddle/claw hands, forearms lost into the
|
||||||
|
torso, stretched shins, "long legs + short torso". The arm either stays short (a shortened arm
|
||||||
|
against the contract hand) or stretches 1.63× (a distorted deltoid + hand). Both are the gate's
|
||||||
|
rejection conditions.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Stop the Stage 1 rollout and **adopt the Quaternius 62-joint rig at runtime** (owner chose
|
||||||
|
option 2). The mesh is not proportion-warped: it keeps its source LOD (3,199 welded verts /
|
||||||
|
6,206 tris) and only the arm-down rest pose is baked.
|
||||||
|
|
||||||
|
- `NpcAvatar` maps the Quaternius joint names instead of the 13-core names.
|
||||||
|
- Gear attach points are re-derived from the Quaternius skeleton (hip ≈0.87, shoulder ≈0.148/1.39,
|
||||||
|
wrist ≈0.99, knee ≈0.52).
|
||||||
|
- The 24 upstream clips ship as authoring reference only and are **not played at runtime**.
|
||||||
|
`NpcAvatar._animate()` drives the proxy pivots and `_sync_skeleton()` writes the bone poses, which
|
||||||
|
is what the FSM already needed for sitting, raising a hand and turning the head. Playing the clips
|
||||||
|
would replace that state machine rather than supplement it; revisiting this needs its own ADR.
|
||||||
|
|
||||||
|
Option 1 (keep the 13-core names with Quaternius rest positions) is rejected in favour of the
|
||||||
|
full source rig.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
### Positive
|
||||||
|
|
||||||
|
- The Quaternius silhouette, deltoid, hand and leg proportions are preserved — no paddle hands,
|
||||||
|
no shortened arm, no torso/leg distortion.
|
||||||
|
- The mesh stays at source LOD (far under the 24,000 cap), so no decimation is needed.
|
||||||
|
|
||||||
|
### Negative
|
||||||
|
|
||||||
|
- The runtime contract numbers (hip 0.62, shoulder 0.27, hand 0.78) change; every gear attach
|
||||||
|
point, `npc_proportions` guide, fit measurement and pose-composition constant must be
|
||||||
|
re-derived and re-tested.
|
||||||
|
- `NpcAvatar`'s bone mapping and pose composition are rewritten for the 62-joint rig, a larger
|
||||||
|
change than the mesh swap.
|
||||||
|
- The 12-variant rollout and the 12×6 baseline are still blocked until the new rest positions
|
||||||
|
and gear fit are owner-approved.
|
||||||
|
|
||||||
|
## Alternatives
|
||||||
|
|
||||||
|
- **Ship the warped mesh.** Rejected by the gate: the 1.63× arm / 0.74× leg warp visibly
|
||||||
|
distorts and the owner directed keeping the Quaternius as close to source as possible.
|
||||||
|
- **Keep the old contract and accept a short arm.** Rejected for the same reason: the hand ends
|
||||||
|
at ≈0.99 instead of 0.78, so handheld gear floats unless attach points move — which is option 1.
|
||||||
|
- **Abandon Quaternius and keep the procedural generator.** Rejected in ADR-0017.
|
||||||
|
|
||||||
|
## Open question
|
||||||
|
|
||||||
|
Resolved: option 2 (62-joint runtime) is the owner's choice. The first implementation step is
|
||||||
|
the `NpcAvatar` bone-map + gear-attach re-derivation, then the slot/AO bake and the 12-variant
|
||||||
|
rollout.
|
||||||
|
|
||||||
|
## Follow-up decision: full roster swap
|
||||||
|
|
||||||
|
- **Date:** 2026-11-05 (owner, at the `0.9.9` face/silhouette gate)
|
||||||
|
|
||||||
|
The owner chose **option (a) full swap** from
|
||||||
|
the face/silhouette gate (its sheets were retired with the review pages): every roster character
|
||||||
|
moves onto the Quaternius base, and the procedural generator plus the MakeHuman head retire to
|
||||||
|
the tested fallback rather than staying in the shipped roster.
|
||||||
|
|
||||||
|
Scope consequences:
|
||||||
|
|
||||||
|
- The shipped roster keeps its twelve public character names and `CHARACTER_POOLS` mapping; the
|
||||||
|
geometry behind them comes from the three CC0 full-body sources already researched
|
||||||
|
(`Casual`, `Casual_Hoodie`, `Worker`), aliased per role.
|
||||||
|
- Variety now comes from the five tint slots, the gear library and the per-role outfit rules
|
||||||
|
instead of twelve distinct meshes. Roster silhouettes are therefore *less* varied than the
|
||||||
|
procedural library until the modular part library (hair, outfits) is added — tracked as a
|
||||||
|
`0.9.10` task, not hidden.
|
||||||
|
- The procedural library, `_build_body()` and the MakeHuman head stay in the tree and tested as
|
||||||
|
the instant fallback; no MPFB or Stage-1 proportion-warp work reopens.
|
||||||
@@ -19,3 +19,6 @@ 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)
|
||||||
|
- [0017-quaternius-npc-base](0017-quaternius-npc-base.md)
|
||||||
|
- [0018-quaternius-stage2-runtime-rig](0018-quaternius-stage2-runtime-rig.md)
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
# 3D model review (2026-11-03)
|
# 3D model review (2026-11-03)
|
||||||
|
|
||||||
Status: **baseline measured; scorecard open.** This is the working document for the unversioned
|
Status: **baseline measured; scorecard open.** This is the working document for the unversioned
|
||||||
`3D model re-evaluation` track in [`TODO.md`](../TODO.md). It records what was measured, what the
|
`3D model re-evaluation` track in [`TODO.md`](../../TODO.md). It records what was measured, what the
|
||||||
Blender skill guidance says the targets are, the ranked candidate gaps, and the decisions that
|
Blender skill guidance says the targets are, the ranked candidate gaps, and the decisions that
|
||||||
still need the project owner. Nothing here re-opens the accepted 0.9.4 limits by itself.
|
still need the project owner. Nothing here re-opens the accepted 0.9.4 limits by itself.
|
||||||
|
|
||||||
Related documents: [`npc-visual-review.md`](npc-visual-review.md) (accepted 0.9.4 limits and
|
Related documents: [`npc-model-sourcing.md`](npc-model-sourcing.md) (sources, shipped roster and
|
||||||
before/after sheets), [`npc-visual-review.md`](npc-visual-review.md#proportion-audit) (proportion guide),
|
build steps), [`blender-assets.md`](blender-assets.md) (asset contract),
|
||||||
[`blender-assets.md`](blender-assets.md) (asset contract), [`asset-tooling.md`](asset-tooling.md)
|
[`asset-tooling.md`](asset-tooling.md) (commands). The 0.9.4 procedural baseline this page was
|
||||||
(commands).
|
measured against no longer ships; its before/after sheets stay in `blender_previews/`.
|
||||||
|
|
||||||
## Method and skill routing
|
## Method and skill routing
|
||||||
|
|
||||||
@@ -85,10 +85,12 @@ Readings:
|
|||||||
|
|
||||||
## Baseline inventory (2026-11-04)
|
## Baseline inventory (2026-11-04)
|
||||||
|
|
||||||
Recorded for the Blender NPC model overhaul track: the exact starting point before the local
|
Recorded for the character baseline before the Quaternius migration. `npc_base.blend` is the
|
||||||
part pipeline is built. `npc_base.blend` is the frozen fallback; the 12 characters are assembled
|
frozen fallback; the 12 characters are currently assembled procedurally by
|
||||||
procedurally by `tools/blender_assets.py`; the MakeHuman prototypes live under `tmp/npc-research/`
|
`tools/blender_assets.py`. The active plan is now the CC0 Quaternius base bake
|
||||||
and are not the shipped path.
|
([ADR-0017](../adr/0017-quaternius-npc-base.md)); this section and the MakeHuman notes below are the
|
||||||
|
pre-migration record. The MPFB/MakeHuman development files were removed from `tmp/` after the
|
||||||
|
2026-11-05 pivot.
|
||||||
|
|
||||||
### `assets/models/npc/npc_base.blend` (frozen fallback)
|
### `assets/models/npc/npc_base.blend` (frozen fallback)
|
||||||
|
|
||||||
@@ -143,7 +145,7 @@ width scale.
|
|||||||
287–440 px/m via the 4× repeat; runtime tint carries the look. This is a recorded note until a
|
287–440 px/m via the 4× repeat; runtime tint carries the look. This is a recorded note until a
|
||||||
portrait shows texture starvation.
|
portrait shows texture starvation.
|
||||||
|
|
||||||
### MakeHuman prototypes (not shipped; `tmp/npc-research/makehuman/`)
|
### MakeHuman prototypes (historical, not shipped; research files removed from `tmp/`)
|
||||||
|
|
||||||
| File | Verts / tris | Bones | Slots | Note |
|
| File | Verts / tris | Bones | Slots | Note |
|
||||||
| --- | ---: | ---: | --- | --- |
|
| --- | ---: | ---: | --- | --- |
|
||||||
@@ -193,7 +195,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.
|
||||||
|
|
||||||
@@ -242,7 +244,7 @@ nose/lip/chin relief cleanly.
|
|||||||
|
|
||||||
The judge then compared the displacement head against the **decimated MakeHuman head**
|
The judge then compared the displacement head against the **decimated MakeHuman head**
|
||||||
(extracted from `makehuman_retargeted.glb`, 2,009 verts / 1,573 tris, saved as
|
(extracted from `makehuman_retargeted.glb`, 2,009 verts / 1,573 tris, saved as
|
||||||
`tmp/npc-parts/makehuman_head.glb`) and returned a decisive result: **ship the MakeHuman head** —
|
the local `makehuman_head.glb`) and returned a decisive result: **ship the MakeHuman head** —
|
||||||
it keeps the nose/chin/jaw landmarks at a fraction of the cost, while the procedural head's
|
it keeps the nose/chin/jaw landmarks at a fraction of the cost, while the procedural head's
|
||||||
"clean ellipse outline instantly screams procedural sphere".
|
"clean ellipse outline instantly screams procedural sphere".
|
||||||
|
|
||||||
@@ -257,6 +259,16 @@ at the MakeHuman landmarks. `build_character(name, head="mh")` assembles it; the
|
|||||||
`inspect` (14 bones, skinned, no issues). The judge reads the face ~3.5/5; remaining polish is
|
`inspect` (14 bones, skinned, no issues). The judge reads the face ~3.5/5; remaining polish is
|
||||||
welding the added eye/brow pieces into the head shell and a skull-conforming hair cap.
|
welding the added eye/brow pieces into the head shell and a skull-conforming hair cap.
|
||||||
|
|
||||||
|
**Standalone head re-review (2026-11-04):** the separate
|
||||||
|
`assets/models/blender_src/makehuman_head.glb` prototype (12,641 tris / 7,690 split verts,
|
||||||
|
with a skin eyelid mask, recessed globes, flat iris/pupil discs and surface-anchored brows)
|
||||||
|
was **accepted by the owner** as a basic human head. The automated vision gate still returns
|
||||||
|
REJECT on the eye/lid region (globe depth, lid overlap, iris at three-quarter) as deferred
|
||||||
|
polish. The assembled `npc_casual --head mh` now adds a skull-conforming hair cap, a hidden
|
||||||
|
scalp trim and a narrowed neck/shoulder body: 14,753 tris / 12,823 seam-split verts /
|
||||||
|
14 bones / 9 materials, `inspect` clean. All 12 variants count 14,693–15,987 tris. See
|
||||||
|
[`makehuman-head-review.md`](makehuman-head-review.md).
|
||||||
|
|
||||||
### Head subdivision comparison (2026-11-04)
|
### Head subdivision comparison (2026-11-04)
|
||||||
|
|
||||||
Three `head_proto` variants at UV-sphere segments 24/48/64 were rendered at 1.85 m and 1.5 m in
|
Three `head_proto` variants at UV-sphere segments 24/48/64 were rendered at 1.85 m and 1.5 m in
|
||||||
@@ -271,7 +283,98 @@ front/three-quarter/profile and judged side by side:
|
|||||||
The chosen s48 is the `head_proto` default; the rejected s24/s64 stay local under
|
The chosen s48 is the `head_proto` default; the rejected s24/s64 stay local under
|
||||||
`tmp/npc-parts/`. A before/after sign-off sheet (current `_face` vs s48, 1.85 m
|
`tmp/npc-parts/`. A before/after sign-off sheet (current `_face` vs s48, 1.85 m
|
||||||
front/three-quarter/profile) is
|
front/three-quarter/profile) is
|
||||||
[`blender_previews/sheet_head_proto_before_after.jpg`](blender_previews/sheet_head_proto_before_after.jpg).
|
[`blender_previews/sheet_head_proto_before_after.jpg`](../blender_previews/sheet_head_proto_before_after.jpg).
|
||||||
|
|
||||||
|
## Foliage language P1 — resolved 2026-11-06
|
||||||
|
|
||||||
|
The ranked P1 was that shrubs read as rocks: `_shrub()` stacked spheres, so the silhouette was
|
||||||
|
smooth and the light response was a single facet per clump.
|
||||||
|
|
||||||
|
`_leaf_card()` replaces the stack: one low-poly inner mass for opacity, then 18–53 two-triangle
|
||||||
|
quads scattered over the canopy shell by a jittered Fibonacci distribution, each rotated onto the
|
||||||
|
canopy normal and tilted off it. No alpha texture, so the flat-colour library and the Compatibility
|
||||||
|
renderer are untouched.
|
||||||
|
|
||||||
|
| Prop | Before | After |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `planter_box` | 1,324 tris | 818 |
|
||||||
|
| `round_planter` | 1,240 tris | 808 |
|
||||||
|
| `street_tree` | 2,592 tris | 1,506 |
|
||||||
|
| Props total (20) | 13,808 | 11,784 |
|
||||||
|
|
||||||
|
## Lighting pass — flashlight measured 2026-11-06
|
||||||
|
|
||||||
|
`capture_realism.gd --stages=late --flashlight` renders the same frame with the lamp off and on, so
|
||||||
|
the beam's contribution is a number instead of an impression. Mean luminance, 0–255:
|
||||||
|
|
||||||
|
| Region | Lamp off | Old settings | Shipped now |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Aimed centre (facade) | 13.5 | 13.6 | **29.7** |
|
||||||
|
| Near pavement | 3.7 | 3.7 | **11.7** |
|
||||||
|
|
||||||
|
The old flashlight (energy 4.2, 20 m range, 14° cone, aimed dead ahead) moved the frame by 0.1/255 —
|
||||||
|
it was effectively off. The shipped values are 10 energy, 45 m, 24°, tilted 5° down: the beam lands
|
||||||
|
on the door or person being checked *and* puts a pool on the pavement in front, without flooding the
|
||||||
|
facade. Verified in both venues (Hollywood facade and the Joke Shop door).
|
||||||
|
|
||||||
|
### Street-lamp pools, measured
|
||||||
|
|
||||||
|
A new `lamp_late` shot frames a street lamp so the pool under it can be sampled. The lamp is
|
||||||
|
`StreetLamp_*` (named so `set_night_mode` can tune it apart from the sconce and marquee glows).
|
||||||
|
Attenuation stays at 1.0 — the venue test requires physical falloff — so the pool is made by range
|
||||||
|
and energy:
|
||||||
|
|
||||||
|
| Setting | Pool | Gap | Pool/gap |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| old: 16 m, energy 2.2 | 14.1 | 2.7 | 5.2 |
|
||||||
|
| 16 m, energy 4.0 | 21.1 | 6.5 | 3.3 (washed) |
|
||||||
|
| 8.5 m, energy 6.5 | 11.5 | 1.3 | 8.9 |
|
||||||
|
| **10 m, energy 8.0 (shipped)** | **16.0** | **1.3** | **12.3** |
|
||||||
|
|
||||||
|
Mean luminance 0–255. The shipped values brighten the pool past the old setting while darkening the
|
||||||
|
gap between poles, which is what "pools, not a wash" means numerically.
|
||||||
|
|
||||||
|
### Event banners read as lit cloth (2026-11-06)
|
||||||
|
|
||||||
|
The banners were one flat emissive panel, so they measured the same luminance from the mounting bar
|
||||||
|
to the hem (114/121/122/125 down the panel) and read as a painted red card rather than lit fabric.
|
||||||
|
They are now four stacked strips with a night gradient (energies 2.6 / 2.2 / 1.8 / 1.4), carried per
|
||||||
|
material through `night_energy` metadata so `set_night_mode` keeps the ratio instead of flattening it.
|
||||||
|
|
||||||
|
| | Before | After |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Vertical profile down a banner | 114 → 125 (flat) | 135 → 84 |
|
||||||
|
| Clipping (p99 / pixels ≥ 250) | 192 / 0.2 % | 192 / 0.2 % |
|
||||||
|
| Daylight read | uniform | uniform (strips flush, no seam) |
|
||||||
|
|
||||||
|
No clipping in either state, and the Compatibility renderer draws it with the same flat emissive
|
||||||
|
material as before — the change is geometry plus per-material energy, not a new shader.
|
||||||
|
|
||||||
|
## Set dressing — Joke Shop queue (2026-11-06)
|
||||||
|
|
||||||
|
The queue props were placed individually (`stanchion` at ±3, `crowd_barrier` at x 2.2, podium at 6.8),
|
||||||
|
so no line read and the stanchions' 0.9 m velvet stubs pointed in unrelated directions. They are now
|
||||||
|
one queue: four stanchions 0.9 m apart west of the guest approach lane, the check-in podium at the
|
||||||
|
head, and the barricade on the curb side. The line has to sit outside
|
||||||
|
`PROP_EXCLUSIONS["guest approach lane"]` (x ±1.4), which is what the placement validator enforces —
|
||||||
|
the first attempt put the podium at x 0.4 and the test caught it.
|
||||||
|
|
||||||
|
Readability at 8 m drove the thickness pass: bike-rack frame 22 → 28 mm, bars 10 → 12 mm, velvet rope
|
||||||
|
18 → 22 mm. The west planter also moved 1.6 m clear of the palm canopy, which was clipping its lip.
|
||||||
|
|
||||||
|
Measured at night afterwards: the entrance walkway sits at 20.7/255 against 3.0 on the side pavement,
|
||||||
|
so the door pool exists; the queue area itself is still unlit and stays queued as a follow-up.
|
||||||
|
|
||||||
|
### Hollywood and the TV Studio
|
||||||
|
|
||||||
|
Hollywood had one stanchion and one barricade, which read as stray street furniture; it now has the
|
||||||
|
same three-post rope line into the check-in podium, with a barricade on the curb.
|
||||||
|
|
||||||
|
The TV Studio had **never been validated**: `placement_problems()` was only applied to the Joke Shop
|
||||||
|
in its test, and running it on the studio reported six violations — three props at z 4.2–4.4 sat
|
||||||
|
inside the steps/door exclusion and outside the sidewalk bounds. They are re-placed as a rope line,
|
||||||
|
podium and two curb barricades, and `test_every_venue_placement_clears_the_sidewalk_and_the_approach`
|
||||||
|
now validates all three venues so the gap cannot reopen.
|
||||||
|
|
||||||
## Scorecard skeleton
|
## Scorecard skeleton
|
||||||
|
|
||||||
@@ -485,6 +588,9 @@ and the full carded-cluster foliage pass is the one remaining owner-gated P1. No
|
|||||||
|
|
||||||
## Next actions
|
## Next actions
|
||||||
|
|
||||||
Tracked in [`TODO.md`](../TODO.md) `3D model re-evaluation`: the remaining `A. Baseline…` item is
|
- Review the assembled [`makehuman-head-review.md`](makehuman-head-review.md) prototype (hair cap and full-body silhouette) before rebuilding the 12 shipped character GLBs.
|
||||||
|
|
||||||
|
|
||||||
|
Tracked in [`TODO.md`](../../TODO.md) `3D model re-evaluation`: the remaining `A. Baseline…` item is
|
||||||
this owner review; `B`/`C`/`D` carry the per-family work, and `E` adds the pose/weight,
|
this owner review; `B`/`C`/`D` carry the per-family work, and `E` adds the pose/weight,
|
||||||
collider-coverage and scorecard-coverage gates this document found missing.
|
collider-coverage and scorecard-coverage gates this document found missing.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Asset Documentation
|
||||||
|
|
||||||
|
Asset contracts, pipelines, sourcing and reviews. These pages own the measured evidence; the
|
||||||
|
executable gates are `tools/blender_assets.py inspect|audit|fit`, `tools/npc_proportions.py` and
|
||||||
|
the capture scripts.
|
||||||
|
|
||||||
|
- [`blender-assets.md`](blender-assets.md) — Blender library operation, the character/gear/prop
|
||||||
|
contract, attach points and rebuild discipline.
|
||||||
|
- [`asset-tooling.md`](asset-tooling.md) — image/model pipelines, the optional Blender MCP setup
|
||||||
|
and the screenshot/vision gates.
|
||||||
|
- [`npc-model-sourcing.md`](npc-model-sourcing.md) — character-source evaluation, licence rules,
|
||||||
|
the Quaternius intake and the active NPC plan.
|
||||||
|
- [`3d-model-review.md`](3d-model-review.md) — measurements, per-asset scorecard, ranked gaps and
|
||||||
|
accepted limits.
|
||||||
|
- [`makehuman-head-review.md`](makehuman-head-review.md) — the retained MakeHuman fallback head,
|
||||||
|
its provenance and the review verdict.
|
||||||
|
|
||||||
|
Up: [`../README.md`](../README.md) · Product plan: [`../../PLAN.md`](../../PLAN.md) · Tasks:
|
||||||
|
[`../../TODO.md`](../../TODO.md).
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Everything the game renders is produced or gated by the scripts below. Architecture-level contracts,
|
Everything the game renders is produced or gated by the scripts below. Architecture-level contracts,
|
||||||
data flow and failure fallbacks are summarized in
|
data flow and failure fallbacks are summarized in
|
||||||
[`architecture.md`](architecture.md#content-and-asset-pipeline-architecture); this page is the
|
[`architecture.md`](../project/architecture.md#content-and-asset-pipeline-architecture); this page is the
|
||||||
operational reference. Development-only outputs (AI concept sheets, Blender sources, raw AI fabrics)
|
operational reference. Development-only outputs (AI concept sheets, Blender sources, raw AI fabrics)
|
||||||
are gitignored; the audited game assets are committed.
|
are gitignored; the audited game assets are committed.
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ colours onto material roles (darkest → metal, warm saturated → wood, light g
|
|||||||
stone, green → foliage). glTF stores colours in linear space, so the tool converts
|
stone, green → foliage). glTF stores colours in linear space, so the tool converts
|
||||||
the sRGB palettes before writing them. Re-run `build` and `godot --headless
|
the sRGB palettes before writing them. Re-run `build` and `godot --headless
|
||||||
--path . --import` after changing a prop. See
|
--path . --import` after changing a prop. See
|
||||||
[ADR-0012](adr/0012-surface-materials-and-generated-props.md).
|
[ADR-0012](../adr/0012-surface-materials-and-generated-props.md).
|
||||||
|
|
||||||
Surface materials share one definition in `src/game/materials.gd`: named
|
Surface materials share one definition in `src/game/materials.gd`: named
|
||||||
roughness/metallic profiles per surface, plus the environment tune-up (ACES
|
roughness/metallic profiles per surface, plus the environment tune-up (ACES
|
||||||
@@ -81,12 +81,14 @@ tonemapping, glow, fog, colour grading) that the phase lighting applies.
|
|||||||
## NPC character model
|
## NPC character model
|
||||||
|
|
||||||
NPCs are moving from the procedural capsule rig to a skinned, UV-mapped base
|
NPCs are moving from the procedural capsule rig to a skinned, UV-mapped base
|
||||||
character authored in Blender ([ADR-0013](adr/0013-blender-authored-npc-characters.md)).
|
character authored in Blender ([ADR-0013](../adr/0013-blender-authored-npc-characters.md)).
|
||||||
|
The active base is the CC0 Quaternius modular character, baked to the runtime contract
|
||||||
|
([ADR-0017](../adr/0017-quaternius-npc-base.md)).
|
||||||
`tools/npc_pipeline.py` builds `assets/models/generated/npc_base.glb` plus the
|
`tools/npc_pipeline.py` builds `assets/models/generated/npc_base.glb` plus the
|
||||||
per-slot material maps. `NpcAvatar` instantiates that skinned model, tints its
|
per-slot material maps. `NpcAvatar` instantiates that skinned model, tints its
|
||||||
five material slots from the seed-driven outfit, and drives the bones from the
|
five material slots from the seed-driven outfit, and drives the bones from the
|
||||||
existing animation code; the procedural rig remains the offline fallback (see
|
existing animation code; the procedural rig remains the offline fallback (see
|
||||||
[ADR-0013](adr/0013-blender-authored-npc-characters.md) and
|
[ADR-0013](../adr/0013-blender-authored-npc-characters.md) and
|
||||||
[`blender-assets.md`](blender-assets.md)).
|
[`blender-assets.md`](blender-assets.md)).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -116,7 +118,7 @@ blotches; skin, hair and fixed gear keep AO. `palette` writes
|
|||||||
`tools/blender_assets.py` models a larger library procedurally in Blender for the
|
`tools/blender_assets.py` models a larger library procedurally in Blender for the
|
||||||
v0.6.0 integration: **8 skinned NPC characters** (casual, jacket, coat, hi-vis vest,
|
v0.6.0 integration: **8 skinned NPC characters** (casual, jacket, coat, hi-vis vest,
|
||||||
dress, hoodie, firefighter, guard), each a drop-in for `npc_base.glb` (same bones,
|
dress, hoodie, firefighter, guard), each a drop-in for `npc_base.glb` (same bones,
|
||||||
joint positions and tint slots); **18 gear pieces** authored at head/hand/back/chest
|
joint positions and tint slots); **15 gear pieces** authored at head/hand/back/chest
|
||||||
attach points (caps, hood, helmet, backpack, SCBA tank, lanyard, phone, cup,
|
attach points (caps, hood, helmet, backpack, SCBA tank, lanyard, phone, cup,
|
||||||
clipboard, umbrella, camera, sign, flashlight, wand, radio, …); and **20 props**
|
clipboard, umbrella, camera, sign, flashlight, wand, radio, …); and **20 props**
|
||||||
(octagonal bollard and bin, slatted bench, hydrant, news box, planters, street lamp,
|
(octagonal bollard and bin, slatted bench, hydrant, news box, planters, street lamp,
|
||||||
@@ -129,22 +131,24 @@ with colliders/avoidance and drives their emissive parts from the day/night
|
|||||||
cycle. The single `npc_base.glb` and primitive props remain offline fallbacks.
|
cycle. The single `npc_base.glb` and primitive props remain offline fallbacks.
|
||||||
Contract and integration notes: [`blender-assets.md`](blender-assets.md).
|
Contract and integration notes: [`blender-assets.md`](blender-assets.md).
|
||||||
|
|
||||||
Sourcing and expansion research (no external model is shipped yet):
|
Sourcing and migration plan: [`npc-model-sourcing.md`](npc-model-sourcing.md) records the
|
||||||
[`npc-model-sourcing.md`](npc-model-sourcing.md) compares Quaternius, Kenney, Khronos and
|
2026-11-05 direction (ADR-0017). Quaternius Ultimate Modular (CC0) is the primary NPC mesh
|
||||||
MakeHuman sources against the character contract and records the 2026-11-03 direction
|
and animation source, baked to the existing 13-core contract; the procedural generator is
|
||||||
(procedural generator first, Quaternius reference, MakeHuman deferred).
|
the fallback. Kenney/Khronos/MakeHuman remain evaluated references, not active bases.
|
||||||
|
|
||||||
| Characters | Props |
|
| Characters | Props |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
flatpak run org.blender.Blender --background --python "$PWD/tools/blender_assets.py" -- build
|
flatpak run org.blender.Blender --background --python "$PWD/tools/blender_assets.py" -- build
|
||||||
|
flatpak run org.blender.Blender --background --python "$PWD/tools/blender_assets.py" -- build --head mh
|
||||||
flatpak run org.blender.Blender --background --python "$PWD/tools/blender_assets.py" -- render
|
flatpak run org.blender.Blender --background --python "$PWD/tools/blender_assets.py" -- render
|
||||||
python3 tools/blender_assets.py sheet # docs/blender_previews/sheet_*.jpg
|
python3 tools/blender_assets.py sheet # docs/blender_previews/sheet_*.jpg
|
||||||
python3 tools/blender_assets.py audit # no Blender needed
|
python3 tools/blender_assets.py audit # no Blender needed
|
||||||
python3 tools/blender_assets.py fit # gear-vs-body fit report
|
python3 tools/blender_assets.py fit # gear-vs-body fit report
|
||||||
python3 tools/blender_assets.py texels # per-slot texel density (px/m) of the characters
|
python3 tools/blender_assets.py texels # per-slot texel density (px/m) of the characters
|
||||||
|
# `build --head mh` selects the retained MakeHuman fallback head; the default is still `face`.
|
||||||
godot --headless --path . --import
|
godot --headless --path . --import
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -186,9 +190,9 @@ Caveats:
|
|||||||
|
|
||||||
### Intake adaptation (`adapt`)
|
### Intake adaptation (`adapt`)
|
||||||
|
|
||||||
`adapt` is the mechanical first half of an external-mesh intake (MakeHuman,
|
`adapt` is the mechanical first half of an external-mesh intake (Quaternius,
|
||||||
MPFB, downloaded GLB): import, apply transforms, ground the feet, weld seam
|
MakeHuman fallback, downloaded GLB): import, apply transforms, ground the feet,
|
||||||
splits, decimate to the character budget, and export a GLB. It does **not** map
|
weld seam splits, decimate to the character budget, and export a GLB. It does **not** map
|
||||||
the five tint slots or rebuild the 13-core-bone `npc_base` armature (optional extra bones are allowed) — those stay a
|
the five tint slots or rebuild the 13-core-bone `npc_base` armature (optional extra bones are allowed) — those stay a
|
||||||
manual `retopology`/`rigging` step with a recorded second-rig contract if the
|
manual `retopology`/`rigging` step with a recorded second-rig contract if the
|
||||||
source rig cannot be retargeted:
|
source rig cannot be retargeted:
|
||||||
@@ -196,14 +200,14 @@ source rig cannot be retargeted:
|
|||||||
```bash
|
```bash
|
||||||
flatpak run org.blender.Blender --background \
|
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/quaternius/Casual.glb" \
|
||||||
--out "$PWD/tmp/npc-research/makehuman_adapted.glb" \
|
--out "$PWD/tmp/npc-research/quaternius_adapted.glb" \
|
||||||
--target-tris 16000
|
--target-tris 24000
|
||||||
# prints: adapted makehuman_adapted.glb: 36972 -> 16000 tris (bones=N, meshes=1)
|
# prints: adapted quaternius_adapted.glb: <source> -> 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
|
||||||
generator as the fallback until a MakeHuman variant passes `audit`/`fit` and the
|
generator as the fallback until a Quaternius variant passes `audit`/`fit` and the
|
||||||
24-NPC budget.
|
24-NPC budget.
|
||||||
- Numbers are Blender-side measurements. Triangles match `audit` on project assets; the seam-split
|
- Numbers are Blender-side measurements. Triangles match `audit` on project assets; the seam-split
|
||||||
vertex count can differ by ±1 because the importer rounds normals. `audit` stays the single final
|
vertex count can differ by ±1 because the importer rounds normals. `audit` stays the single final
|
||||||
@@ -242,7 +246,7 @@ gate as `--reference` on `generate`.
|
|||||||
`tools/refcollect.py` downloads images from DuckDuckGo image search into `tmp/research/<slug>/` for
|
`tools/refcollect.py` downloads images from DuckDuckGo image search into `tmp/research/<slug>/` for
|
||||||
development reference only. It applies **no licence gate** (rows are marked `local_only` /
|
development reference only. It applies **no licence gate** (rows are marked `local_only` /
|
||||||
`unchecked-local`); everything it fetches must never be committed or promoted into
|
`unchecked-local`); everything it fetches must never be committed or promoted into
|
||||||
[`screens/refs/`](screens/refs/README.md) without the normal sidecar licence + privacy gate. This
|
[`screens/refs/`](../screens/refs/README.md) without the normal sidecar licence + privacy gate. This
|
||||||
is the owner-authorised local-only override (TODO.md §3D model re-evaluation → A).
|
is the owner-authorised local-only override (TODO.md §3D model re-evaluation → A).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -261,7 +265,7 @@ string); the UA alone is no longer enough to look like a browser.
|
|||||||
### Reference-board research (`refboard`)
|
### Reference-board research (`refboard`)
|
||||||
|
|
||||||
`tools/refboard.py` searches, fetches and documents Wikimedia Commons photos of a real location for
|
`tools/refboard.py` searches, fetches and documents Wikimedia Commons photos of a real location for
|
||||||
the [`screens/refs/`](screens/refs/README.md) boards. It is stdlib-only and never commits anything
|
the [`screens/refs/`](../screens/refs/README.md) boards. It is stdlib-only and never commits anything
|
||||||
itself: downloads land in `tmp/`, and moving a file into a board folder is a deliberate manual step
|
itself: downloads land in `tmp/`, and moving a file into a board folder is a deliberate manual step
|
||||||
that goes through the sidecar licence gate.
|
that goes through the sidecar licence gate.
|
||||||
|
|
||||||
@@ -298,12 +302,30 @@ python3 tools/blender_assets.py texels --json # machine-readable
|
|||||||
python3 tools/blender_assets.py texels --only npc_coat
|
python3 tools/blender_assets.py texels --only npc_coat
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Quaternius modular parts (outfit variety)
|
||||||
|
|
||||||
|
`tools/quaternius_parts.py` is the intake for the upstream modular pack, which ships as a Google
|
||||||
|
Drive folder and is therefore downloaded once by hand into `tmp/quaternius-intake/` (gitignored):
|
||||||
|
|
||||||
|
| Step | Command | Runs in |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| list what the download contains | `python3 tools/quaternius_parts.py inventory --dir tmp/quaternius-intake` | plain Python (parses the GLB container) |
|
||||||
|
| cut one mesh out as a part | `... extract --file <glb> --mesh <name> --part <name>` | Blender (rewrites the skin) |
|
||||||
|
| hash and validate the kept parts | `... verify --dir assets/models/blender_src/quaternius/parts` | plain Python |
|
||||||
|
|
||||||
|
A part is one skinned mesh on the 62-joint rig; the contract and the join behaviour are in
|
||||||
|
`assets/models/blender_src/quaternius/parts/README.md`. `build` joins a role's
|
||||||
|
`CHARACTERS[...]["parts"]` onto its base body before the slot map, keeping the part's weights and
|
||||||
|
dropping its redundant armature. The pack is never committed — only the parts that are used, with
|
||||||
|
their SHA-256 in `CREDITS.md`.
|
||||||
|
|
||||||
## Local map development (planned)
|
## Local map development (planned)
|
||||||
|
|
||||||
The local map workstreams (H–M) in [`TODO.md`](../TODO.md#3d-model-re-evaluation) are
|
The local map workstreams (H–M) in [`TODO.md`](../../TODO.md#3d-model-and-local-map-re-evaluation) are
|
||||||
planned, not implemented; there are no map-generation commands yet. The runtime
|
planned, not implemented; there are no map-generation commands yet. The runtime
|
||||||
contract, provenance rules, budget/navigation gates and fallback are in
|
contract, provenance rules, budget/navigation gates and fallback are in
|
||||||
[`architecture.md#venue-implementation-contract`](architecture.md#venue-implementation-contract).
|
[`architecture.md#venue-implementation-contract`](../project/architecture.md#venue-implementation-contract).
|
||||||
The detailed pipeline/task list lives in `TODO.md`.
|
The detailed pipeline/task list lives in `TODO.md`.
|
||||||
|
|
||||||
## Confirmed game assets
|
## Confirmed game assets
|
||||||
@@ -313,9 +335,9 @@ Everything below is audited and shipped in the game; development-only outputs
|
|||||||
|
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
|  |  |
|
|  |  |
|
||||||
|  |  |
|
|  |  |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
- **Surface textures:** the v2 picks above (brick, sidewalk pavers, dry and wet asphalt, awning canvas) plus their normal maps, loaded by `src/game/materials.gd` and `WorldBuilder`; the three skyline panoramas are switched per shift phase. The first-generation tiles and `assets/textures/skyline.png` are no longer loaded.
|
- **Surface textures:** the v2 picks above (brick, sidewalk pavers, dry and wet asphalt, awning canvas) plus their normal maps, loaded by `src/game/materials.gd` and `WorldBuilder`; the three skyline panoramas are switched per shift phase. The first-generation tiles and `assets/textures/skyline.png` are no longer loaded.
|
||||||
- **UI art:** `assets/textures/ai/game_ready/icons/` (flashlight, door lock, wand, REC) and `assets/textures/ai/game_ready/cards/` (ID, wristband, ticket, credential, guest list), loaded by `src/game/ui/hud.gd`.
|
- **UI art:** `assets/textures/ai/game_ready/icons/` (flashlight, door lock, wand, REC) and `assets/textures/ai/game_ready/cards/` (ID, wristband, ticket, credential, guest list), loaded by `src/game/ui/hud.gd`.
|
||||||
@@ -489,7 +511,7 @@ remain optional interactive exploration; the headless commands stay the build an
|
|||||||
## Realism pass: scene concepts, skylines and textures
|
## Realism pass: scene concepts, skylines and textures
|
||||||
|
|
||||||
The skyline, surface tiles and phase lighting were rebuilt against AI concept frames. The
|
The skyline, surface tiles and phase lighting were rebuilt against AI concept frames. The
|
||||||
concepts live in [`docs/screens/concepts/`](../docs/screens/concepts/README.md); the validated
|
concepts live in [`docs/screens/concepts/`](../screens/concepts/README.md); the validated
|
||||||
picks the game loads are in `assets/textures/ai/game_ready/v2/picks/` (day/dusk/night
|
picks the game loads are in `assets/textures/ai/game_ready/v2/picks/` (day/dusk/night
|
||||||
panoramas, brick, sidewalk pavers, dry and wet asphalt, awning canvas, each with a normal
|
panoramas, brick, sidewalk pavers, dry and wet asphalt, awning canvas, each with a normal
|
||||||
map).
|
map).
|
||||||
@@ -549,7 +571,7 @@ contract.
|
|||||||
|
|
||||||
`tools/npc_proportions.py` checks the eight character GLBs against the shared
|
`tools/npc_proportions.py` checks the eight character GLBs against the shared
|
||||||
height/head/shoulder/hip/torso/leg/arm/foot guide; the current results are in
|
height/head/shoulder/hip/torso/leg/arm/foot guide; the current results are in
|
||||||
[`npc-visual-review.md`](npc-visual-review.md#proportion-audit). It reads the exported GLBs
|
[`3d-model-review.md`](3d-model-review.md#character-measurements). It reads the exported GLBs
|
||||||
and does not require Blender.
|
and does not require Blender.
|
||||||
|
|
||||||
`capture_npc_pose.gd` is the pose/deformation harness for the 3D re-evaluation: idle,
|
`capture_npc_pose.gd` is the pose/deformation harness for the 3D re-evaluation: idle,
|
||||||
@@ -574,7 +596,7 @@ camera, studio lighting and no venue/HUD/animation. The raw PNGs stay in
|
|||||||
`tmp/`; `tools/npc_baseline.py sheet` builds the committed contact sheet, and
|
`tmp/`; `tools/npc_baseline.py sheet` builds the committed contact sheet, and
|
||||||
`tools/npc_baseline.py compare --before DIR --after DIR` builds the review
|
`tools/npc_baseline.py compare --before DIR --after DIR` builds the review
|
||||||
comparison after a model change. See
|
comparison after a model change. See
|
||||||
[`npc-visual-review.md`](npc-visual-review.md).
|
[`3d-model-review.md`](3d-model-review.md).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
godot --path . --script res://src/test/capture_npc_baseline.gd -- \
|
godot --path . --script res://src/test/capture_npc_baseline.gd -- \
|
||||||
@@ -611,7 +633,7 @@ texture detail 1.2, backdrop 2.0 and characters 1.2; the Pillow metric gap was
|
|||||||
particularly lit night facades and dense backdrop detail. That is expected: the
|
particularly lit night facades and dense backdrop detail. That is expected: the
|
||||||
pass validated close-range surfaces and promoted the texture repairs, not a
|
pass validated close-range surfaces and promoted the texture repairs, not a
|
||||||
photoreal renderer. The 0.9.5 before/after close-up sheet is
|
photoreal renderer. The 0.9.5 before/after close-up sheet is
|
||||||
[`blender_previews/sheet_texture_refinement_0.9.5.jpg`](blender_previews/sheet_texture_refinement_0.9.5.jpg);
|
[`blender_previews/sheet_texture_refinement_0.9.5.jpg`](../blender_previews/sheet_texture_refinement_0.9.5.jpg);
|
||||||
the texture-adoption run itself was the earlier 0.8-style candidate comparison,
|
the texture-adoption run itself was the earlier 0.8-style candidate comparison,
|
||||||
and its report remains local/gitignored.
|
and its report remains local/gitignored.
|
||||||
|
|
||||||
@@ -1,18 +1,21 @@
|
|||||||
# Blender asset library
|
# Blender asset library
|
||||||
|
|
||||||
Architecture context: the asset contracts and fallback path are summarized in
|
Architecture context: the asset contracts and fallback path are summarized in
|
||||||
[`architecture.md`](architecture.md#content-and-asset-pipeline-architecture).
|
[`architecture.md`](../project/architecture.md#content-and-asset-pipeline-architecture).
|
||||||
|
|
||||||
Status: built, audited, and integrated (2026-11-01). `NpcAvatar` selects the
|
Status: built, audited, and integrated (2026-11-01). The active character migration
|
||||||
|
replaces the procedural body with a baked CC0 Quaternius base
|
||||||
|
([ADR-0017](../adr/0017-quaternius-npc-base.md)); the current library remains the shipped
|
||||||
|
fallback until the Quaternius 12-variant baseline passes review. `NpcAvatar` selects the
|
||||||
character variants and attaches the gear; `WorldBuilder` loads the prop library
|
character variants and attaches the gear; `WorldBuilder` loads the prop library
|
||||||
with colliders and phase-driven emissives. The 0.9.4 neutral baseline and its
|
with colliders and phase-driven emissives. The 0.9.4 neutral baseline and its
|
||||||
acceptance criteria are in [`npc-visual-review.md`](npc-visual-review.md);
|
acceptance criteria are in [`architecture.md`](../project/architecture.md#character-and-gear-asset-contract);
|
||||||
the committed 8 × 6 contact sheet is
|
the committed 8 × 6 contact sheet is
|
||||||
[`blender_previews/sheet_npc_baseline.jpg`](blender_previews/sheet_npc_baseline.jpg).
|
[`blender_previews/sheet_npc_baseline.jpg`](../blender_previews/sheet_npc_baseline.jpg).
|
||||||
|
|
||||||
Generator: [`tools/blender_assets.py`](../tools/blender_assets.py). Manifest (the
|
Generator: [`tools/blender_assets.py`](../../tools/blender_assets.py). Manifest (the
|
||||||
source of truth for integration):
|
source of truth for integration):
|
||||||
[`assets/models/blender/manifest.json`](../assets/models/blender/manifest.json).
|
[`assets/models/blender/manifest.json`](../../assets/models/blender/manifest.json).
|
||||||
|
|
||||||
## Art direction
|
## Art direction
|
||||||
|
|
||||||
@@ -63,7 +66,7 @@ flatpak run org.blender.Blender --background \
|
|||||||
flatpak run org.blender.Blender --background \
|
flatpak run org.blender.Blender --background \
|
||||||
--python "$PWD/tools/npc_parts.py" -- extract --part hand_l --variant npc_casual \
|
--python "$PWD/tools/npc_parts.py" -- extract --part hand_l --variant npc_casual \
|
||||||
--out "$PWD/tmp/npc-parts/npc_casual/hand_l.glb"
|
--out "$PWD/tmp/npc-parts/npc_casual/hand_l.glb"
|
||||||
# Assemble a variant (currently rebuilds the procedural character)
|
# Assemble a variant (current fallback path; Quaternius migration in progress)
|
||||||
flatpak run org.blender.Blender --background \
|
flatpak run org.blender.Blender --background \
|
||||||
--python "$PWD/tools/npc_parts.py" -- assemble --variant npc_casual \
|
--python "$PWD/tools/npc_parts.py" -- assemble --variant npc_casual \
|
||||||
--out "$PWD/tmp/npc-parts/npc_casual/assembled.glb"
|
--out "$PWD/tmp/npc-parts/npc_casual/assembled.glb"
|
||||||
@@ -139,10 +142,22 @@ render about 2.5 min.
|
|||||||
|
|
||||||
## Characters
|
## Characters
|
||||||
|
|
||||||
All library variants share the [character and gear asset contract](architecture.md#character-and-gear-asset-contract):
|
All library variants share the
|
||||||
`npc_base` mesh node, required 13 core bones (optional extras allowed), five
|
[character and gear asset contract](../project/architecture.md#character-and-gear-asset-contract):
|
||||||
tint slots, +Z visual front, 16,000/16,000 character budget and the same 256²
|
`npc_base` mesh node, five tint slots, +Z visual front, 24,000/24,000 character budget and the
|
||||||
slot-map/AO rules. Role selection and look notes:
|
same 256² slot-map/AO rules. The shipped roster is on the 62-joint Quaternius skeleton
|
||||||
|
(ADR-0018); the procedural fallback built by `build --source procedural` keeps the 13 core bones.
|
||||||
|
Both are accepted by `audit`, `inspect`, the runtime bone map and the tests.
|
||||||
|
|
||||||
|
The three Quaternius sources (`casual`, `hoodie`, `worker`) live in
|
||||||
|
`assets/models/blender_src/quaternius/` as build inputs. `build` (default
|
||||||
|
`--source quaternius`) does a two-pass bake per character: a cached T-pose round trip that joins
|
||||||
|
without welding, maps the upstream materials onto the five slots and unwraps the degenerate
|
||||||
|
source UVs, then an arm-down rest bake exported with `export_apply=False`. The per-character slot
|
||||||
|
map, triangle counts and measurements are in
|
||||||
|
[`npc-model-sourcing.md#shipped-roster-099-owner-chose-the-full-swap`](npc-model-sourcing.md#shipped-roster-099-owner-chose-the-full-swap).
|
||||||
|
|
||||||
|
Role selection and look notes (tint + gear now carry the role, not the mesh):
|
||||||
|
|
||||||
| Character | `layer_for()` / look | Suggested roles | Preview gear |
|
| Character | `layer_for()` / look | Suggested roles | Preview gear |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
@@ -161,6 +176,22 @@ colour texture. The current `_apply_outfit_materials()` sets
|
|||||||
`albedo_color = WHITE` on any slot it does not recognise, and these keep their
|
`albedo_color = WHITE` on any slot it does not recognise, and these keep their
|
||||||
colour through that. When integrating, tint only the five contract slots.
|
colour through that. When integrating, tint only the five contract slots.
|
||||||
|
|
||||||
|
**Hair part library.** Each base ships one hair shell and the build reshapes it in place
|
||||||
|
(`QUATERNIUS_HAIR_PARTS`): `short` is identity, `buzz` squashes toward the hairline, `long` stretches
|
||||||
|
from the crown. The role picks the style through `CHARACTERS[...]["hair"]`, and the T-pose cache is
|
||||||
|
keyed on it. `bald` is only allowed on the `casual` and `hoodie` bases, where the skin closes the
|
||||||
|
skull; the modular Worker's head stops at the hairline, so removing its hair would open the crown.
|
||||||
|
|
||||||
|
**Face detail.** None of the three Quaternius heads ships a mouth or eye whites, so the build adds
|
||||||
|
both: `_add_quaternius_mouth()` places a lip block on the measured skin surface, and
|
||||||
|
`_add_quaternius_eye_whites()` renames the eye quads to `sclera` and adds a shrunken `pupil` copy in
|
||||||
|
front of each. Both are fixed-colour (not tint slots), so they survive the role palettes.
|
||||||
|
|
||||||
|
**Head gear fit.** Head gear is authored for the shipped Quaternius head:
|
||||||
|
`HEAD_GEAR_SCALE = 0.64` (0.201 m base head against the 0.315 m procedural one) and
|
||||||
|
`HEAD_GEAR_LIFT = 0.07` (its centre sits higher). The procedural fallback therefore wears slightly
|
||||||
|
undersized caps — cosmetic and fallback-only.
|
||||||
|
|
||||||
**Runtime tint notes (implemented).** Only the five contract slots are tinted;
|
**Runtime tint notes (implemented).** Only the five contract slots are tinted;
|
||||||
fixed detail materials keep their authored colour. On `npc_vest` the vest is the
|
fixed detail materials keep their authored colour. On `npc_vest` the vest is the
|
||||||
fixed `hivis` material and `cloth` is the undershirt, so the yellow override is
|
fixed `hivis` material and `cloth` is the undershirt, so the yellow override is
|
||||||
@@ -170,7 +201,42 @@ the role's `TYPE_COLORS`.
|
|||||||
## Gear attach points
|
## Gear attach points
|
||||||
|
|
||||||
Gear is authored in attach-point space; the exact contract and runtime fit offsets are in
|
Gear is authored in attach-point space; the exact contract and runtime fit offsets are in
|
||||||
[`architecture.md#character-and-gear-asset-contract`](architecture.md#character-and-gear-asset-contract).
|
[`architecture.md#character-and-gear-asset-contract`](../project/architecture.md#character-and-gear-asset-contract).
|
||||||
|
|
||||||
|
The shipped matrix is **fifteen pieces** since the hat removal (owner, 2026-11-06): `cap` and
|
||||||
|
`hood` are retired, and `firefighter_helmet` is the only head item.
|
||||||
|
|
||||||
|
| Attach | Pieces |
|
||||||
|
| --- | --- |
|
||||||
|
| head | `firefighter_helmet`, `sunglasses` |
|
||||||
|
| back | `backpack`, `shoulder_bag`, `scba_tank` |
|
||||||
|
| chest | `lanyard` |
|
||||||
|
| hand | `phone`, `cup`, `clipboard`, `umbrella`, `camera`, `protest_sign`, `flashlight`, `wand`, `radio` |
|
||||||
|
|
||||||
|
### Hand-item fit on the Quaternius rig
|
||||||
|
|
||||||
|
The hand attach point moved from Godot y 0.78 (procedural wrist) to **y 1.017** (Quaternius
|
||||||
|
wrist), so `fit` measures hand gear against the new wrist instead of the authored attach offset.
|
||||||
|
Run `blender_assets.py fit`; per item it reports the grip drop, the lowest point at rest, whether
|
||||||
|
that clears the hip line (0.95) and `size_vs_head` — the proportion that makes "reads oversized"
|
||||||
|
measurable on the 0.20 m head.
|
||||||
|
|
||||||
|
| Item | Drop (m) | Lowest at rest | Clears hip | Longest | × head |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| `camera` | 0.053 | 0.964 | yes | 0.138 | 0.69 |
|
||||||
|
| `phone` | 0.105 | 0.912 | no | 0.150 | 0.75 |
|
||||||
|
| `cup` | 0.110 | 0.907 | no | 0.142 | 0.71 |
|
||||||
|
| `radio` | 0.108 | 0.909 | no | 0.203 | 1.01 |
|
||||||
|
| `flashlight` | 0.077 | 0.940 | no | 0.243 | 1.14 |
|
||||||
|
| `wand` | 0.125 | 0.892 | no | 0.400 | 1.87 |
|
||||||
|
| `umbrella` | 0.201 | 0.816 | no | 0.900 | 4.48 |
|
||||||
|
| `clipboard` | 0.375 | 0.642 | no | 0.305 | 1.63 |
|
||||||
|
| `protest_sign` | 0.250 | 0.767 | no | 1.230 | 6.12 |
|
||||||
|
|
||||||
|
Falling below the hip line is normal for a carried object; the number that matters is whether the
|
||||||
|
item was *authored* for the new grip. Only the `clipboard` was: its grip sat in the middle of the
|
||||||
|
board, so it swung through the thigh. It now grips the top edge (0.22 × 0.30 m) like a carried
|
||||||
|
clipboard, and `HAND_ITEM_AUTHORED_SIZE` in the tool flags any future drift past 10 %.
|
||||||
|
|
||||||
## Props
|
## Props
|
||||||
|
|
||||||
@@ -200,7 +266,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
|
||||||
@@ -212,7 +278,7 @@ carry baked AO and the shared neutral material maps described above.
|
|||||||
`npc_base`, the bones accept `NpcAvatar`'s pose composition, and props are
|
`npc_base`, the bones accept `NpcAvatar`'s pose composition, and props are
|
||||||
grounded.
|
grounded.
|
||||||
- `tools/test_model_review.py`: every `CHARACTERS`/`GEAR`/`PROPS` entry has a
|
- `tools/test_model_review.py`: every `CHARACTERS`/`GEAR`/`PROPS` entry has a
|
||||||
scorecard row and verdict in `docs/3d-model-review.md` (coverage gate).
|
scorecard row and verdict in `docs/assets/3d-model-review.md` (coverage gate).
|
||||||
- `src/test/tests/test_world.gd`: every library prop that blocks walking has a
|
- `src/test/tests/test_world.gd`: every library prop that blocks walking has a
|
||||||
`StaticBody3D` + `NavigationObstacle3D`, checked against the catalogue
|
`StaticBody3D` + `NavigationObstacle3D`, checked against the catalogue
|
||||||
(collider/proxy gate).
|
(collider/proxy gate).
|
||||||
@@ -235,4 +301,4 @@ carry baked AO and the shared neutral material maps described above.
|
|||||||
chin/cheekbone, nose, lips) but its `seg=18/rings=12` head still reads
|
chin/cheekbone, nose, lips) but its `seg=18/rings=12` head still reads
|
||||||
somewhat faceted at portrait range; a subdivision/deeper-sculpt prototype is
|
somewhat faceted at portrait range; a subdivision/deeper-sculpt prototype is
|
||||||
gated on the owner scorecard review. The full ranked list and measurements are
|
gated on the owner scorecard review. The full ranked list and measurements are
|
||||||
in [`npc-visual-review.md`](npc-visual-review.md).
|
in [`3d-model-review.md`](3d-model-review.md).
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
# MakeHuman head prototype
|
||||||
|
|
||||||
|
Status: **retained fallback; superseded as the active NPC head by the Quaternius
|
||||||
|
base (ADR-0017).** The owner accepted the basic human head on 2026-11-04. The automated vision gate
|
||||||
|
still records REJECT on the eye/lid region as deferred polish. The asset is a
|
||||||
|
standalone head/neck extracted from the CC0 MakeHuman base. The assembled path
|
||||||
|
adds hair, a hidden scalp trim and the procedural body. The 12 shipped GLBs have
|
||||||
|
not been rebuilt with it, and the Quaternius migration replaces it as the active
|
||||||
|
base. The development source files were removed from `tmp/` on 2026-11-05.
|
||||||
|
|
||||||
|
## Asset
|
||||||
|
|
||||||
|
- GLB: [`assets/models/blender_src/makehuman_head.glb`](../../assets/models/blender_src/makehuman_head.glb)
|
||||||
|
- Review sheet: [`blender_previews/sheet_makehuman_head.jpg`](../blender_previews/sheet_makehuman_head.jpg)
|
||||||
|
- Source workflow (development-only, files removed after the Quaternius pivot;
|
||||||
|
retained here as the historical method) — extracts the MakeHuman head, cuts it at the neck, keeps the head/eye/mouth
|
||||||
|
components, cuts an almond aperture through a skin eyelid mask, adds recessed
|
||||||
|
eyeballs with flat iris/pupil discs, anchors brows to the face surface, renders
|
||||||
|
front/three-quarter/profile and exports the standalone GLB.
|
||||||
|
- Measurements (final standalone build, `inspect`): **12,641 triangles / 7,690
|
||||||
|
split vertices**; bounds approximately `x ±0.094 m`, `y -0.180…0.042 m`,
|
||||||
|
`z 1.530…1.803 m` in project Z-up space.
|
||||||
|
- Assembled `npc_casual --head mh`: **14,753 triangles / 12,823 seam-split
|
||||||
|
vertices / 14 bones / 9 materials**, `inspect` clean. All 12 variants count
|
||||||
|
14,693–15,987 triangles with the same head.
|
||||||
|
- Materials used: `skin`, `eye_white`, `iris`, `pupil`, `hair`. No textures are
|
||||||
|
baked into this prototype.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## What was done
|
||||||
|
|
||||||
|
1. Imported the CC0 MakeHuman base OBJ and cleared the importer axis rotation.
|
||||||
|
2. Applied the project scale/axis transform: 1.82 m body, Z-up, metres,
|
||||||
|
front −Y.
|
||||||
|
3. Cut the head at the neck (`z ≈ 1.53`) rather than keeping the cut shoulders;
|
||||||
|
capped the neck opening.
|
||||||
|
4. Built an eyelid mask by subtracting an almond aperture from a skin sphere
|
||||||
|
centred on each eye (`solver = "EXACT"`), then recessed the globes so the
|
||||||
|
cornea sits behind the lid plane.
|
||||||
|
5. Added flat iris/pupil discs on the globe axis; disabled backface culling so
|
||||||
|
the discs stay visible at three-quarter angles.
|
||||||
|
6. Anchored brow strips to the skin with object-space ray casts and added a
|
||||||
|
shallow supraorbital ridge so they do not float, then reduced the crown
|
||||||
|
height to improve the profile silhouette.
|
||||||
|
7. Fixed a material-remap bug introduced by joining the extra eye objects: the
|
||||||
|
joined head faces were pointing at the `eye_white` slot, making the whole
|
||||||
|
head render as white clay. The largest connected component is now forced
|
||||||
|
back onto `skin` after the join.
|
||||||
|
8. Rendered front/three-quarter/profile views in a neutral review studio and
|
||||||
|
exported the standalone GLB.
|
||||||
|
|
||||||
|
## Provenance
|
||||||
|
|
||||||
|
- Base mesh: MakeHuman / MPFB base, CC0, from the local research set
|
||||||
|
(development source files removed after the 2026-11-05 Quaternius pivot); see
|
||||||
|
[`CREDITS.md`](../../CREDITS.md).
|
||||||
|
- The head is a **derived prototype**, not a shipped NPC. It does not enter
|
||||||
|
`assets/models/blender/npc/`, `npc_base`, the runtime `NpcAvatar` path, CI, or
|
||||||
|
a release package. It is retained as a fallback, not the active NPC base.
|
||||||
|
- Source photographs/proportions are not used as textures here; this is a
|
||||||
|
geometry-only head built from the researched model data.
|
||||||
|
|
||||||
|
## Review criteria
|
||||||
|
|
||||||
|
Accept only if:
|
||||||
|
|
||||||
|
- the head reads as human at front/three-quarter/profile and the neck is a
|
||||||
|
clean head/bust silhouette, not a shoulder cut;
|
||||||
|
- eyes, brow, nose, mouth and ears are readable without spikes, holes or
|
||||||
|
floating shells;
|
||||||
|
- the asset is inside the character budget and has no script/contract violation;
|
||||||
|
- the prototype remains clearly local and un-integrated until the part pipeline
|
||||||
|
is approved.
|
||||||
|
|
||||||
|
## Judge result
|
||||||
|
|
||||||
|
**Owner verdict: ACCEPT (basic human head, 2026-11-04).**
|
||||||
|
**Automated vision gate: REJECT** (vision judge `z-ai/glm-5.3-flash`, final
|
||||||
|
standalone build render set above). The eye/lid findings below remain deferred
|
||||||
|
polish; they are no longer a rollout blocker because the owner accepted the head.
|
||||||
|
|
||||||
|
Blocking findings:
|
||||||
|
|
||||||
|
- **P0 — globe depth is inconsistent across views.** The front/three-quarter
|
||||||
|
reads still show a bead-like iris with a pale sclera halo, while the profile
|
||||||
|
reduces the eye to a brown sliver. The judge reads this as a faked recess
|
||||||
|
rather than a socketed globe under a lid.
|
||||||
|
- **P0 — no convincing lid overlap.** The iris remains nearly circular in front
|
||||||
|
and the upper lid does not visibly clip the globe; the skin lid mask reads as
|
||||||
|
a crater around a bead.
|
||||||
|
- **P0 — iris orientation reads decal-locked** at three-quarter, so the gaze
|
||||||
|
appears to drift off the head axis.
|
||||||
|
- **P0 — the aperture/lid mask is too circular** and lacks medial/lateral
|
||||||
|
canthi, so the eye still reads as a doll eye at portrait distance.
|
||||||
|
|
||||||
|
Should-fix findings:
|
||||||
|
|
||||||
|
- the brow tubes are better anchored but the medial ends still detach in
|
||||||
|
three-quarter/profile;
|
||||||
|
- nose lacks a defined tip/wing and nostrils;
|
||||||
|
- mouth is a faint geometric seam with no lip volume;
|
||||||
|
- crown/back-of-skull is still faceted and egg-like in profile;
|
||||||
|
- the catchlight is baked geometry and is not consistent between eyes.
|
||||||
|
|
||||||
|
What passed: the skin/eye material remap is correct, the eye openings are
|
||||||
|
closed, the standalone GLB reports **12,641 triangles / 7,690 split vertices**,
|
||||||
|
and an assembled `npc_casual` with this head passes `inspect` at **14,753 /
|
||||||
|
16,000 triangles, 12,823 seam-split vertices, 14 bones, no issues**.
|
||||||
|
|
||||||
|
Known limits: bald mannequin-like presentation, stylized geometry-only
|
||||||
|
iris/pupil, no rig, no UV texture pass, and the neck cap is a review cut rather
|
||||||
|
than a body-welded seam.
|
||||||
|
|
||||||
|
## Assembled prototype (2026-11-04)
|
||||||
|
|
||||||
|
- `_makehuman_head` imports the GLB and adds a **skull-conforming hair cap**
|
||||||
|
derived from the closed head shell (scaled shell + boolean front-sphere
|
||||||
|
cut + decimate). Hair skips the old `hair_normal.png` because the skull UVs
|
||||||
|
produced large dark tangent patches.
|
||||||
|
- Head faces fully covered by the cap are deleted to recover ~950 triangles;
|
||||||
|
boundary faces stay as a safety band, so the accepted face geometry is
|
||||||
|
untouched. The hidden neck plug uses 12 segments.
|
||||||
|
- The procedural body was narrowed at the neck and shoulders (chest 0.158,
|
||||||
|
neck base 0.060, neck top 0.054, shoulder root z 1.345) and its skin decimate
|
||||||
|
dropped to 0.21 so all 12 variants fit the 16,000 cap.
|
||||||
|
- Local review renders were removed with the 2026-11-05 `tmp/` cleanup; the
|
||||||
|
committed review sheet above is the retained evidence.
|
||||||
|
|
||||||
|
## Deferred polish
|
||||||
|
|
||||||
|
- Replace the radial lid mask with real upper/lower lid masses that fold over
|
||||||
|
the globe, with pointed canthi, and pass the profile view.
|
||||||
|
- Move the iris onto a curved cornea cap so its orientation follows the globe at
|
||||||
|
three-quarter angles, and use a lighting-driven catchlight instead of baked
|
||||||
|
white geometry.
|
||||||
|
- Refine the hair cap silhouette (current short cap reads as a helmet) and
|
||||||
|
improve the full-body shoulder/arm shape before the 12-variant rollout.
|
||||||
|
- Add a clean UV/material pass and a contract armature/weights when the head
|
||||||
|
becomes part of the shipped library characters.
|
||||||
@@ -0,0 +1,380 @@
|
|||||||
|
# NPC Model Sourcing
|
||||||
|
|
||||||
|
This page records the source evaluation and the active character plan. The
|
||||||
|
decision is [ADR-0017](../adr/0017-quaternius-npc-base.md), which supersedes the
|
||||||
|
generator-first sourcing decision in [ADR-0015](../adr/0015-npc-model-variety-sourcing.md).
|
||||||
|
|
||||||
|
## 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](https://quaternius.com/packs/ultimatemodularcharacters.html)
|
||||||
|
and [Ultimate Modular Women](https://quaternius.com/packs/ultimatemodularwomen.html),
|
||||||
|
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](../adr/0018-quaternius-stage2-runtime-rig.md) 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).
|
||||||
|
|
||||||
|
## Pilot bake and shipped state (2026-11-05)
|
||||||
|
|
||||||
|
`npc_casual` is the first Quaternius-derived character. The reproducible pipeline lives in
|
||||||
|
`tmp/npc-research/` (local tooling, not shipped) and has two steps:
|
||||||
|
|
||||||
|
1. `build_base_minimal.py` — import `quaternius/Casual_Hoodie.glb`, join the four skinned meshes
|
||||||
|
**without welding**, rename the upstream materials to the project tint slots, Smart-UV-unwrap
|
||||||
|
and repack, export `quaternius_tpose.glb`.
|
||||||
|
2. `bake_armdown_v5.py` — pose `UpperArm.L/R` −90° local X, read the posed matrices, apply the
|
||||||
|
Armature modifier, **reset the pose to identity**, set the rest matrices, re-add the modifier,
|
||||||
|
export `quaternius_base.glb` and save `assets/models/blender_src/npc_casual.blend` for the AO
|
||||||
|
bake.
|
||||||
|
|
||||||
|
Then `tools/bake_ao.py --only npc_casual` and a copy of the GLB to
|
||||||
|
`assets/models/blender/npc/npc_casual.glb`.
|
||||||
|
|
||||||
|
| Measurement | npc_casual (Quaternius) | procedural library |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Triangles | 6,206 | 4,812–6,046 |
|
||||||
|
| glTF vertices | 12,988 | 4,908–5,785 |
|
||||||
|
| Bones | 62 | 13 |
|
||||||
|
| Head height / body height | 0.134 | 0.16–0.22 (stylized band) |
|
||||||
|
| Shoulder width | 0.201 m head width, `fit` OK | `fit` OK |
|
||||||
|
| Texel density (256² maps) | 73–74 px/m | 75–96 px/m |
|
||||||
|
| Materials | `skin`, `cloth`, `pants`, `hair`, `accessory` + fixed `Eye`, `Eyebrows` | five slots + fixed detail |
|
||||||
|
|
||||||
|
Two source quirks shaped the bake:
|
||||||
|
|
||||||
|
- the upstream UV map is degenerate (every loop at 0,0) and its materials are flat colours, so the
|
||||||
|
AO/texture bake must follow a real unwrap or it silently writes a black map;
|
||||||
|
- the upstream materials are named `Skin`/`Purple`/`LightBlue`/`White`/`Hair`, so the five-slot
|
||||||
|
contract is applied as a rename, not a re-author.
|
||||||
|
|
||||||
|
The face/silhouette gate that chose the full swap is recorded in the follow-up decision of
|
||||||
|
[ADR-0018](../adr/0018-quaternius-stage2-runtime-rig.md); its comparison sheets were retired with the
|
||||||
|
review pages.
|
||||||
|
|
||||||
|
## Shipped roster (0.9.9, owner chose the full swap)
|
||||||
|
|
||||||
|
Every public character name is baked from one of the three CC0 sources. The build is
|
||||||
|
`tools/blender_assets.py build` (default `--source quaternius`); the sources live in
|
||||||
|
`assets/models/blender_src/quaternius/` and the geometry pipeline is two passes:
|
||||||
|
|
||||||
|
1. `_quaternius_tpose_glb()` — import, drop the Icosphere helper, join **without welding**,
|
||||||
|
repoint the upstream materials onto the five tint slots, Smart-UV-unwrap + repack, export an
|
||||||
|
intermediate T-pose GLB. The round trip also normalises the mirrored upstream bone rolls,
|
||||||
|
which is what makes the next pass symmetric.
|
||||||
|
2. `_bake_quaternius_rest()` — pose `UpperArm.L/R` -90° local X, read the posed matrices, apply
|
||||||
|
the Armature modifier, reset the pose, write the rest matrices, re-add the modifier, export
|
||||||
|
with `export_apply=False`.
|
||||||
|
|
||||||
|
Then `tools/bake_ao.py --only <name>`.
|
||||||
|
|
||||||
|
| Character | Source | Tris | Material slots |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `npc_casual` | hoodie | 6,206 | skin, cloth, pants, hair, accessory + Eye, Eyebrows |
|
||||||
|
| `npc_jacket` | casual | 6,424 | five slots + eyes/brows |
|
||||||
|
| `npc_coat` | hoodie | 6,206 | five slots + eyes/brows |
|
||||||
|
| `npc_vest` | worker | 5,240 | five slots + hivis vest/hat, eyes, moustache |
|
||||||
|
| `npc_dress` | casual | 6,424 | five slots + eyes/brows |
|
||||||
|
| `npc_hoodie` | hoodie | 6,206 | five slots + eyes/brows |
|
||||||
|
| `npc_firefighter` | worker (vest + hat dropped) | 4,458 | five slots + eyes, moustache |
|
||||||
|
| `npc_guard` | worker (vest + hat dropped) | 4,458 | five slots + eyes, moustache |
|
||||||
|
| `npc_crowd_a` | casual | 6,424 | five slots + eyes/brows |
|
||||||
|
| `npc_crowd_b` | casual | 6,424 | five slots + eyes/brows |
|
||||||
|
| `npc_crowd_c` | hoodie | 6,206 | five slots + eyes/brows |
|
||||||
|
| `npc_crowd_d` | worker (vest + hat dropped) | 4,458 | five slots + eyes, moustache |
|
||||||
|
|
||||||
|
Source slot maps (`QUATERNIUS_SOURCES`): the `casual` tee is `Skin`/`White`/`Orange`/`Grey`/
|
||||||
|
`Hair_Blond`; the hoodie is `Skin`/`Purple`/`LightBlue`/`Hair`/`White`; the worker is `Skin`/
|
||||||
|
`LightBrown`/`Brown`+`Brown2`/`Grey`+`Black`/`Eyebrows`. Everything not in the map keeps its
|
||||||
|
authored colour (eyes, brows, moustache, hivis vest and hard hat), so the contract still holds if
|
||||||
|
upstream adds a material — it shows up as an extra fixed-colour slot instead of vanishing.
|
||||||
|
|
||||||
|
Head gear is authored for this head: `HEAD_GEAR_SCALE = 0.64` and `HEAD_GEAR_LIFT = 0.07` map the
|
||||||
|
0.315 m procedural head onto the 0.201–0.214 m Quaternius head. The procedural fallback therefore
|
||||||
|
wears slightly small hats.
|
||||||
|
|
||||||
|
## Modular outfit intake (2026-11-06)
|
||||||
|
|
||||||
|
The owner downloaded the *Ultimate Modular Men* pack once (CC0 1.0, 54.5 MB zip, 15 outfit families
|
||||||
|
plus weapons and a horse) into the gitignored `tmp/quaternius-intake/`. The pack ships FBX, not GLB,
|
||||||
|
so the intake composes each family into a single skinned base:
|
||||||
|
|
||||||
|
python3 tools/quaternius_parts.py make-base \
|
||||||
|
--family "tmp/quaternius-intake/Ultimate Modular Men- Feb 2022/Separate Skeletal Meshes and Animations/Suit" \
|
||||||
|
--out assets/models/blender_src/quaternius/Suit.glb
|
||||||
|
|
||||||
|
What `make-base` has to undo, and why it is not a straight import:
|
||||||
|
|
||||||
|
1. each of the four FBX files carries its own copy of the armature — one is kept and the meshes are
|
||||||
|
repointed at it, otherwise `join` leaves three meshes bound to deleted armatures;
|
||||||
|
2. the FBX rig adds zero-length `_end` leaf bones and a `neutral_bone` root; Godot's importer fails
|
||||||
|
the exported GLB with them (`resource_format_binary` error), so they are stripped back to the
|
||||||
|
accepted 62 joints;
|
||||||
|
3. the object transforms are baked before export, or the glTF node transforms change the rest pose
|
||||||
|
on import and the character renders with a giant head;
|
||||||
|
4. the pack reuses one fabric material for jacket and trousers, so the leg meshes get their own
|
||||||
|
`*_legs` copies that the slot map sends to `pants`;
|
||||||
|
5. imported parts share seams, which leaves zero-area triangles the audit rejects.
|
||||||
|
|
||||||
|
The pack itself is never committed. Only the composed bases are, with their SHA-256 here and in
|
||||||
|
`CREDITS.md`.
|
||||||
|
|
||||||
|
| Base | Source family | SHA-256 | Used by |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `Suit.glb` | Suit | `674f2a63…` | `npc_coat` |
|
||||||
|
| `Adventurer.glb` | Adventurer | `062caf69…` | `npc_crowd_c` |
|
||||||
|
| `Beach.glb` | Beach | `81c69837…` | `npc_crowd_a` |
|
||||||
|
| `Casual_2.glb` | Casual_2 | `fe4edb73…` | `npc_jacket` |
|
||||||
|
| `Farmer.glb` | Farmer | `b9b67058…` | `npc_crowd_b` (hair slot patched) |
|
||||||
|
| `King.glb` | King | `85aae2a0…` | `npc_dress` |
|
||||||
|
| `Punk.glb` | Punk | `56993274…` | `npc_hoodie` (the mohawk is the `Red` material) |
|
||||||
|
| `Swat.glb` | Swat | `43659684…` | **not used** — authored facing the other way; see below |
|
||||||
|
|
||||||
|
The roster therefore runs **eleven distinct outfits across twelve roles** (the worker base serves
|
||||||
|
`npc_vest`, `npc_firefighter`, `npc_guard` and `npc_crowd_d`).
|
||||||
|
|
||||||
|
### Open: the Swat base faces backwards
|
||||||
|
|
||||||
|
`Swat.glb` is authored facing Godot −Z. Rotating the exported base about world Z rotates the skin
|
||||||
|
with the armature node and the character renders headless, and rotating the mesh as well collapses
|
||||||
|
it into a spike; the reliable fix is to yaw the four FBX parts *before* the join and re-bake. Until
|
||||||
|
then `npc_guard` stays on the worker base.
|
||||||
|
|
||||||
|
### Slots a family cannot paint
|
||||||
|
|
||||||
|
`Farmer` has no hair shell and `Swat`/`SpaceSuit` have neither hair nor skin. The audit and the
|
||||||
|
runtime both need the five slots as *used* materials, so `patch_slots` buries a 4 cm triangle
|
||||||
|
inside the skull or the pelvis for each missing slot (`_patch_missing_slots`). It is invisible, it
|
||||||
|
keeps the material in the export, and it means a helmeted head still satisfies the contract.
|
||||||
|
|
||||||
|
## 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`](../../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`](../../DONE.md), [`MEMORY.md`](../../MEMORY.md) and the review docs.
|
||||||
|
|
||||||
|
## Related documents
|
||||||
|
|
||||||
|
- [ADR-0017: Quaternius NPC base](../adr/0017-quaternius-npc-base.md)
|
||||||
|
- [ADR-0016: 24,000-triangle character budget](../adr/0016-npc-character-budget-24k.md)
|
||||||
|
- [Blender asset contract](../project/architecture.md#character-and-gear-asset-contract)
|
||||||
|
- [`3d-model-review.md`](3d-model-review.md)
|
||||||
|
- [`asset-tooling.md`](asset-tooling.md)
|
||||||
@@ -9,6 +9,7 @@ capture harnesses.
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| [](sheet_npc.jpg) <br> `sheet_npc.jpg` | Eight skinned character variants (casual, jacket, coat, hi-vis vest, dress, hoodie, firefighter, guard) with their gear attach points. |
|
| [](sheet_npc.jpg) <br> `sheet_npc.jpg` | Eight skinned character variants (casual, jacket, coat, hi-vis vest, dress, hoodie, firefighter, guard) with their gear attach points. |
|
||||||
| [](sheet_npc_baseline.jpg) <br> `sheet_npc_baseline.jpg` | Neutral studio baseline: 8 characters x front, three-quarter, profile, back, full body and crowd views. |
|
| [](sheet_npc_baseline.jpg) <br> `sheet_npc_baseline.jpg` | Neutral studio baseline: 8 characters x front, three-quarter, profile, back, full body and crowd views. |
|
||||||
|
| [](sheet_makehuman_head.jpg) <br> `sheet_makehuman_head.jpg` | MakeHuman head: front, three-quarter and profile review views. The owner accepted the basic head; the automated vision gate still rejects the eye/lid region as deferred polish. See [`../makehuman-head-review.md`](../assets/makehuman-head-review.md). |
|
||||||
| [](sheet_npc_baseline_compare-body.jpg) <br> `sheet_npc_baseline_compare-body.jpg` | Neck/shoulder transition: fuller neck base and a lower shoulder root. |
|
| [](sheet_npc_baseline_compare-body.jpg) <br> `sheet_npc_baseline_compare-body.jpg` | Neck/shoulder transition: fuller neck base and a lower shoulder root. |
|
||||||
| [](sheet_npc_baseline_compare-face-detail.jpg) <br> `sheet_npc_baseline_compare-face-detail.jpg` | Face detail: nose ala wings, a single rounded mouth and a darker ear concha. |
|
| [](sheet_npc_baseline_compare-face-detail.jpg) <br> `sheet_npc_baseline_compare-face-detail.jpg` | Face detail: nose ala wings, a single rounded mouth and a darker ear concha. |
|
||||||
| [](sheet_npc_baseline_compare-face.jpg) <br> `sheet_npc_baseline_compare-face.jpg` | Face-depth pass: recessed sclera, upper lid and sculpted chin/cheek planes. |
|
| [](sheet_npc_baseline_compare-face.jpg) <br> `sheet_npc_baseline_compare-face.jpg` | Face-depth pass: recessed sclera, upper lid and sculpted chin/cheek planes. |
|
||||||
@@ -18,7 +19,7 @@ capture harnesses.
|
|||||||
| [](sheet_npc_baseline_compare-texuv.jpg) <br> `sheet_npc_baseline_compare-texuv.jpg` | 4x fabric weave with the baked per-character AO removed. |
|
| [](sheet_npc_baseline_compare-texuv.jpg) <br> `sheet_npc_baseline_compare-texuv.jpg` | 4x fabric weave with the baked per-character AO removed. |
|
||||||
| [](sheet_npc_baseline_compare-torso.jpg) <br> `sheet_npc_baseline_compare-torso.jpg` | Torso/hip taper without changing the skeleton or build multipliers. |
|
| [](sheet_npc_baseline_compare-torso.jpg) <br> `sheet_npc_baseline_compare-torso.jpg` | Torso/hip taper without changing the skeleton or build multipliers. |
|
||||||
| [](sheet_npc_crowd_prototypes.jpg) <br> `sheet_npc_crowd_prototypes.jpg` | Four approved crowd-variety looks queued for the 12-character roster. |
|
| [](sheet_npc_crowd_prototypes.jpg) <br> `sheet_npc_crowd_prototypes.jpg` | Four approved crowd-variety looks queued for the 12-character roster. |
|
||||||
| [](sheet_npc_gear.jpg) <br> `sheet_npc_gear.jpg` | Eighteen gear pieces authored in attach space: caps, hood, helmet, bags, tanks, lanyards and handheld items. |
|
| [](sheet_npc_gear.jpg) <br> `sheet_npc_gear.jpg` | Fifteen gear pieces authored in attach space: helmet, sunglasses, bags, tank, lanyard and the nine hand items. Caps and hoods are retired (owner, 2026-11-06). |
|
||||||
| [](sheet_npc_hands_compare.jpg) <br> `sheet_npc_hands_compare.jpg` | Hand pass: wider palms, segmented fingers and a separate thumb. |
|
| [](sheet_npc_hands_compare.jpg) <br> `sheet_npc_hands_compare.jpg` | Hand pass: wider palms, segmented fingers and a separate thumb. |
|
||||||
| [](sheet_npc_hands_grip_compare.jpg) <br> `sheet_npc_hands_grip_compare.jpg` | Grip pass: the forward hand-item offset that puts props in the palm. |
|
| [](sheet_npc_hands_grip_compare.jpg) <br> `sheet_npc_hands_grip_compare.jpg` | Grip pass: the forward hand-item offset that puts props in the palm. |
|
||||||
| [](sheet_head_proto_before_after.jpg) <br> `sheet_head_proto_before_after.jpg` | Head overhaul sign-off: current `_face` vs the s48 connected-shell prototype at 1.85 m front/three-quarter/profile. |
|
| [](sheet_head_proto_before_after.jpg) <br> `sheet_head_proto_before_after.jpg` | Head overhaul sign-off: current `_face` vs the s48 connected-shell prototype at 1.85 m front/three-quarter/profile. |
|
||||||
@@ -26,7 +27,5 @@ capture harnesses.
|
|||||||
| [](sheet_props.jpg) <br> `sheet_props.jpg` | Twenty street and venue props with baked maps, ground contact and collider footprints. |
|
| [](sheet_props.jpg) <br> `sheet_props.jpg` | Twenty street and venue props with baked maps, ground contact and collider footprints. |
|
||||||
| [](sheet_texture_refinement_0.9.5.jpg) <br> `sheet_texture_refinement_0.9.5.jpg` | 0.9.5 texture refinement before/after: pavers, awning stripes and NPC fabric. |
|
| [](sheet_texture_refinement_0.9.5.jpg) <br> `sheet_texture_refinement_0.9.5.jpg` | 0.9.5 texture refinement before/after: pavers, awning stripes and NPC fabric. |
|
||||||
|
|
||||||
The acceptance criteria for these sheets are in [`../npc-visual-review.md`](../npc-visual-review.md),
|
The measurements are in [`../3d-model-review.md`](../assets/3d-model-review.md) and the asset contract in
|
||||||
the measurements in [`../npc-visual-review.md#proportion-audit`](../npc-visual-review.md#proportion-audit) and
|
[`../blender-assets.md`](../assets/blender-assets.md).
|
||||||
[`../3d-model-review.md`](../3d-model-review.md), and the asset contract in
|
|
||||||
[`../blender-assets.md`](../blender-assets.md).
|
|
||||||
|
After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 132 KiB |
@@ -0,0 +1,13 @@
|
|||||||
|
# Design Documentation
|
||||||
|
|
||||||
|
Gameplay, venues, presentation and player-facing constraints.
|
||||||
|
|
||||||
|
- [`gameplay.md`](gameplay.md) — the playable loop, escalation mechanics, venues and tutorial.
|
||||||
|
- [`venues.md`](venues.md) — real-site evidence, game mapping and venue simplifications.
|
||||||
|
- [`ui-copy.md`](ui-copy.md) — screen, copy and button inventory plus the screen-design judge
|
||||||
|
record.
|
||||||
|
- [`accessibility.md`](accessibility.md) — accessibility statement and known gaps.
|
||||||
|
- [`known-limitations.md`](known-limitations.md) — release blockers and accepted limitations.
|
||||||
|
|
||||||
|
Up: [`../README.md`](../README.md) · Product plan: [`../../PLAN.md`](../../PLAN.md) · Tasks:
|
||||||
|
[`../../TODO.md`](../../TODO.md).
|
||||||
@@ -28,5 +28,5 @@ Known gaps:
|
|||||||
review is still a 0.10.0 release-review item.
|
review is still a 0.10.0 release-review item.
|
||||||
|
|
||||||
Test evidence and the manual checklist live in
|
Test evidence and the manual checklist live in
|
||||||
[`release-qa.md`](release-qa.md#manual-smoke-checklist); settings and save behaviour are
|
[`release-qa.md`](../process/release-qa.md#manual-smoke-checklist); settings and save behaviour are
|
||||||
documented in [`getting-started.md`](getting-started.md).
|
documented in [`getting-started.md`](../process/getting-started.md).
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Gameplay
|
# Gameplay
|
||||||
|
|
||||||
The complete design rationale also lives in [`PLAN.md`](../PLAN.md); this page keeps the playable mechanics close to the README.
|
The complete design rationale also lives in [`PLAN.md`](../../PLAN.md); this page keeps the playable mechanics close to the README.
|
||||||
|
|
||||||
## Game Overview
|
## Game Overview
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ public release.
|
|||||||
observation.
|
observation.
|
||||||
- **AI asset provenance:** the image-generation provider terms and commercial
|
- **AI asset provenance:** the image-generation provider terms and commercial
|
||||||
redistribution rights for the committed AI-assisted textures/UI art still need
|
redistribution rights for the committed AI-assisted textures/UI art still need
|
||||||
legal review. See [`../CREDITS.md`](../CREDITS.md).
|
legal review. See [`../CREDITS.md`](../../CREDITS.md).
|
||||||
- **Storefront/legal approval:** age/content rating, storefront policy, trademark
|
- **Storefront/legal approval:** age/content rating, storefront policy, trademark
|
||||||
language and the mental-health-crisis/body-camera representation have not been
|
language and the mental-health-crisis/body-camera representation have not been
|
||||||
externally approved.
|
externally approved.
|
||||||
@@ -31,7 +31,7 @@ public release.
|
|||||||
- Character faces, hands and fabric use a deliberately low-poly style; the
|
- Character faces, hands and fabric use a deliberately low-poly style; the
|
||||||
>26 m tier remains a two-quad impostor and there is no separate finger-curl
|
>26 m tier remains a two-quad impostor and there is no separate finger-curl
|
||||||
rig. The accepted limits are recorded in
|
rig. The accepted limits are recorded in
|
||||||
[`npc-visual-review.md`](npc-visual-review.md).
|
[`npc-model-sourcing.md`](../assets/npc-model-sourcing.md).
|
||||||
- There is no live 3D body-camera replay; the timeline is text-based.
|
- There is no live 3D body-camera replay; the timeline is text-based.
|
||||||
- There is no recorded voice/music track. Ambience and cues are procedural.
|
- There is no recorded voice/music track. Ambience and cues are procedural.
|
||||||
- The game is English-only and does not yet have a translator workflow or
|
- The game is English-only and does not yet have a translator workflow or
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# UI copy and button inventory
|
# UI copy and button inventory
|
||||||
|
|
||||||
Status: dialogue, button-state, focus, modal-close, font/layout, destructive-action and end-to-end passes complete; capture/smoke sign-off remains for 0.9.3.
|
Status: complete (0.9.3). Retained as the screen/button inventory, copy audit and screen-design judge record.
|
||||||
|
|
||||||
## Screen inventory
|
## Screen inventory
|
||||||
|
|
||||||
@@ -236,9 +236,9 @@ Command: `python3 tools/screen_designs.py judge`
|
|||||||
Result: **21/21 match, 0 review, 0 diff**
|
Result: **21/21 match, 0 review, 0 diff**
|
||||||
|
|
||||||
The screenshot gallery was regenerated on the current build before judging, including the eight UI-state captures 14–21 added in `src/test/capture_ui_states.gd`.
|
The screenshot gallery was regenerated on the current build before judging, including the eight UI-state captures 14–21 added in `src/test/capture_ui_states.gd`.
|
||||||
Accepted captures are in [`docs/screens/`](screens/README.md); the committed
|
Accepted captures are in [`docs/screens/`](../screens/README.md); the committed
|
||||||
gallery is in [`docs/screenshots/`](screenshots/README.md).
|
gallery is in [`docs/screenshots/`](../screenshots/README.md).
|
||||||
|
|
||||||
The automatic model selection and retry/spend behavior is documented in
|
The automatic model selection and retry/spend behavior is documented in
|
||||||
[`docs/asset-tooling.md`](asset-tooling.md). This report intentionally records
|
[`docs/assets/asset-tooling.md`](../assets/asset-tooling.md). This report intentionally records
|
||||||
the outcome rather than generated captures, which remain local/gitignored.
|
the outcome rather than generated captures, which remain local/gitignored.
|
||||||