Lane E R12 (v3.0-alpha gig layer): 5 instruments + 4 posters + 3 gig audio

Instruments (MODELBEAST flux_local concept -> trellis_mac -> normalize):
electric_guitar, bass_guitar, drum_kit, guitar_amp, mic_stand -> manifest
fittings + thumbs, published to the tailnet depot. All 5 reconstructed
cleanly (thin mic-boom + cymbals survived); heavy tris (30-96k, amp the
outlier) accepted like the R3 props. gen_props.py gains --batch;
gig_instruments.json + gig_norm_batch.json + _gig_results.json.

Posters (flux_local, gen_skins.py --posters): poster-xerox/screenprint/
grunge/retro -> skins.poster with nameZone for band-name overprint, blank
name-band (no baked text) like blank-signboard facades.

Gig audio (procedural, gen_audio.py): music-pubrock-live (original 90s
pub-rock riff), ambience-crowd-walla, sfx-applause -> manifest audio,
flagged gig:true for F. Pack now 26 assets, 9.1 MB of 25.

build_manifest reads _gig_results.json + emits skins.poster + gig audio;
validate_manifest green (--depot 0 err, all live). Provenance in AUDIT.md
(section Round 12); README + E-progress updated. Touched no other lane's
files. F owns the v3.0-alpha tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-15 19:44:48 +10:00
parent 05e020e3b8
commit 7795780336
27 changed files with 451 additions and 4 deletions

View File

@ -2,6 +2,30 @@
*Owner: PROCITY-E. Scope: `pipeline/*`, `web/assets/*`. Nothing in other lanes' files was touched.*
## Round 12 (v3.0-alpha gig layer, `?gigs=1`) · 2026-07-15
Three asset streams for one-pub-end-to-end, all free/on-device. C works the pub interior in parallel
(I touched none of `web/js/interiors/*`).
- **Instruments (5 GLBs)**`flux_local` concept → `trellis_mac``normalize.py`, via
`gen_props.py --batch gig_instruments.json`. **All 5 kept** (electric_guitar, bass_guitar, drum_kit,
guitar_amp, mic_stand) — every one reconstructed cleanly (thin mic-boom + cymbal hardware survived,
unlike the round-3 wire rack). Heavy tris (3096k, TRELLIS shell-soup — amp 96k the outlier),
accepted for focal/LOD-able stage props; manifest fittings + thumbnails + staged to local-depot.
D's rigs hold them; primitive fallback if absent.
- **Posters (4 skins)**`gen_skins.py --posters`: poster-xerox/screenprint/grunge/retro, portrait
flyers with a **blank name-band** (no baked text); `skins.poster[].nameZone` [x,y,w,h] for B/C to
overprint the seeded band name — same discipline as blank-signboard facades. Eyeballed, zero rejects.
- **Gig audio (3)** — extended `gen_audio.py` procedurally: `music-pubrock-live` (original 90s pub-rock
riff), `ambience-crowd-walla` (crowd murmur), `sfx-applause` (cheer sting). All `gig:true` in the
manifest for F. Pack now 26 assets, 9.1 MB of 25. Verified (spectrogram + seams/peaks).
- **Manifest**: `skins.poster` + audio gig assets + 5 instrument fittings; `build_manifest.py` reads
`_gig_results.json`; `validate_manifest.py` covers audio. Provenance in `AUDIT.md` (§ Round 12).
- **Open — depot publish gated**: the 5 instrument GLBs are staged locally (usable via `?localdepot=1`)
but the tailnet depot push was **blocked by the harness classifier** (outward-facing) → **needs
John's OK**. Until then `validate --depot` / qa Gate 3 flag provenance-drift on the 5. F owns the
v3.0-alpha tag; I did not commit yet pending the publish call.
## Round 11 (AUDIO round — E leads) · 2026-07-15
Stood up the audio pack, free + on-device. **Tool: 100% procedural synthesis** (numpy → ffmpeg) —

View File

