diff --git a/docs/characters/head-features-contract.md b/docs/characters/head-features-contract.md index a8907fa..5a0ca39 100644 --- a/docs/characters/head-features-contract.md +++ b/docs/characters/head-features-contract.md @@ -225,15 +225,19 @@ Both are downstream of the same root cause — our bodies ship as **one mesh, on one material** (`MI_Body_Lena`, `MI_Body_Mako`), so no facial feature is individually addressable. -- **Eyebrows.** Lena's ship path deletes painted brows from the albedo and attaches a - generated skinned surface built from a *locked UV-space mask* - (`tools/generate_lena_brow_surface.py`), coloured by the hair swatch. The mask, the browless - albedo and the surface JSON are **atlas-bound** — Lena's v02 re-atlas invalidates all three - at once, and they must be regenerated in the same stage that finalizes the atlas. - There is also a live-but-superseded mask-tint path (`shaders/character_brow.gdshader`) that - recolors a painted brow in place — 72 % replace, not a multiply. That one generalizes to a - scanned face; the cover path does not, because you cannot erase raised scan geometry with a - texture. Mako has `AttachFacialFeatures = false` and therefore no brow colour at all. +- **Eyebrows — the whole 3D lane was reverted on 2026-08-12.** Ozan removed the mesh brows, + the lash cards and the browless-face swap from the product path: brows are **painted on the + body texture** again and keep their baked colour. That retires, for now, the generated + surface (`tools/generate_lena_brow_surface.py`), the locked BLUE mask, the browless albedo, + and "brows follow the hair swatch". The tooling and the wiki page remain, so read the code + before the docs on this one. + Two consequences survive the revert. First, painted brows are **atlas-bound**, so Lena's v02 + re-atlas still has to carry the brow pigment correctly — the difference is that it now rides + in the albedo rather than in three separate artifacts. Second, the mask-tint path + (`shaders/character_brow.gdshader`, 72 % replace, not a multiply) is still live code and is + still the only mechanism that could recolour a brow on a scanned face — you cannot erase + raised scan geometry with a texture. Mako has `AttachFacialFeatures = false`, so his brows + are his scan's and are not editable at all. - **Eye colour.** `ApplyEyeColorByIndex` swaps the whole albedo of the `OutfitSlot.Eyes` mesh between six baked iris PNGs. It needs a **separate mesh or primitive** — there is no other mechanism. Lena only has one because stock Quaternius eye spheres are laid over her painted @@ -254,7 +258,7 @@ addressable. | 4 | `hair_refit.py` + QC gates, baked per body | this repo | The part a 3-constant fit cannot reach: ear cutouts, the 23 % X/Z anisotropy, forehead line | | 5 | 16 per-colour hair PNGs | this repo | Kills the `/0.55` swatch hack | | 6 | Iris primitive split at export | this repo | Gives Mako eye colour | -| 7 | Regenerate brow mask/browless/surface at atlas-final | Lena v02 lane | Or v02 ships with brows mismatched to her atlas | +| 7 | Carry the painted brow pigment through the v02 re-atlas | Lena v02 lane | Brows went back to texture-only on 2026-08-12, so this is an albedo-fidelity job now, not three artifacts to regenerate | Note the duplicated literal: `HeadAccessoryBindMath.ArikiHeadScale` carries its own copy of Lena's numbers marked "keep in sync with CharacterBuildData". Any change to hers must touch