feat: hero asset batch 2 — yatai, koban, phone booths, bus stops, bikes

Second round of original Blender-kitbashed street furniture
(tools/build_hero_assets.py):

- yatai.glb: ramen cart — noren curtain strips on a hanger bar, counter,
  wheels, three stools, paper lantern, red roof with ink trim; one at
  every market mouth (wood collider)
- koban.glb: police box with teal roof, door, framed window, sign board
  and red lamp — watches the central crossing from the SE plaza corner
- phonebooth.glb: green-framed glass booth on ~25% of retail corners
- busstop.glb: bench + glass canopy + yellow sign disc, alternating
  blocks along the central avenue, both directions
- bicycle.glb: torus-wheeled bikes with frame/seat/basket, parked in
  seeded rows of 2-4 beside building fronts

All toonified with ink outlines; colliders acoustics-tagged (wood/
concrete/glass/metal). Movement 11/11, smoke 0, acoustics ALL PASSED.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Nicholas Butzke
2026-07-19 03:04:54 -04:00
co-authored by Claude Fable 5
parent 7f9a579b63
commit 18f50adb78
7 changed files with 110 additions and 2 deletions
+86
View File
@@ -215,3 +215,89 @@ station()
clock()
torii()
print("hero: all assets built")
# ── Batch 2: street furniture ────────────────────────────────────────────────
def yatai():
"""Ramen cart: body, roof, noren curtain strips, stools, lantern."""
clear()
box("body", (2.6, 1.2, 1.1), (0, 0, 0.75), WOOD, 0.03)
box("counter", (2.8, 1.35, 0.08), (0, 0, 1.34), mat("counter", (0.62, 0.45, 0.28)), 0.02)
for sx in (-1, 1):
box("post", (0.08, 0.08, 1.3), (sx * 1.2, -0.45, 2.0), INK, 0.0)
cyl("wheel", 0.28, 0.1, (sx * 0.9, 0.62, 0.28), INK, rot=(math.radians(90), 0, 0))
box("roof", (3.0, 1.5, 0.12), (0, 0, 2.7), RED, 0.02)
box("roof_trim", (3.1, 1.6, 0.06), (0, 0, 2.62), INK, 0.0)
# noren curtain strips across the front
for i in range(5):
x = -1.1 + i * 0.55
box("noren", (0.42, 0.04, 0.6), (x, 0.72, 2.28), mat("noren", (0.92, 0.9, 0.85)), 0.0)
box("noren_bar", (2.7, 0.05, 0.05), (0, 0.72, 2.6), INK, 0.0)
for i, x in enumerate((-0.9, 0.0, 0.9)):
cyl("stool", 0.18, 0.5, (x, 1.05, 0.25), RED, verts=12)
cyl("lantern", 0.16, 0.42, (1.35, 0.7, 2.3), mat("lamp", (0.98, 0.62, 0.25)), verts=12)
export(os.path.join(OUT, "yatai.glb"))
def koban():
"""Police box: small building, sign board, red lamp."""
clear()
W, D, H = 3.2, 3.0, 3.2
box("body", (W, D, H), (0, 0, H / 2), CREAM, 0.03)
box("roof", (W + 0.5, D + 0.5, 0.3), (0, 0, H + 0.15), TEAL, 0.03)
box("door", (0.95, 0.1, 2.1), (-0.6, D / 2, 1.05), INK, 0.01)
box("window", (1.1, 0.1, 1.0), (0.7, D / 2, 1.7), GLASS, 0.01)
box("winframe", (1.25, 0.06, 1.15), (0.7, D / 2 - 0.02, 1.7), INK, 0.01)
box("sign", (1.6, 0.12, 0.5), (0, D / 2 + 0.1, 2.75), WHITE, 0.01)
cyl("lamp", 0.12, 0.24, (0, D / 2 + 0.2, 3.05), RED, verts=10)
export(os.path.join(OUT, "koban.glb"))
def phonebooth():
clear()
box("frame", (1.1, 1.1, 2.5), (0, 0, 1.25), mat("booth", (0.2, 0.45, 0.3)), 0.03)
for a in range(4):
ang = math.pi / 2 * a
dx, dy = math.cos(ang), math.sin(ang)
box("glass", (0.06 if a % 2 == 0 else 0.85, 0.85 if a % 2 == 0 else 0.06, 1.6),
(dx * 0.53, dy * 0.53, 1.35), GLASS, 0.0)
box("cap", (1.25, 1.25, 0.18), (0, 0, 2.6), INK, 0.02)
export(os.path.join(OUT, "phonebooth.glb"))
def busstop():
clear()
box("bench", (2.6, 0.5, 0.1), (0, 0.2, 0.55), WOOD, 0.02)
for sx in (-1, 1):
box("leg", (0.1, 0.45, 0.55), (sx * 1.1, 0.2, 0.27), INK, 0.0)
box("cpost", (0.1, 0.1, 2.4), (sx * 1.5, -0.25, 1.2), METAL, 0.0)
box("croof", (3.6, 1.3, 0.1), (0, 0.15, 2.45), GLASS, 0.02)
box("croof_trim", (3.7, 1.4, 0.05), (0, 0.15, 2.38), INK, 0.0)
box("signpole", (0.08, 0.08, 3.0), (2.1, -0.3, 1.5), METAL, 0.0)
cyl("signdisc", 0.35, 0.06, (2.1, -0.3, 2.85), YELLOW, rot=(math.radians(90), 0, 0), verts=16)
export(os.path.join(OUT, "busstop.glb"))
def bicycle():
clear()
for wy in (-0.55, 0.55):
bpy.ops.mesh.primitive_torus_add(major_radius=0.32, minor_radius=0.035,
location=(0, wy, 0.32),
rotation=(math.radians(90), 0, math.radians(90)))
o = bpy.context.active_object
o.data.materials.append(INK)
box("frame1", (0.05, 0.7, 0.05), (0, 0.1, 0.55), RED, 0.0, rot=(math.radians(25), 0, 0))
box("frame2", (0.05, 0.6, 0.05), (0, -0.2, 0.5), RED, 0.0, rot=(math.radians(-35), 0, 0))
box("bar", (0.4, 0.05, 0.05), (0, -0.52, 0.85), INK, 0.0)
box("seat", (0.14, 0.3, 0.06), (0, 0.28, 0.85), INK, 0.01)
box("basket", (0.32, 0.3, 0.25), (0, -0.72, 0.72), METAL, 0.01)
export(os.path.join(OUT, "bicycle.glb"))
yatai()
koban()
phonebooth()
busstop()
bicycle()
print("hero: batch 2 built")