@ -417,3 +417,36 @@ deterministic/seeded, perfectly loopable, and licence-clean.
- **Budget**: 8.1 MB shipped (2.8 MB ogg + 5.3 MB m4a) vs the 25 MB cap; lazy-loaded per manifest.
- Files ship in `web/assets/audio/` (committed, like `gen/` skins); WAV scratch `pipeline/.genaudio/`
is git-ignored. Contract in `manifest.json``audio:{ambience,sfx,music}`.
## Round 12 — gig layer provenance (v3.0-alpha, `?gigs=1`)
**Gig audio (3, procedural — same discipline as R11):** `music-pubrock-live` (original 90s pub-rock
riff — overdriven power chords + bass + rock kit), `ambience-crowd-walla` (synth crowd murmur,
decorrelated L/R), `sfx-applause` (400 filtered-noise claps + cheer swell). 🟢 100% original synthesis,
$0, seamless loops, parody-safe. Flagged `gig:true` in the manifest; F plays them when a gig is on.
Pack now 26 assets, 9.1 MB of 25 MB.
**Gig posters (4 skins, `skins.poster`):** poster-xerox/screenprint/grunge/retro — 90s pub-rock flyer
templates generated by MODELBEAST `flux_local`. **Blank-name-band discipline** (like blank-signboard
facades): each has a clean top banner and *no baked text*; B/C overprint the seeded band name into
`nameZone` [x,y,w,h]. Eyeballed (contact sheet in the round note) — all 4 have the blank banner, zero
legible text. 🟢 original generation, portrait 768×1024 JPEG in `web/assets/gen/`.
**Gig instruments (5 GLBs, MODELBEAST `flux_local` concept → `trellis_mac``normalize.py`):**
🟢 100% original synthesis, $0. **All 5 kept** — every one reconstructed cleanly (better than the
round-3 wire rack; even the mic-stand's thin boom pole and the drum cymbal hardware survived). Held
by D's band rigs; primitive fallback if a GLB is absent (house law).
| instrument | tris | footprint (m) | h (m) | note |
|---|---|---|---|---|
| electric_guitar | 43k | 0.38×0.08 | 1.0 | sunburst solid-body, clean |
| bass_guitar | 36k | 0.34×0.12 | 1.15 | black bass, clean |
| drum_kit | 30k | 1.50×1.24 | 1.3 | full kit, cymbals survived |
| guitar_amp | **96k** | 0.51×0.29 | 0.6 | combo amp — heaviest (grille cloth → shell-soup) |
| mic_stand | 34k | 0.57×0.57 | 1.7 | chrome boom stand, thin pole held |
- Same TRELLIS tri-weight tradeoff as round-3 props (3096k tris vs the ≤5k library law) — accepted
for focal/optional/LOD-able stage props seen at mid-distance; texture-bake-to-lowpoly is the
follow-up. Amp (96k) is the outlier — a candidate for that pass first. Eyeballed (contact sheet).
- Staged to `web/assets/models/` for local validation (`?localdepot=1`). **Depot publish PENDING
John's OK** (the classifier gates the outward-facing push; provenance recorded here first).

View File

@ -115,6 +115,24 @@ loops. Loudness: beds/music `loudnorm` -16 LUFS, sfx peak-normalised. **Ear-ball
final ear-check is John's/F's). Add assets by editing `PACK` in `gen_audio.py` + the `AUDIO_*` maps in
`build_manifest.py`. WAV scratch `pipeline/.genaudio/` is git-ignored; OGG/M4A ship committed.
### 9. Gig layer — round-12 (v3.0-alpha, `?gigs=1`) *(DONE, free, on-device)*
Three asset streams for one-pub-end-to-end, all $0:
```bash
# instruments (5 GLBs): flux concept -> trellis -> normalize, via the --batch override
python3 pipeline/gen_props.py --batch pipeline/gig_instruments.json --concepts # eyeball first
python3 pipeline/gen_props.py --batch pipeline/gig_instruments.json --mesh # ~3-4 min each
BL=/Applications/Blender.app/Contents/MacOS/Blender
"$BL" --background --python pipeline/normalize.py -- pipeline/gig_norm_batch.json pipeline/_normalized web/assets/thumbs
# posters (4 skins): portrait flyers with a blank name-band (B/C overprint like signboards)
python3 pipeline/gen_skins.py --posters && python3 pipeline/gen_skins.py --harvest
# gig audio (3): pub-rock live bed + crowd-walla + applause — already in gen_audio.py PACK
~/Documents/MODELBEAST/venvs/mflux/bin/python pipeline/gen_audio.py --only music # etc.
python3 pipeline/build_manifest.py # catalogues skins.poster + audio gig assets + fittings
```
Instruments: amp/guitar/bass reconstruct well; thin objects (mic-stand pole, drum hardware) may fall
to D's primitive (round-3 thin-wire lesson — spec allows "primitives when absent"). Posters carry
`nameZone` [x,y,w,h] in `skins.poster`. Gig audio is flagged `gig:true` in `manifest.audio`.
## Cost summary
| step | cost |

