hero: make the portals real recesses and land the facade on Z 0

The portal detail shot failed for a modelling reason, not a camera reason: the
doors were 0.1 m panels on a solid plinth, so they read as shading. The plinth is
now four piers plus a lintel band, with a 1.2 m reveal, stone jambs and lintels
standing 0.10 m proud and three mullions per opening. review-06 frames them from
8 m at eye height.

Two defects fixed while doing it: the jamb boxes hung 0.15 m below the pavement,
so the facade imported with min Z -15 cm; and a rebuild run against a read-only
.blend silently skipped the save, which is why screenshots kept showing the old
geometry.
This commit is contained in:
zwitschi committed 2026-11-07 12:46:00 +01:00
1 parent f575bc82a8
commit d4af4af90f
22 files changed
+132 -55

No files matched your search

+54 -14
View File
@@ -122,8 +122,7 @@ def build():
# --- stylobate and steps ----------------------------------------------
# A plinth from the pavement to the pedestal shelf, with three door flights.
cube("Hero_Stylobate", 0.0, -1.2, PEDESTAL_H / 2.0, FRONTAGE_W, 2.4, PEDESTAL_H, stone)
note("Hero_Stylobate", (FRONTAGE_W, 2.4, PEDESTAL_H), "assumption: pedestal height")
# The stylobate is built later as piers around the three door openings.
# --- Ionic colonnade ---------------------------------------------------
col_xs = []
@@ -171,24 +170,65 @@ def build():
note("Hero_Medallion_x2", (1.1, 1.1, 0.02), "photographs: two stone discs beside the motto")
# --- entrances ---------------------------------------------------------
# Three portals between column pairs, each with its own short flight.
# Three portals between column pairs, each with its own short flight. The
# doorway is cut INTO the stylobate face rather than laid on it: the plinth is
# modelled as three segments so the opening is a real recess, and the portals
# stand proud of the wall behind the colonnade so they read from the street.
portal_xs = (-COLUMN_BAY, 0.0, COLUMN_BAY)
plinth_front = -2.4 # front face of the plinth, in the facade frame
plinth_back = 0.0
gap = PORTAL_W
# The plinth is four piers between and beside the openings, plus a band over
# them, so each door is a real recess instead of a panel on a solid face.
piers = [
(-(FRONTAGE_W / 2.0), portal_xs[0] - gap / 2.0),
(portal_xs[0] + gap / 2.0, portal_xs[1] - gap / 2.0),
(portal_xs[1] + gap / 2.0, portal_xs[2] - gap / 2.0),
(portal_xs[2] + gap / 2.0, (FRONTAGE_W / 2.0)),
]
for pi, (x0, x1) in enumerate(piers, start=1):
cube(f"Hero_Stylobate_{pi}", (x0 + x1) / 2.0, -1.2, PEDESTAL_H / 2.0,
x1 - x0, 2.4, PEDESTAL_H, stone)
# Band above the openings, closing the plinth to full height between the doors.
cube("Hero_Stylobate_LintelBand", 0.0, -1.2, PORTAL_H + (PEDESTAL_H - PORTAL_H) / 2.0,
(portal_xs[-1] + gap / 2.0) - (portal_xs[0] - gap / 2.0), 2.4,
PEDESTAL_H - PORTAL_H, stone)
note("Hero_Stylobate", (FRONTAGE_W, 2.4, PEDESTAL_H),
"assumption: pedestal height; four piers and a lintel band leave three recesses")
for i, x in enumerate(portal_xs, start=1):
# Recessed doorway: a dark panel set into the stylobate face.
cube(f"Hero_Portal_{i}", x, -2.35, PORTAL_H / 2.0,
PORTAL_W, 0.10, PORTAL_H, glass)
# Door grille above the steps, using the banner red for the sign panel.
cube(f"Hero_PortalSign_{i}", x, -2.42, PORTAL_H + 0.55,
# Recessed doorway: a dark reveal set back inside the plinth, 1.2 m deep so
# it reads as an opening from any angle.
depth = 1.2
cube(f"Hero_Portal_{i}", x, plinth_front + depth / 2.0 + 0.05, PORTAL_H / 2.0,
PORTAL_W, depth, PORTAL_H, glass)
# Stone surround, standing 0.1 m proud of the plinth face.
for side, sx in (("L", -1.0), ("R", 1.0)):
# Jambs stop at the pavement: a 0.15 m overhang below Z 0 would sink the
# whole facade into the ground plane.
cube(f"Hero_PortalJamb_{i}{side}", x + sx * (PORTAL_W / 2.0 + 0.15),
plinth_front - 0.10, (PORTAL_H + 0.3) / 2.0, 0.3, 0.2, PORTAL_H + 0.3, stone)
cube(f"Hero_PortalLintel_{i}", x, plinth_front - 0.10, PORTAL_H + 0.15,
PORTAL_W + 0.6, 0.2, 0.3, stone)
# Door grille: mullions across the opening, dark metal read at distance.
for m in range(1, 4):
cube(f"Hero_PortalMullion_{i}_{m}", x - PORTAL_W / 2.0 + m * PORTAL_W / 4.0,
plinth_front + 0.12, PORTAL_H / 2.0, 0.09, 0.06, PORTAL_H, stone_dark)
# Sign panel over the doorway, as the photographs show.
cube(f"Hero_PortalSign_{i}", x, plinth_front - 0.16, PORTAL_H + 0.75,
0.7, 0.06, 0.9, banner)
# Photographs show four to five risers per portal; the count follows the
# pedestal height rather than inheriting the old "eight steps" claim.
steps = max(3, min(5, int(round((PEDESTAL_H - 0.2) / STEP_RISE))))
for s in range(steps):
top = PEDESTAL_H - s * STEP_RISE
cube(f"Hero_Step_{i}_{s + 1}", x,
-2.4 - 0.14 - s * STEP_TREAD - STEP_TREAD / 2.0,
top - STEP_RISE / 2.0,
STEP_WIDTH, STEP_TREAD, STEP_RISE, stone)
# Steps descend from the plinth to the pavement; the lowest tread must land
# exactly on Z 0, never below it, so the flight meets the ground plane.
steps = max(3, min(steps, int(round(PEDESTAL_H / STEP_RISE))))
for st in range(steps):
top = PEDESTAL_H - st * STEP_RISE
height = top if st == steps - 1 else STEP_RISE
cube(f"Hero_Step_{i}_{st + 1}", x,
plinth_front - 0.14 - st * STEP_TREAD - STEP_TREAD / 2.0 + 0.28,
top - height / 2.0, STEP_WIDTH, STEP_TREAD, height, stone)
note(f"Hero_PortalFlight_{i}", (PORTAL_W, STEP_TREAD * steps, PEDESTAL_H - 0.2),
f"{steps} steps at {STEP_RISE:.2f} m rise / {STEP_TREAD:.2f} m tread "
f"(assumption; photos show 4-5, the old notes said 8)")