feat(hero): stepped medallion relief, seated on the parapet face

The medallions were not just flat - they were buried. seat_on_front put
Hero_Medallion at offset 0.08 (front Y -0.42) while the 1.2 m-deep parapet stands
at Y -0.15, so both discs sat inside the parapet and never rendered. The motto
band and surround have the same burial (offset 0.06) and are a separate follow-up.

- Three stepped layers per medallion with per-layer prefixes so seat_on_front gives
  each its own stand-off: Rim (0.55 m, dark, offset 0.36 -> Y -0.14), Field
  (0.38 m, light, offset 0.43 -> Y -0.07), Boss (0.15 m, dark, offset 0.50 -> Y 0.00).
  A single Hero_Medallion prefix would both flatten the relief and (via startswith)
  swallow the specific prefixes, so it is removed.
- Moved from +/-6.2 (inside the inscription text, which spans +/-6.87) to +/-9.8.
- Fixed Tools/review/hero_iterate.sh, which still had the pre-tools-move
  'cd dirname/..' and landed in Tools/ instead of the repo root.

Rendered and judged; the advisory two-model judge (no, 0.93) no longer flags the
medallions. Owner review pending.
This commit is contained in:
zwitschi committed 2026-11-10 15:04:48 +01:00
1 parent 1d57ed477d
commit 33f8139cb2
24 files changed
+54 -34

No files matched your search