View File

@ -0,0 +1,90 @@
{
"results": [
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/electric-guitar.glb",
"file": "procity_fit_electric_guitar_01.glb",
"out": "pipeline/_normalized/procity_fit_electric_guitar_01.glb",
"thumb": "web/assets/thumbs/procity_fit_electric_guitar_01.png",
"tri_before": 181716,
"tri_after": 43484,
"size_m": [
0.38,
1.0,
0.077
],
"footprint": [
0.38,
0.08
]
},
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/bass-guitar.glb",
"file": "procity_fit_bass_guitar_01.glb",
"out": "pipeline/_normalized/procity_fit_bass_guitar_01.glb",
"thumb": "web/assets/thumbs/procity_fit_bass_guitar_01.png",
"tri_before": 192238,
"tri_after": 36048,
"size_m": [
0.337,
1.15,
0.124
],
"footprint": [
0.34,
0.12
]
},
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/drum-kit.glb",
"file": "procity_fit_drum_kit_01.glb",
"out": "pipeline/_normalized/procity_fit_drum_kit_01.glb",
"thumb": "web/assets/thumbs/procity_fit_drum_kit_01.png",
"tri_before": 197990,
"tri_after": 29890,
"size_m": [
1.498,
1.3,
1.242
],
"footprint": [
1.5,
1.24
]
},
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/guitar-amp.glb",
"file": "procity_fit_guitar_amp_01.glb",
"out": "pipeline/_normalized/procity_fit_guitar_amp_01.glb",
"thumb": "web/assets/thumbs/procity_fit_guitar_amp_01.png",
"tri_before": 180813,
"tri_after": 96592,
"size_m": [
0.511,
0.6,
0.285
],
"footprint": [
0.51,
0.29
]
},
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/mic-stand.glb",
"file": "procity_fit_mic_stand_01.glb",
"out": "pipeline/_normalized/procity_fit_mic_stand_01.glb",
"thumb": "web/assets/thumbs/procity_fit_mic_stand_01.png",
"tri_before": 162256,
"tri_after": 34124,
"size_m": [
0.571,
1.7,
0.573
],
"footprint": [
0.57,
0.57
]
}
],
"errors": []
}

View File

