From e653d476fa5530f0550a99730e1bdf19d14f7fb5 Mon Sep 17 00:00:00 2001 From: Pygmalion Date: Sun, 21 Jun 2026 17:49:13 +0200 Subject: [PATCH] feat(hero): strike-pose attack hero GLB for combat-state swap (FLO-480) Second hero GLB of the same survivor character in an attack pose (forward lunging strike, lead fist raised) for the normal<->attack avatar swap that unblocks FLO-474. Drop-in twin of korovany_hero_player-default: - 2,905 tris (<=3,000 cap), 295 KB, 1x 1024 flat unlit base-color. - Same outfit/palette/identity; bbox height 2.0 = default's longest extent, so loadModel(targetSize:1.8) renders both at the same in-scene height -> no vertical jump or rescale on swap. - Forward strike (not raised-overhead) keeps height as the longest bbox extent; an overhead raise would have silently shrunk the body under fitScale. - Flat-matte retexture (FLO-440 pattern) -> coherent with the default, no PBR semi-realism; engine still facets via convertToFlatShadedMesh. - Pose baked into bind-pose geometry (loader renders GLBs statically; rig is useless here -- lesson FLO-434). Meshy: preview 019eead7-8fc8-743b-a550-8c54b344a2d3, refine 019eead9-26e6-78f4-94b6-e7e9b7ac3a01, flat retexture 019eeadc-c569-72af-b3dc-642406681f6a (40cr). Spec + renders in assets/models/hero/. Combat-state wiring is FLO-474 (Wayland/Aldric). Co-Authored-By: Pygmalion Co-Authored-By: Claude Opus 4.8 --- .../korovany_hero_player-attack.README.md | 75 +++++++++++++++++++ .../korovany_hero_player-attack.preview.png | 3 + .../korovany_hero_player-attack.strike.png | 3 + public/models/README.md | 9 +++ public/models/korovany_hero_player-attack.glb | 3 + 5 files changed, 93 insertions(+) create mode 100644 assets/models/hero/korovany_hero_player-attack.README.md create mode 100644 assets/models/hero/korovany_hero_player-attack.preview.png create mode 100644 assets/models/hero/korovany_hero_player-attack.strike.png create mode 100644 public/models/korovany_hero_player-attack.glb diff --git a/assets/models/hero/korovany_hero_player-attack.README.md b/assets/models/hero/korovany_hero_player-attack.README.md new file mode 100644 index 0000000..1765f0e --- /dev/null +++ b/assets/models/hero/korovany_hero_player-attack.README.md @@ -0,0 +1,75 @@ +# korovany_hero_player-attack — hero strike-pose variant (FLO-480 / FLO-474) + +Second hero GLB of the **same character** as `korovany_hero_player-default`, in an +**attack pose** (поза атаки) for the combat-state avatar swap. Pattern: FLO-440 +(re-author the identity, bake the pose into bind-pose geometry — the loader +renders GLBs statically, so a rig cannot apply a pose; lesson FLO-434). + +## v1 — forward lunging strike (flat-unlit retexture) + +- Role: Hero player avatar, attack state. Spec: visual language v1.2 (low-poly). +- Final GLB: `public/models/korovany_hero_player-attack.glb` — **2,905 tris, 295 KB, + 1× 1024 flat unlit base-color** (matches the default hero's v13 treatment). +- Budget check (v1.2 §5 Hero): tris 2,905 / 3,000 cap OK; size 0.30 / 1.0 MB OK; tex 1024 OK. +- Pipeline (FLO-440 pattern): text preview (target_polycount=2800) → refine + (enable_pbr, for clean welded geometry) → **flat retexture** (no `--enable-pbr`, + default removes baked lighting → flat/unlit albedo) → resize textures to 1024. + The PBR refine was only a geometry step; the shipped texture is flat, killing the + semi-realism FLO-440 removed from the default — so the two heroes are coherent. +- Meshy tasks: preview `019eead7-8fc8-743b-a550-8c54b344a2d3` (20cr); refine + `019eead9-26e6-78f4-94b6-e7e9b7ac3a01` (10cr); flat retexture + `019eeadc-c569-72af-b3dc-642406681f6a` (10cr). Total 40cr. +- Art evidence: `korovany_hero_player-attack.preview.png` (Meshy 512² untextured + preview — silhouette/pose truth) and `korovany_hero_player-attack.strike.png` + (Meshy 512² flat-textured render — palette truth). + +## Pose — forward lunging melee strike (NOT raised-overhead, NOT surrender) + +Lead fist clenched and raised forward in a jab/strike with a wide combat lunge +stance; rear arm low; bare fists, no weapon (the default hero is empty-handed → +silhouette match). Reads as aggression, deliberately **not** arms-out-to-the-sides +(which reads as surrender — the retired off-spec FLO-260 failure mode). + +**Why forward, not overhead:** `modelLoader.fitScale` normalizes by the *longest* +bbox extent and grounds at y=0. An overhead raise would make the vertical extent +exceed the standing height and silently shrink the body on swap. A forward strike +keeps **height** as the longest extent, identical to the default — so the swap is a +true drop-in with no vertical jump or rescale. + +## Drop-in parity vs default-hero (measured via Babylon NullEngine smoke loader) + +| asset | tris | bbox x | bbox y (height) | bbox z | longest extent | +|---------|-------|--------|-----------------|--------|----------------| +| attack | 2,905 | 0.88 | **2.0** | 0.531 | y (height) | +| default | 2,884 | 0.723 | **2.0** | 0.494 | y (height) | + +Both have **height = 2.0** as the longest extent, so `loadModel(targetSize: 1.8)` +scales each to 1.8 units tall, grounded at y=0 and centred on x/z. The in-scene +character height is identical between states; only the width grows slightly (0.79 vs +0.65 after normalization) because the lead fist extends forward — expected for a +strike. No scene-code change required to swap; `targetSize` is unchanged. + +In-engine shading: same as every character — `convertToFlatShadedMesh` facets it +(FLO-452 coherence), so the PBR gloss of the bare GLB is not what ships. + +## Reproducible prompt (v1) + +> a male survivor hero character in a brown leather bomber jacket, grey hooded +> sweater, olive-green cargo pants, brown work boots and fingerless gloves, in a +> dynamic aggressive melee fighting pose, lunging forward in a deep combat stance, +> torso twisted, one clenched fist cocked back at the shoulder and the other +> clenched fist thrust forward in a powerful punch, leaning into a forceful strike, +> fierce and aggressive, mid-attack, bare fists and no weapon, korovany action game +> player avatar, low-poly stylized 3D, faceted shading, flat color zones, simple +> geometry, game-ready, clean single-subject, muted earthy palette: ochre, +> terracotta, deep teal, wheat gold, charcoal, three distinct value tertiles, no +> logos, no text, no infringing IP + +Negative: `T-pose, A-pose, arms outstretched sideways, arms spread horizontally, +arms out to the sides, surrender pose, hands up surrendering, relaxed idle, +standing still, arms hanging limp, weapon, sword, gun, staff, holding object, +high-poly, smooth subdivision surfaces, photorealistic, hyperreal, realistic skin, +complex topology, busy patterns, neon, pastel, brand marks, watermarks, signature` + +Outfit/palette clause is identical to `korovany_hero_player-default` v12; only the +pose clause and the pose-related negatives differ. diff --git a/assets/models/hero/korovany_hero_player-attack.preview.png b/assets/models/hero/korovany_hero_player-attack.preview.png new file mode 100644 index 0000000..3533356 --- /dev/null +++ b/assets/models/hero/korovany_hero_player-attack.preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d73f2c772e6ce7c855da226fbba81d00d1d6f890eac49a6440de06a85adb911 +size 64994 diff --git a/assets/models/hero/korovany_hero_player-attack.strike.png b/assets/models/hero/korovany_hero_player-attack.strike.png new file mode 100644 index 0000000..ed31093 --- /dev/null +++ b/assets/models/hero/korovany_hero_player-attack.strike.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7bfff4fdcf8fa8848e570ed30495cb01e0e61d3a1144e6e3802cfd381f4fa66f +size 68507 diff --git a/public/models/README.md b/public/models/README.md index 0de2ee0..cd5e5e8 100644 --- a/public/models/README.md +++ b/public/models/README.md @@ -24,6 +24,15 @@ loaded at runtime via `loadModel()` (`src/scenes/modelLoader.ts`). 1.8)`. Source render + reproducible spec sheet in `assets/models/hero/`. Also serves as the **Phase-1 elf player avatar** (reuse-first; faction elf deferred to Phase 4 — FLO-299). +- `korovany_hero_player-attack.glb` — same hero in an **attack pose** (forward + lunging strike, lead fist raised), low-poly (2,905 tris · 295 KB · 1× 1024 flat + unlit base-color), within the v1.2 §5 Hero budget (FLO-480 / FLO-474). Flat-matte + retexture (FLO-440 pattern) so it stays coherent with the default — no PBR gloss. + Drop-in twin of the default: same outfit/palette/identity, **height (2.0) as + longest bbox extent** so `loadModel(targetSize:1.8)` renders it at the same + in-scene height — no scene change needed to swap normal↔attack by combat state + (wiring tracked on FLO-474). Spec + preview/textured renders in + `assets/models/hero/`. - `forest-tree.glb` — faceted low-poly forest conifer (1,357 tris · 77 KB · no textures, flat-shaded in-engine), v1.2 ≤3,000-tri budget. Streamed by the Phase-1 forest slice (E1.3). Spec + reference render in `assets/models/props/` diff --git a/public/models/korovany_hero_player-attack.glb b/public/models/korovany_hero_player-attack.glb new file mode 100644 index 0000000..c2a5d0d --- /dev/null +++ b/public/models/korovany_hero_player-attack.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d361e44df07490c85efcb68a041c9c36384f93b2142a6fd8c0bfb09834b6b7c +size 301848