3D bosses — pipeline notes
Status: ADOPTED (2026-08-25). Chris signed off on the animated Janitor;
experiment/3d-boss was fast-forwarded into main and 3D boss work now ships
straight to production. (The original hold-back ran the branch against Netlify
draft URLs only; that pattern remains the template for future risky spikes.)
Rollout order follows the in-game boss rotation: janitor ✓, monitor ✓, then quiz / substitute / exam / detention / group / parent / vice.
Pipeline (asset → mesh → game)
- Turnaround from our own art. The boss splash master is the identity
reference;
nano_banana_prorenders a 4-view turnaround (front / 3-4 / side / back, flat grey studio, mop held consistently) at 2 credits. Sheet:assets-src/incoming/models/janitor-turnaround.png. Crop the four figures (excluding the decorative floating props between panels — they poison the reconstruction). - Mesh via Higgsfield
multi_image_to_3d(Meshy). 4 view crops → textured GLB. 30 credits atshould_texture:true, target_polycount:20000, topology:triangle, symmetry:auto. Gotcha: the output safety checker false-flags the masked janitor (status:"nsfw") — passenable_safety_checker:falsefor our own game art. - In-game via
src/boss3d.js. GLTFLoader lazy-loadsassets/models/{art}.glb; the model is normalized (unit height, feet at y=0), re-skinned to the house look (MeshToonMaterial over the baked texture + 4-step gradient + inverted-hull outline viainflate()), and tracks the sim entity with the same animation language as the primitives (brute bob, windup pulse, charge stretch, hit flash via emissive).view._syncEnemiesskips the instanced primitive for claimed bosses; shadow blob + boss ring stay. Sim untouched — purely visual; fails silently back to primitives (single-file build, offline, bad GLB).
Verdict criteria
- Reads as the same character as the splash at gameplay camera distance.
- Cel + outline treatment sits next to instanced primitives without clashing.
- No frame cost worth caring about (one ~20K-tri mesh; watch mobile).
- GLB size acceptable for web delivery (target < ~8 MB).
If it works / if it doesn't
Works → repeat per boss (2cr sheet + 30cr mesh each, ~½ hour each), consider
rigged+animated variants later (enable_rigging + 678-clip library exists).
Doesn't → fall back: Meshy/Tripo web UIs (manual), or purchased packs
restyled with the cel treatment for generic minions (bosses stay primitives).
Phase 2 — rigged animation (2026-08-25)
3d_rigging (8cr/clip) rigged the SAME janitor GLB twice: Monster_Walk (112,
4.13s) and Heavy_Hammer_Swing (128, 1.87s). 24-bone rigs, identical armature
names, so the swing clip retargets onto the walk GLB's skeleton — one skinned
mesh carries all clips. boss3d.js v2: SkeletonUtils.clone per instance,
AnimationMixer, sim-state clip machine (idle/chase -> walk with timeScale from
real ground speed; windup+sweep -> one swing stretched across the 2.5s attack
window via LoopOnce + clampWhenFinished; crossfades 0.16s). Outline = skinned
inverted-hull shells bound to the same skeleton (ink deforms with the body).
Fallback chain animated -> static -> primitives, all verified. Files are ~9MB
per clip GLB (texture re-embedded in each) — before scaling to 9 bosses,
dedupe via gltf-transform or strip textures from clip GLBs and rebind.
Monitor (2026-08-25)
Cleanest turnaround yet (arms-at-sides brief rigs better; exclude the light
beam — the in-game spotlight FX owns it). Kit is stateless: profile maps
e.caught -> RunFast (16) and default -> Walk_Fight_Forward (21). First walk
pick Confident_Walk (106) had too much hip sway from the top-down camera —
LESSON: prefer neutral/guarded gaits; swagger clips read as full-body tilt
from above. Total: 2 sheet + 30 mesh + 3x8 rigs (one discarded) = 58cr.