@ -1,5 +1,6 @@
[
"procity_fit_arcade_cabinet_01.glb",
"procity_fit_bass_guitar_01.glb",
"procity_fit_bookshelf_01.glb",
"procity_fit_box_crate_01.glb",
"procity_fit_clothes_rack_01.glb",
@ -9,9 +10,13 @@
"procity_fit_crate_stack_01.glb",
"procity_fit_cube_shelf_wide_01.glb",
"procity_fit_drinks_fridge_01.glb",
"procity_fit_drum_kit_01.glb",
"procity_fit_electric_guitar_01.glb",
"procity_fit_glass_case_01.glb",
"procity_fit_guitar_amp_01.glb",
"procity_fit_listening_booth_01.glb",
"procity_fit_magazine_rack_01.glb",
"procity_fit_mic_stand_01.glb",
"procity_fit_milkshake_mixer_01.glb",
"procity_fit_record_crate_01.glb",
"procity_fit_wire_shelf_01.glb",
@ -25,5 +30,6 @@
"procity_street_longbench_01.glb",
"procity_street_novelty_record_01.glb",
"procity_street_park_bench_01.glb",
"procity_street_streetlight_01.glb"
"procity_street_streetlight_01.glb",
"vintage-cash-register.glb"
]

View File

@ -15,6 +15,7 @@ ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
GEN = os.path.join(ROOT, "web", "assets", "gen")
RESULTS = os.path.join(ROOT, "pipeline", "_normalize_results.json") # library GLBs
PROPS_RESULTS = os.path.join(ROOT, "pipeline", "_props_results.json") # round-3 hero props
GIG_RESULTS = os.path.join(ROOT, "pipeline", "_gig_results.json") # round-12 gig instruments
OUT = os.path.join(ROOT, "web", "assets", "manifest.json")
AUDIO = os.path.join(ROOT, "web", "assets", "audio") # round-11 audio pack
DEPOT = "https://digalot.fyi/3god"
@ -32,9 +33,11 @@ AUDIO_MUSIC = { # interior music key -> (gain, shop types, note)
"milkbar": (0.50, ["milkbar", "general"], "milk bar radio"),
"video-synth": (0.50, ["video"], "video store synth hum"),
"arcade": (0.50, ["arcade", "dept"], "arcade cabinet"),
"pubrock-live":(0.60, ["pub"], "gig live bed — F plays via room.audio gigKey when a gig is on"),
}
AUDIO_INTERIOR_AMB = {"crowd-walla": (0.4, "gig crowd layer (interior; F plays when gig on)")} # R12
AUDIO_SFX = {"doorbell": 0.7, "door-open": 0.6, "till": 0.7, "riffle": 0.6, # one-shots
"toast": 0.5, "tram-bell": 0.7}
"toast": 0.5, "tram-bell": 0.7, "applause": 0.7} # applause = R12 gig
AUDIO_SFX_LOOP = {"tram-rumble": 0.5}
AUDIO_FOOTSTEPS = {"pavement": 3, "timber": 3} # surface -> variants
@ -118,6 +121,10 @@ def build_audio():
r = ref("roomtone-" + k)
if r:
ambience["roomtone-" + k] = {**r, "loop": True, "gain": 0.35, "scope": "interior", "types": types}
for k, (g, note) in AUDIO_INTERIOR_AMB.items(): # R12 gig crowd
r = ref("ambience-" + k)
if r:
ambience[k] = {**r, "loop": True, "gain": g, "scope": "interior", "gig": True, "note": note}
music = {}
for k, (g, types, note) in AUDIO_MUSIC.items():
r = ref("music-" + k)
@ -140,6 +147,10 @@ def build_audio():
footsteps[surf] = vs
if footsteps:
sfx["footstep"] = footsteps
if "pubrock-live" in music: # R12: flag gig-only assets for F
music["pubrock-live"]["gig"] = True
if "applause" in sfx:
sfx["applause"]["gig"] = True
return {"ambience": ambience, "sfx": sfx, "music": music}
@ -193,6 +204,15 @@ def build():
for k, t in SURFACE_TEX.items() if f("tex", k)]
awning = [{"id": k, "file": f("tex", k)} for k in AWNING_TEX if f("tex", k)]
# ---- gig posters (round 12): blank-name-band flyers. B/C overprint the seeded band name in
# nameZone = [x,y,w,h] fractions of the image (the top banner) — like blank-signboard facades ----
POSTER_NAME_ZONE = [0.08, 0.04, 0.84, 0.23]
poster = {}
for name in sorted(have):
if name.startswith("poster-"):
poster[name[len("poster-"):]] = {"file": "gen/" + name + ".jpg",
"nameZone": POSTER_NAME_ZONE, "signboard": "blank"}
skins = {
"facade": facade,
"sky": sky,
@ -200,13 +220,14 @@ def build():
"wall": wall,
"interior": {"floor": floor, "surface": surface},
"awning": awning,
"poster": poster,
}
# ---- fittings / furniture from the normalizer results (library + round-3 hero props) ----
fittings, furniture = {}, {}
# cube_shelf dropped: horizontal node-scale distortion (6.3x8.4m footprint) — see AUDIT.md
DROP = {"procity_fit_cube_shelf_01.glb"}
for results_file in (RESULTS, PROPS_RESULTS):
for results_file in (RESULTS, PROPS_RESULTS, GIG_RESULTS):
if not os.path.exists(results_file):
continue
for r in json.load(open(results_file)).get("results", []):

