diff --git a/.claude/skills/art-dev/references/blender-cookbook.md b/.claude/skills/art-dev/references/blender-cookbook.md index bf291f299..e5da81f8b 100644 --- a/.claude/skills/art-dev/references/blender-cookbook.md +++ b/.claude/skills/art-dev/references/blender-cookbook.md @@ -335,3 +335,5 @@ Tie any emissive to the **ontology** (the helmet porthole = teal glass, faint gl **D. Judge cohesion in-engine, at game scale, next to the existing Synty assets.** A generated mesh that looks fine solo can still clash beside the low-poly body — the only true test is a Play capture with the character next to its neighbours (the suit, an enemy) at the real game framing (§9). The Blender render confirms the mesh is clean; the *style match* is an in-engine, next-to-siblings call. Recipe verified on the Mark-V: 4 hand-model attempts failed → Rodin generate → clean-decimate 23k→1.1k (0 holes) → drop the copper photoreal map → flat `M_Diver_Brass`/`HelmetMetal` + a teal `M_Diver_Porthole` + flat-shade → reads as one cohesive Synty diver (operator-approved). GLB 1.7 MB → 736 KB (texture dropped). + +**E. ★ Coloring on the GAMEPLAY (deformation) rig ≠ staging — flat `_BaseColor` FAILS.** A static staging mesh takes flat colour from the material `_BaseColor` (plain Principled / the `Skinned-Palette` graph). But the animated player/enemy render entities carry a **per-instance `URPMaterialPropertyBaseColor` override** (driven by the hit-flash system, set to `(1,1,1)` at rest) which **REPLACES** the material's `_BaseColor` — so a flat-`_BaseColor` material with `_BaseColorMap = null` renders **white/cream** (null map samples white × instance-white). (This corrects the older "clear `_BaseColorMap` → uses `_BaseColor` directly" note — that only holds for entities WITHOUT the per-instance override.) Fix: drive colour from `_BaseColorMap` — either UV the piece to a `PaletteAtlas` band, or assign a **solid-colour texture** (an 8×8 PNG of the target colour) as `_BaseColorMap` and leave `_BaseColor` white; the instance override then just multiplies (and the flash still tints correctly). Diagnose by reading the live entity: `EntityManager.HasComponent` on the `LinkedEntityGroup` render children → if present and `(1,1,1)`, the material `_BaseColor` is dead, use a map. Per-submesh colour (e.g. the Mark-V's brass/gunmetal/glass) = one material per submesh, each with its own solid `_BaseColorMap`. Verified live: `M_Diver_*_Skinned` + `DiverTex/T_Diver_*.png` on `Player.prefab`. diff --git a/Docs/Vault/07_Sessions/2026/2026-07-24_Bathynaut_Helmet_Synty_Ingame_Bodyswap.md b/Docs/Vault/07_Sessions/2026/2026-07-24_Bathynaut_Helmet_Synty_Ingame_Bodyswap.md new file mode 100644 index 000000000..c91c2a322 --- /dev/null +++ b/Docs/Vault/07_Sessions/2026/2026-07-24_Bathynaut_Helmet_Synty_Ingame_Bodyswap.md @@ -0,0 +1,62 @@ +--- +title: 2026-07-24_Bathynaut_Helmet_Synty_Ingame_Bodyswap +type: note +permalink: gamevault/07-sessions/2026/2026-07-24-bathynaut-helmet-synty-ingame-bodyswap +--- + +# 2026-07-24 — Bathynaut: Mark-V helmet Synty-match + in-game body-swap + +Continuation of the character overhaul. Two operator gates: **"the helmet doesn't match the Synty art +style, it looks jarring"** → restyle; then **"go ahead, the character is approved"** → put it in the +gameplay player. Both shipped + verified live. + +## Helmet: AI-gen → Synty-match (staging) +The AI-generated (Hyper3D Rodin) Mark-V arrived photoreal + high-poly + single-textured — it clashed with +the flat-shaded low-poly Synty suit. Also the first decimation (0.10 collapse) **tore holes** in the mesh. +Fixes (banked in `/art-dev` cookbook §14): +- **Watertight decimate:** weld doubles + recalc normals + delete loose FIRST, then a gentle 0.18 collapse + → 23k→1090 tris with **0 boundary edges** (the hole detector). Aggressive collapse on un-welded gen + geometry is what shattered it. +- **Drop the photoreal texture → shared flat palette:** re-materialled with the suit's OWN materials + (`M_Diver_Brass` bonnet + `M_Diver_HelmetMetal` valve/collar/bezel + a teal `M_Diver_Porthole` glass), + flat-shaded for chunky facets. Shares the suit's materials → cohesion guaranteed; the teal porthole ties + into the bioluminescent palette. GLB 1.7 MB → 736 KB. +- **Scale gotcha earlier the same day:** the meter-scale gen mesh skinned to the cm-scale (0.01) rig + imported at ~5 mm (invisible) with a bad bindpose → made it a **rigid** (non-skinned) attachment, scale + 0.25 → ~0.5 m. (Commits `059458db8`, `69685a665`, `be55683f1`.) + +## In-game body-swap (the shipping animated Player.prefab) +The `.blend` body/armour are pose-baked static (staging only, can't export as a skinned body) — so the swap +works on the **in-engine Synty rest-pose skinned rig** that already animates. Torso/head bones sit at rest +(only the arms are posed), so re-skinning the torso/head kit pieces is valid. +- **Re-exported the skinned kit FBX** dome-less (metal 2157→1092 v — the old dome is gone) + the Mark-V + skinned to `Head` (3 submeshes brass/gunmetal/glass). Re-ran `AttachBathynautKit` (proven `GraftSmr` + rebase) → grafted metal + beacon + Mark-V; deleted the orphaned old porthole. +- **Material split:** armour → brass, body → dark-teal undersuit, tanks → gunmetal, beacon → warm, + Mark-V → brass/gunmetal/teal-glass. +- **★ per-instance `_BaseColor` gotcha (cost a cycle):** every player render child carries a + `URPMaterialPropertyBaseColor = (1,1,1)` override (hit-flash system) that **REPLACES** the material + `_BaseColor`. So flat-`_BaseColor` + null `_BaseColorMap` rendered the whole diver **cream/white**. Fix = + drive colour from a **solid-colour `_BaseColorMap` texture** (`DiverTex/T_Diver_*.png`), leave + `_BaseColor` white; the instance override just multiplies (flash still works). Diagnosed by reading the + live LEG children. Corrects the older "clear the map → uses `_BaseColor`" note (only true without the + override). → cookbook §14-E. +- **Verified live in DevSandbox from the game camera:** copper Mark-V + brass armour + dark-teal undersuit + + gunmetal tanks + warm beacon, animated, reads at true game scale. Commit `9f9c3b07b`. + +## Tooling scare +A range-format `apply_text_edits` on `PlayerRigTools.cs` (from a **stale** 932-line read; the file is 931 — +they coincidentally matched, but the range still) **truncated the file 931→808 lines**, deleting +`GraftSmr`'s body. Recovered via `git checkout HEAD -- PlayerRigTools.cs`. Lesson: the harness Read can lag +the true file; ground line numbers against `execute_code` disk-read or MCP `find_in_file`, and prefer a +whole-`oldText` match over blind line ranges. + +## Follow-ups (flagged, not silently dropped) +- **Silhouette broadening** (shoulders ×1.17 / boots ×1.14) is on the staging `.blend` armour but NOT + in-game yet — the in-game armour is the stock Synty mesh. It already reads heavy (brass plate + tank + pack); the broadening is a subtle enhancement via a vertex-edit on a skinned armour-mesh copy. Offered. +- **`PlayerRigTools` material drift:** `AttachBathynautKit` still assigns placeholder materials + (`M_Skinned_Palette`/`mGlow`); the correct diver materials are set post-hoc on the prefab. A re-run + reverts them. Bake the correct per-SMR + Mark-V multi-material assignment into the tool when convenient + (deferred after the truncation scare — didn't want more C# surgery same session). +- The grafted helmet SMR is named `SM_Suit_Helmet_MarkV_EXP` (the export dup name) — cosmetic. \ No newline at end of file