# Export the two in-scope north-side background buildings from the OSM blockout. # # blender -b --factory-startup Art/blender/blockout/blockout-2026-11-06.blend \ # --python Tools/export_north_buildings.py -- --out /tmp/gigline/north # # The blockout is already in the shared project frame (metres, X east / Y north / # Z up, origin Hollywood x Highland), so exporting each object at its own world # position preserves the offset from the hero facade. The site export preset # (`ue_metric_v1`) is reused verbatim so the metre->centimetre mapping matches. import argparse import os import sys import bpy BUILDINGS = ("TCL Chinese Theatre", "Madame Tussaud's") def main(): argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [] ap = argparse.ArgumentParser() ap.add_argument("--out", default="/tmp/gigline/north") args = ap.parse_args(argv) os.makedirs(args.out, exist_ok=True) print(f"[north] scene objects: {len(bpy.data.objects)}") for name in BUILDINGS: obj = bpy.data.objects.get(name) if obj is None or obj.type != "MESH": print(f"[north] MISSING {name}") continue bpy.ops.object.select_all(action="DESELECT") obj.select_set(True) bpy.context.view_layer.objects.active = obj mesh = obj.data if not mesh.materials: mat = bpy.data.materials.new(f"M_{name.replace(' ', '_')}") mat.diffuse_color = (0.75, 0.72, 0.68, 1.0) mat.use_nodes = False mesh.materials.append(mat) # The blockout sits with the hero (6840, south side) at negative Y. The two # in-scope north buildings must land ACROSS Hollywood Blvd at positive Y in # Unreal. Mirror the exported geometry across the road centreline (Y=0) and # reverse winding; the FBX exporter does not do this for us. new_mesh = mesh.copy() new_obj = obj.copy() new_obj.data = new_mesh new_obj.matrix_world = obj.matrix_world.copy() bpy.context.collection.objects.link(new_obj) import mathutils as mu world = new_obj.matrix_world inv = world.inverted() for v in new_mesh.vertices: wp = world @ v.co wp.y = -wp.y v.co = inv @ wp for poly in new_mesh.polygons: verts = list(poly.vertices) verts.reverse() poly.vertices = verts new_mesh.update() bpy.ops.object.select_all(action="DESELECT") new_obj.select_set(True) bpy.context.view_layer.objects.active = new_obj path = os.path.join(args.out, name.replace(" ", "_").replace("'", "") + ".fbx") bpy.ops.export_scene.fbx( filepath=path, use_selection=True, object_types={"MESH"}, apply_unit_scale=True, apply_scale_options="FBX_SCALE_NONE", axis_forward="-Y", axis_up="Z", use_space_transform=True, use_mesh_modifiers=True, mesh_smooth_type="OFF", path_mode="AUTO", bake_space_transform=False, ) zs = [(world @ v.co).z for v in new_mesh.vertices] print(f"[north] {name:22} verts {len(new_mesh.vertices):5} z {min(zs):+.2f}..{max(zs):+.2f} m " f"-> {path}") bpy.data.objects.remove(new_obj, do_unlink=True) print(f"[north] done") main()