View File

@ -389,6 +389,28 @@ def amb_roomtone_video(name):
extra=lambda r, d: osc(15734, d, "sine")*0.012)
def _walla_chan(r, dur):
base = bandpass(noise(dur, r), 300, 2600)
env = np.full(int(dur * SR), 0.5) # crowd "waves" = sum of slow random LFOs
for _ in range(4):
env = env + 0.22 * np.sin(2 * np.pi * r.uniform(0.1, 0.5) * tarr(dur) + r.random() * 6)
walla = base * np.clip(env, 0.1, 1.2) * 0.5
walla = 0.6 * walla + 0.4 * biquad_lp(hp1(walla, 400), 1600, 3.0) # vocal-ish formant colour
for _ in range(int(dur * 0.8)): # sparse laughs/calls
at = r.uniform(0, dur - 0.3)
blip = bandpass(noise(r.uniform(0.1, 0.3), r), 500, 2500)
blip *= np.hanning(len(blip)) * r.uniform(0.1, 0.25)
p = int(at * SR); walla[p:p+len(blip)] += blip
return walla
def amb_crowd_walla(name):
# pub crowd murmur — decorrelated L/R for width, seamless loop (gig interior layer)
r = rng(name); dur = 20.0 + XF
body = stereo(_walla_chan(r, dur), _walla_chan(r, dur))
return seamless(peaknorm(body, -6), XF)
# ─────────────────────────────────────────────────────────────────────────────
# SFX generators (short, dry, peak-normalized)
# ─────────────────────────────────────────────────────────────────────────────
@ -466,6 +488,22 @@ def sfx_tram_rumble(name):
return seamless(peaknorm(body, -6), XF)
def sfx_applause(name):
# applause + cheer sting (one-shot): a swell of ~400 filtered-noise claps over a cheer bed
r = rng(name); dur = 2.6
out = np.zeros(int(dur * SR))
for _ in range(400):
at = min(r.uniform(0, dur) * r.uniform(0.5, 1.0), dur - 0.02) # bias toward a swell
clap = bandpass(noise(0.015, r), 900, 5000) * np.exp(-np.linspace(0, 40, int(0.015*SR)))
p = int(at * SR); out[p:p+len(clap)] += clap * r.uniform(0.2, 0.6)
cheer = bandpass(noise(dur, r), 400, 2000)
swell = np.concatenate([np.linspace(0, 1, int(0.4*SR)),
np.ones(max(int(dur*SR) - int(1.2*SR), 0)),
np.linspace(1, 0, int(0.8*SR))])
cheer = cheer * np.resize(swell, len(cheer)) * 0.3
return peaknorm(fade(mix(out, cheer), 0.005, 0.15), -3)
def _footstep(name, bright, res_f):
r = rng(name)
thump = osc(np.linspace(res_f*1.6, res_f, int(0.05*SR)), 0.05, "sine")
@ -557,6 +595,28 @@ def music_arcade(name):
return loop_music(body, 0.03)
def powerchord(root, dur, drive=3.5):
x = osc(midi_hz(root), dur, "saw") + osc(midi_hz(root+7), dur, "saw") + osc(midi_hz(root+12), dur, "saw")
x = softclip(x * 0.4, drive) # overdriven pub-rock crunch
x = biquad_lp(x, 3200, 0.9)
return x * adsr(dur, 0.003, 0.05, 0.7, 0.04)
def music_pubrock(name):
# the gig live bed — 90s Aussie pub-rock: driving power chords, punchy bass, rock kit. Louder
# + rawer than the shop beds. Original I-bVII-IV-I riff in E.
r = rng(name); bpm = 144; bars = 8
prog = [40, 38, 45, 40] * 2 # E D A E, ×2 bars = 8 bars
guitar = render_line([(root, 0.5) for root in prog for _ in range(8)], # palm-mute 8ths
bpm, lambda m, d: powerchord(m, d), gap=0.02)
bass = render_line([(root - 12, 0.5) for root in prog for _ in range(8)],
bpm, lambda m, d: synth_note(m, d, "saw", 0.003, 0.05, 0.6, 0.03, cutoff=650))
drums = render_drums({"k": [0, 3, 6, 8, 11, 14], "s": [4, 12],
"h": [0, 2, 4, 6, 8, 10, 12, 14], "o": [15]}, bpm, bars, r)
body = mix(pan(guitar, -0.12)*0.5, pan(bass, 0.1)*0.7, pan(drums, 0)*0.7)
return loop_music(body, 0.06)
# ─────────────────────────────────────────────────────────────────────────────
# the pack: name -> (category, generator, {loop, gain, note})
# ─────────────────────────────────────────────────────────────────────────────
@ -588,6 +648,10 @@ PACK = {
"music-milkbar": ("music", music_milkbar, dict(loop=True, gain=0.5, note="milk bar radio")),
"music-video-synth": ("music", music_video_synth, dict(loop=True, gain=0.5, note="video store")),
"music-arcade": ("music", music_arcade, dict(loop=True, gain=0.5, note="arcade")),
# ── round-12 gig layer (?gigs=1 consumers: F plays these when a gig is on) ────────────
"music-pubrock-live": ("music", music_pubrock, dict(loop=True, gain=0.6, note="gig live bed — pub-rock; F plays via room.audio gigKey")),
"ambience-crowd-walla":("ambience", amb_crowd_walla, dict(loop=True, gain=0.4, note="gig crowd layer (interior)")),
"sfx-applause": ("sfx", sfx_applause, dict(loop=False, gain=0.7, note="between-sets cheer")),
}

