feat(facades): 0.1.5 — hero detail, scene audit, material orphaning fixed (#32)

Merged PR #32: 0.1.5 — hero detail, scene audit, material orphaning fixed

Co-authored-by: Zwitschi <zwitschi82@gmail.com>
This commit was merged in pull request #32.
This commit is contained in:
zwitschi authored and zwitschi committed 2026-11-08 22:56:08 +01:00
1 parent 743a290ac9
commit 73aca9db80
50 files changed
+1326 -88

No files matched your search

+33 -4
View File
@@ -174,6 +174,20 @@ def build():
cap_z0 = HEIGHT - ENTABLATURE_H - PARAPET_H - CAPITAL_H
cylinder(f"Hero_Column_{i + 1}", x, -0.55, shaft_z0, cap_z0,
COLUMN_D / 2.0, stone)
# Fluting: 20 shallow grooves around the shaft, as the photographs show on
# the colonnade. Each flute is a thin cylinder set into the shaft surface;
# modelling them as grooves would need booleans on 6 columns for detail the
# eye reads only in silhouette and grazing light, so they are added mass in
# the *shadow* direction instead — cheap, and it breaks the flat highlight.
flutes = 20
flute_r = 0.032
for f in range(flutes):
ang = (2.0 * math.pi * f) / flutes
fx = x + (COLUMN_D / 2.0 - flute_r * 0.4) * math.cos(ang)
fy = -0.55 + (COLUMN_D / 2.0 - flute_r * 0.4) * math.sin(ang)
cylinder(f"Hero_Flute_{i + 1}_{f + 1}", fx, fy, shaft_z0 + 0.05,
cap_z0 - 0.05, flute_r, stone_dark, vertices=6)
# Capital block, then the square abacus that carries the architrave.
# The abacus takes the top 0.14 m of the capital zone so the colonnade
# still ends at HEIGHT - ENTABLATURE_H - PARAPET_H (proportion unchanged).
@@ -185,6 +199,9 @@ def build():
1.30, 1.30, abacus_h, stone)
note("Hero_Column_x6", (COLUMN_D, COLUMN_D, HEIGHT - ENTABLATURE_H - PARAPET_H - PEDESTAL_H),
f"6 columns at {COLUMN_BAY} m centres (sibling notes x measured frontage)")
note("Hero_Flute_x120", (0.064, 0.064, cap_z0 - shaft_z0),
"photographs: fluted shafts; 20 grooves per column modelled as shallow "
"cylinders in the shadow tone rather than boolean cut grooves")
note("Hero_ColumnBase_x6", (1.36, 1.36, 0.22),
"assumption: Ionic base moulding; photographs show a wider base at the shaft foot")
note("Hero_Abacus_x6", (1.30, 1.30, 0.14),
@@ -223,10 +240,22 @@ def build():
FRONTAGE_W, 1.2, PARAPET_H, stone)
note("Hero_Parapet", (FRONTAGE_W, 1.2, PARAPET_H), "assumption: parapet carries the motto band")
# Motto band: a recessed panel across the parapet, as the photographs show.
cube("Hero_MottoBand", 0.0, -1.32, HEIGHT - PARAPET_H / 2.0,
FRONTAGE_W - 3.0, 0.08, 0.85, stone_dark)
note("Hero_MottoBand", (FRONTAGE_W - 3.0, 0.08, 0.85), "photographs: motto panel above the colonnade")
# Motto band: a recessed panel across the parapet with a moulded surround, as
# the photographs show. The panel was a 8 cm stripe of dark stone; it is now a
# real recess — surround frame standing 6 cm proud, panel set 12 cm behind it —
# so it reads as an inscription panel from the street instead of a paint line.
motto_z = HEIGHT - PARAPET_H / 2.0
motto_w = FRONTAGE_W - 3.0
for x_off in (-(motto_w / 2.0 + 0.16), (motto_w / 2.0 + 0.16)):
cube(f"Hero_MottoSurround_v{int(x_off > 0)}", x_off, -1.13, motto_z,
0.32, 0.26, 1.15, stone)
for z_off in (-0.575, 0.575):
cube(f"Hero_MottoSurround_h{int(z_off > 0)}", 0.0, -1.13, motto_z + z_off,
motto_w + 0.64, 0.26, 0.32, stone)
cube("Hero_MottoBand", 0.0, -1.06, motto_z, motto_w, 0.10, 0.85, stone_dark)
note("Hero_MottoBand", (motto_w, 0.10, 0.85),
"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).