+2
View File
@@ -69,3 +69,5 @@ Thumbs.db
# Unreal per-project build artefacts (FileOpenOrder logs and the like)
Build/
dsh-session-*
tmp/
Binary file not shown.
+2 -2
View File
@@ -122,10 +122,10 @@
"object": "Hero_Medallion_x2",
"dims_m": [
1.1,
0.04,
0.2,
1.1
],
"evidence": "photographs: two stone discs beside the motto, mounted on the parapet face"
"evidence": "photographs: two round reliefs beside the motto - dark rim, raised light field, dark boss"
},
{
"object": "Hero_Stylobate",
Binary file not shown.
Binary file not shown.
+7
View File
@@ -661,3 +661,10 @@ The related lesson: a prefix-based clear (`clear(("Demo_", "PlayerStart", ...))`
## 2026-11-10 — Render-to-import chain, in one order
A visual change needs **build → import → render**, never just a render: `render_screenshots.sh` renders the imported Unreal assets. `Tools/review/e2e_asset_check.py` runs the whole thing (Blender renders → empty maps → both builds → captures → two-model judge → README) and is the command to use instead of remembering four.
## 2026-11-10 — Hero attic: the medallions were buried, not just flat
- **`seat_on_front` offsets are relative to `FRONT_Y` (the wall plane, Y −0.5), not to the parapet face.** The parapet is 1.2 m deep with its front at Y −0.15, so any applied detail with offset < 0.35 sits *inside* the parapet and never renders. The medallions (offset 0.08 → front −0.42) and the motto band + surround (offset 0.06 → front −0.44) were all buried; only the inscription (moved to 0.40 → front −0.10 in the previous commit) read.
- **Medallion fix:** stepped relief with per-layer prefixes so `seat_on_front` gives each its own stand-off — `MedallionRim` 0.36, `MedallionField` 0.43, `MedallionBoss` 0.50. One shared prefix (`Hero_Medallion`) would seat every disc at the same offset and flatten the relief, and it also matched the more specific prefixes via `startswith`, so it had to be removed entirely.
- **Medallions were also at ±6.2, inside the inscription text (spans ±6.87).** Moved to ±9.8.
- **`Tools/review/hero_iterate.sh` still had the pre-move `cd "$(dirname "$0")/.."`** from the tools restructure — it landed in `Tools/` and failed `find Art` with "no such file". Fixed to `../..`, matching `render_screenshots.sh`.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -223,7 +223,7 @@ Open:
- [x] **Make the generated ashlar albedo render.** Two blockers, both measured: the map's generic material pass was **overriding every hero slot** with the kit's flat stone (`comp.set_material` on `Hero_Facade`), and assigning authored materials to the _mesh's_ slot list does not persist because `get_editor_property("static_materials")` returns a copy. What works: exclude the hero from the generic pass and set **component-level overrides** to the authored `*_Ref` materials in both builders (`apply_hero_materials()`). The elevation now shows coursed, grainy limestone.
- [x] Carved inscription: `inscription()` in `Tools/blender/hero_facade_build.py` lays 112 letter marks in three lines across the attic, in the shadow stone so they read at 45 m. They had to be **seated on the parapet face** (`FRONT_Y + 0.40`): the parapet is 1.2 m deep and stands in front of the wall plane, so marks at the wall plane were hidden behind it.
- [ ] Medallion relief that reads at 45 m - the two discs exist but are flush and empty; a bevelled rim and a raised motif would read, or a baked texture.
- [x] Medallion relief that reads at 45 m. **Measured first, then fixed:** the discs were not just flat - they were **buried**. `seat_on_front` put `Hero_Medallion` at offset 0.08 → front face Y −0.42, while the parapet (1.2 m deep) stands at Y −0.15, so both medallions were inside the parapet and never rendered (the motto band and surround have the same bug at offset 0.06). Fixed: three stepped layers per medallion — `Hero_MedallionRim` (0.55 m, dark, offset 0.36 → Y −0.14), `Hero_MedallionField` (0.38 m, light, offset 0.43 → Y −0.07), `Hero_MedallionBoss` (0.15 m, dark, offset 0.50 → Y 0.00) — a 7 cm step each way so the rim/field/boss read as relief. Moved from ±6.2 (inside the inscription text, ±6.87) to ±9.8. Rendered and judged; the two-model judge is advisory-pessimistic (`no` 0.93) and does not flag medallions any more. Owner review pending.
- [ ] Banner lettering (JIMMY KIMMEL LIVE) - needs a texture; the banners are flat panels today.
- [ ] Crimson banner tone and the JIMMY KIMMEL LIVE lettering.
- [ ] Re-render the three ReviewMap staging shots and put them back in the status table for review.
+18 -8
View File
@@ -272,13 +272,22 @@ def build():
"photographs: motto panel above the colonnade, now an inset panel with a "
"moulded surround rather than a flat stripe")
# Medallions either side of the inscription: discs on the parapet face, not
# pancakes on the coping (see disc_on_wall).
for i, x in enumerate((-6.2, 6.2), start=1):
disc_on_wall(f"Hero_Medallion_{i}", x, -1.30, HEIGHT - PARAPET_H / 2.0,
0.55, 0.04, stone_dark, vertices=20)
note("Hero_Medallion_x2", (1.1, 0.04, 1.1),
"photographs: two stone discs beside the motto, mounted on the parapet face")
# Medallions either side of the inscription: stepped round reliefs (dark rim, raised
# light field, dark central boss) so they read as round medallions at 45 m instead of
# flat, empty discs. Each layer has its own prefix so `seat_on_front` gives it its own
# stand-off; one shared prefix would seat every disc at the same offset and flatten the
# relief. They sit OUTSIDE the inscription text (which spans ~±6.9 m) on the parapet
# face, which is 0.35 m proud of FRONT_Y - at the old 0.08 offset they were buried
# inside the 1.2 m-deep parapet and never rendered.
for i, x in enumerate((-9.8, 9.8), start=1):
disc_on_wall(f"Hero_MedallionRim_{i}", x, -1.30, HEIGHT - PARAPET_H / 2.0,
0.55, 0.10, stone_dark, vertices=28)
disc_on_wall(f"Hero_MedallionField_{i}", x, -1.30, HEIGHT - PARAPET_H / 2.0,
0.38, 0.16, stone, vertices=28)
disc_on_wall(f"Hero_MedallionBoss_{i}", x, -1.30, HEIGHT - PARAPET_H / 2.0,
0.15, 0.20, stone_dark, vertices=20)
note("Hero_Medallion_x2", (1.1, 0.20, 1.1),
"photographs: two round reliefs beside the motto - dark rim, raised light field, dark boss")
# --- entrances ---------------------------------------------------------
# Three portals between column pairs, each with its own short flight. The
@@ -403,7 +412,8 @@ def build():
seat_on_front((
("Hero_Architrave", 0.05), ("Hero_Cornice", 0.05), ("Hero_Dentil", 0.05),
("Hero_Entablature", 0.03), ("Hero_MottoBand", 0.06), ("Hero_MottoSurround", 0.06),
("Hero_Medallion", 0.08), ("Hero_Banner", 0.08), ("Hero_Window", 0.03),
("Hero_MedallionRim", 0.36), ("Hero_MedallionField", 0.43), ("Hero_MedallionBoss", 0.50),
("Hero_Banner", 0.08), ("Hero_Window", 0.03),
("Hero_Portal", 0.05), ("Hero_PortalJamb", 0.08), ("Hero_PortalLintel", 0.08),
("Hero_PortalMullion", 0.04), ("Hero_PortalSign", 0.10),
# The parapet is 1.2 m deep and stands in front of the wall plane, so the inscription has to sit on
+1 -1
View File
@@ -10,7 +10,7 @@
# order is load-bearing. The Blender save happens BEFORE the FBX export, so a read-only .blend makes
# the build look successful while the old FBX is reused silently - hence the chmod at the top.
set -uo pipefail
cd "$(dirname "$0")/.." || exit 1
cd "$(dirname "$0")/../.." || exit 1
ENGINE="${ENGINE:-/run/media/system/DATA/Engines/UE_5.8.4}"
BLENDER_FILES="${BLENDER_FILES:-/var/lib/flatpak/app/org.blender.Blender/x86_64/stable/active/files}"
Symlink
+1
View File
@@ -0,0 +1 @@
/tmp/gigline