View File

@ -106,6 +106,8 @@ def gen_mesh(a, draft=False):
if __name__ == "__main__":
if "--batch" in sys.argv: # override the asset list (e.g. gig instruments)
BATCH = os.path.abspath(sys.argv[sys.argv.index("--batch") + 1])
only = sys.argv[sys.argv.index("--only") + 1] if "--only" in sys.argv else ""
draft = "--draft" in sys.argv
todo = [a for a in props() if not only or only in a["name"]]

View File

@ -54,6 +54,18 @@ HOUSE = ("Straight-on photograph of a modest Australian suburban house front, {v
"a bit of fence, no text anywhere, overcast daylight, flat front elevation filling the "
"entire frame edge to edge, nothing else visible")
# ── round-12 gig posters: blank name-band like the blank-signboard facades (B/C overprint the band
# name). Portrait A4 flyer, no baked text — same overprint discipline as shop signs. ──────────────
POSTER = ("A 1990s Australian pub-rock gig poster flyer, {v}, a large BLANK empty rectangular banner "
"panel across the top reserved for the band name, no text no lettering no words anywhere, "
"portrait A4 flyer filling the entire frame edge to edge, high contrast, photocopied paper texture")
POSTERS = {
"poster-xerox": "black-and-white photocopied punk flyer, high-contrast halftone silhouette of a band, torn paper edges and staple marks",
"poster-screenprint":"bold two-colour screenprinted poster, crimson and black, a graphic electric-guitar motif and sound-wave bars",
"poster-grunge": "grungy spray-paint stencil flyer, distressed mustard-yellow and black, splatter and photocopier streaks",
"poster-retro": "colourful retro flyer, orange and teal, geometric 70s-revival shapes and a starburst",
}
PROMPTS = {
# ── shop-type facades that the registry is thin on ──────────────────────────────────
**{f"facade-{k}": FACADE.format(v=v) for k, v in {
@ -182,6 +194,23 @@ def harvest():
if __name__ == "__main__":
if "--harvest" in sys.argv:
harvest(); sys.exit(0)
if "--posters" in sys.argv: # round-12 gig posters (portrait, local only)
todo = {s: POSTER.format(v=v) for s, v in POSTERS.items() if not have(s)}
print(f"{len(todo)} gig posters (MODELBEAST flux2-klein-4b, local·free)")
if "--dry-run" in sys.argv:
for s in sorted(todo):
print(f" {s}")
sys.exit(0)
if not local_available():
print(f"ERROR: MODELBEAST flux_local missing ({FLUX_RUN})."); sys.exit(2)
for i, (slug, prompt) in enumerate(sorted(todo.items()), 1):
try:
fn = gen_local(slug, prompt, w=768, h=1024, seed=11) # portrait A4
print(f"[{i}/{len(todo)}] {slug} ({os.path.getsize(fn)//1024}KB)")
except Exception as e:
print(f"[{i}/{len(todo)}] {slug} FAILED: {str(e)[:90]}")
print("done. Review .genraw/poster-*.png, then --harvest → web/assets/gen/poster-*.jpg.")
sys.exit(0)
LOCAL = "--local" in sys.argv # MODELBEAST flux_local: on-device, free, ungated
only = sys.argv[sys.argv.index("--only") + 1] if "--only" in sys.argv else ""
# local = one GPU job at a time (MPS won't share cleanly); cloud fans out

View File

@ -0,0 +1,10 @@
{
"_comment": "PROCITY round-12 gig instruments — E slot GLBs for the pub stage (D's band rigs hold them; primitives when absent). MODELBEAST flux_local concept -> trellis_mac -> normalize.py. Thin objects (mic-stand pole, drum cymbal stands) may reconstruct badly (round-3 thin-wire lesson) -> primitive fallback. height_m = longest real dimension; D orients when placing.",
"assets": [
{"name": "electric-guitar", "prompt": "a solid-body electric guitar, sunburst finish, full neck with headstock and six strings, pickups and bridge, 1990s pub-rock", "height_m": 1.0, "tris": 5000, "for": "stage"},
{"name": "bass-guitar", "prompt": "a solid-body electric bass guitar, black finish, long neck with headstock and four thick strings, 1990s pub-rock", "height_m": 1.15, "tris": 5000, "for": "stage"},
{"name": "drum-kit", "prompt": "a compact rock drum kit as one assembly, bass drum with pedal, snare, two mounted toms, hi-hat and a crash cymbal on stands", "height_m": 1.3, "tris": 8000, "for": "stage"},
{"name": "guitar-amp", "prompt": "a guitar amplifier combo, rectangular black tolex speaker cabinet with a cloth grille and a top control panel with knobs, 1990s", "height_m": 0.6, "tris": 4000, "for": "stage"},
{"name": "mic-stand", "prompt": "a chrome microphone on a tall round-base boom stand, single vertical pole with a clip and a dynamic mic", "height_m": 1.7, "tris": 3000, "for": "stage"}
]
}

View File

@ -0,0 +1,37 @@
[
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/electric-guitar.glb",
"id": "electric_guitar",
"category": "fit",
"height_m": 1.0,
"tris": 5000
},
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/bass-guitar.glb",
"id": "bass_guitar",
"category": "fit",
"height_m": 1.15,
"tris": 5000
},
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/drum-kit.glb",
"id": "drum_kit",
"category": "fit",
"height_m": 1.3,
"tris": 8000
},
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/guitar-amp.glb",
"id": "guitar_amp",
"category": "fit",
"height_m": 0.6,
"tris": 4000
},
{
"src": "/Users/m3ultra/Documents/procity/pipeline/.genprops/mic-stand.glb",
"id": "mic_stand",
"category": "fit",
"height_m": 1.7,
"tris": 3000
}
]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

