"""Build the gallery HTML: curated scenes from allscenes.json injected into gallery_template.html.""" import json, os CURATED = [ # (scene key, project, display name, blurb) ("STDAVE/TREK.SCN", "Star Trek", "Enterprise-D", "The Enterprise-D at rest among three parallax layers of drifting stars."), ("STDAVE/KLNGVID.SCN", "Star Trek", "Klingon flyby", "A Klingon cruiser at rest while two more drift past on spline paths."), ("STDAVE/TREKVID.SCN", "Star Trek", "Enterprise flyby", "Camera-pass variant of the Enterprise scene, built for video capture."), ("HPDAVE/SDEMO.SCN", "Hull Pressure", "Sea demo", "The big Hull Pressure demo: seafloor, wrecks, and marine life on spline paths."), ("HPDAVE/FISHSPLS.SCN", "Hull Pressure", "Fish schools", "Schools of fish and sharks swimming spline circuits over the seabed."), ("HPDAVE/BDDEMO.SCN", "Hull Pressure", "Big demo", "Full underwater environment demo for the unreleased submarine game."), ("HPDAVE/TMPRIGS.SCN", "Hull Pressure", "Temple rigs", "Sunken temple environment with rig structures."), ("HPDAVE/DUANE.SCN", "Hull Pressure", "Duane's scene", "An underwater scene named for one of the team."), ("HPDAVE/SANDTEST.SCN", "Hull Pressure", "Sand test", "Seafloor sand and lighting test."), ("BTDAVE/MAPS/POLAR4.SCN", "BattleTech", "Polar map", "The polar arena environment, assembled from 99 models."), ("BTRAVINE/RAVTEST.SCN", "BattleTech", "Ravine map", "The Ravine arena in development — this environment shipped as RAV/RAV1."), ("BTRAVINE/DESTEST.SCN", "BattleTech", "Desert test", "Desert environment test with full map furniture."), ("BTDAVE/MAPS/DTEST.SCN", "BattleTech", "Desert map test", "A smaller desert map assembly test."), ("CONVERT/BTECH/STAD/STAD.SCN", "BattleTech", "Stadium", "Arena stadium model in the art-conversion workspace."), ("DPL3RLS/SCENES/MISSILE.SCN", "BattleTech", "Missile test", "Weapon-effects staging scene with arena props."), ("RPDAVE/SCENES/BLADE.SCN", "Red Planet", "Blade arena", "The Blade racing arena — late Red Planet development work."), ("CONVERT/MILESTON/MILESTON.SCN", "Red Planet", "Milestone", "The Red Planet milestone demo: Mars mining-canal raceway."), ("CONVERT/MILESTON/WELLENT.SCN", "Red Planet", "Well entrance", "Raceway well-entrance sequence from the milestone build."), ("CONVERT/RD/CHOICE2.SCN", "Red Planet", "Choice point", "A raceway fork (“choice”) section of the Mars canals."), ("RD/VTER.SCN", "Red Planet", "Terrain", "Generated Mars terrain heightfield test."), ("CANYON/CANYON.SCN", "Canyon demo", "Canyon", "River-canyon flythrough environment — Division demo work."), ("CANYON/CANABOVE.SCN", "Canyon demo", "Canyon from above", "The canyon seen from altitude."), ("CANYON/TEMPLE.SCN", "Canyon demo", "Maya temple", "Mayan temple set piece at the canyon rim."), ("ERIC/VANSMAK.SCN", "Misc", "Van's MAK", "A 31-model scene from developer Eric's directory."), ("HPDAVE/BATEST.SCN", "Hull Pressure", "Bathysphere test", "Single-model test of the submersible."), ("CONVERT/CALIB/DIVCAL.SCN", "Misc", "Division calibration", "Display-calibration model used to align the pod projectors."), ] # camera overrides for scenes whose START sits inside geometry (dev scenes); # None = use the viewer's auto-framing instead START_OVERRIDE = { "BTRAVINE/RAVTEST.SCN": [280, 30, 160, -8, 25, 0], "CANYON/CANYON.SCN": None, "CANYON/CANABOVE.SCN": None, "CANYON/TEMPLE.SCN": None, "BTDAVE/MAPS/DTEST.SCN": None, "CONVERT/CALIB/DIVCAL.SCN": None, } here = os.path.dirname(os.path.abspath(__file__)) data = json.load(open(os.path.join(here, "allscenes.json"))) out = {"models": {}, "images": {}, "scenes": {}, "catalog": []} for key, project, name, blurb in CURATED: sc = data["scenes"].get(key) if not sc: print("MISSING SCENE:", key) continue if key in START_OVERRIDE: sc = dict(sc); sc["start"] = START_OVERRIDE[key] if sc["start"] is None: del sc["start"] out["scenes"][key] = sc out["catalog"].append({"key": key, "project": project, "name": name, "blurb": blurb}) for mid in sc["modelmap"].values(): out["models"][mid] = data["models"][mid] for mat in sc["materials"].values(): if mat and mat.get("img"): out["images"][mat["img"]] = data["images"][mat["img"]] # per-model bounding radius for auto-framing for mid, groups in out["models"].items(): lo = [1e9] * 3; hi = [-1e9] * 3 for g in groups: for v in g.get("v", g.get("points", [])): for i in range(3): lo[i] = min(lo[i], v[i]); hi[i] = max(hi[i], v[i]) if lo[0] > hi[0]: lo = hi = [0, 0, 0] for g in groups: pass c = [(lo[i] + hi[i]) / 2 for i in range(3)] r = max(hi[i] - lo[i] for i in range(3)) / 2 or 1 out.setdefault("bounds", {})[mid] = {"c": [round(x, 2) for x in c], "r": round(r, 2)} blob = json.dumps(out, separators=(",", ":")) print("gallery data: %.1f MB, %d scenes, %d models, %d images" % (len(blob) / 1e6, len(out["scenes"]), len(out["models"]), len(out["images"]))) tpl = open(os.path.join(here, "gallery_template.html"), encoding="utf-8").read() open(os.path.join(here, "vwe-archive.html"), "w", encoding="utf-8").write( tpl.replace("%%DATA%%", blob)) print("wrote vwe-archive.html", os.path.getsize(os.path.join(here, "vwe-archive.html")) / 1e6, "MB")