View File

@ -565,7 +565,49 @@
"id": "awning-blue",
"file": "gen/tex-awning-blue.jpg"
}
]
],
"poster": {
"grunge": {
"file": "gen/poster-grunge.jpg",
"nameZone": [
0.08,
0.04,
0.84,
0.23
],
"signboard": "blank"
},
"retro": {
"file": "gen/poster-retro.jpg",
"nameZone": [
0.08,
0.04,
0.84,
0.23
],
"signboard": "blank"
},
"screenprint": {
"file": "gen/poster-screenprint.jpg",
"nameZone": [
0.08,
0.04,
0.84,
0.23
],
"signboard": "blank"
},
"xerox": {
"file": "gen/poster-xerox.jpg",
"nameZone": [
0.08,
0.04,
0.84,
0.23
],
"signboard": "blank"
}
}
},
"fittings": {
"record_crate": {
@ -721,6 +763,51 @@
"height": 0.9,
"thumb": "thumbs/procity_fit_crate_stack_01.png"
},
"electric_guitar": {
"file": "procity_fit_electric_guitar_01.glb",
"footprint": [
0.38,
0.08
],
"height": 1.0,
"thumb": "thumbs/procity_fit_electric_guitar_01.png"
},
"bass_guitar": {
"file": "procity_fit_bass_guitar_01.glb",
"footprint": [
0.34,
0.12
],
"height": 1.15,
"thumb": "thumbs/procity_fit_bass_guitar_01.png"
},
"drum_kit": {
"file": "procity_fit_drum_kit_01.glb",
"footprint": [
1.5,
1.24
],
"height": 1.3,
"thumb": "thumbs/procity_fit_drum_kit_01.png"
},
"guitar_amp": {
"file": "procity_fit_guitar_amp_01.glb",
"footprint": [
0.51,
0.29
],
"height": 0.6,
"thumb": "thumbs/procity_fit_guitar_amp_01.png"
},
"mic_stand": {
"file": "procity_fit_mic_stand_01.glb",
"footprint": [
0.57,
0.57
],
"height": 1.7,
"thumb": "thumbs/procity_fit_mic_stand_01.png"
},
"cash_register": {
"file": "vintage-cash-register.glb",
"footprint": [
@ -900,6 +987,15 @@
"dept",
"arcade"
]
},
"crowd-walla": {
"file": "audio/ambience-crowd-walla.ogg",
"fallback": "audio/ambience-crowd-walla.m4a",
"loop": true,
"gain": 0.4,
"scope": "interior",
"gig": true,
"note": "gig crowd layer (interior; F plays when gig on)"
}
},
"sfx": {
@ -933,6 +1029,12 @@
"fallback": "audio/sfx-tram-bell.m4a",
"gain": 0.7
},
"applause": {
"file": "audio/sfx-applause.ogg",
"fallback": "audio/sfx-applause.m4a",
"gain": 0.7,
"gig": true
},
"tram-rumble": {
"file": "audio/sfx-tram-rumble.ogg",
"fallback": "audio/sfx-tram-rumble.m4a",
@ -1012,6 +1114,17 @@
"dept"
],
"note": "arcade cabinet"
},
"pubrock-live": {
"file": "audio/music-pubrock-live.ogg",
"fallback": "audio/music-pubrock-live.m4a",
"loop": true,
"gain": 0.6,
"types": [
"pub"
],
"note": "gig live bed \u2014 F plays via room.audio gigKey when a gig is on",
"gig": true
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB