frontage: south block frontage, plus the placement bug it exposed
Adds the five remaining verified south-side buildings to the demo block (6922, 6902, 6838 El Capitan Theatre, 6822 Budget, 6806-6820, 6800 Lee Drug) exported in place from the OSM blockout and staged by the demo builder. Adding neighbours exposed a pre-existing placement bug that could not be seen while the hero stood alone: - UE south is +Y (south sidewalk Y +718..+1447), but the hero facade sat at Y -1450 on the NORTH side and at X -12024..-9420, which is 26 m east of the 6840 footprint (the frontage gap is X -14591..-12082). - The two north-side buildings were on the SOUTH side, because their exporter mirrored Y. Fixes: hero moved to X -13336 / Y +1307, inside its frontage gap; frontage and north buildings export without a Y mirror (the FBX preset already lands Blender -Y south on UE +Y south); player start and demo cameras moved to the north sidewalk looking south; sun raised to pitch -62 so both frontages read instead of the north side going to silhouette. Screenshots re-rendered; the four demo views are marked needs-review because the whole block changed.
This commit is contained in:
1 parent
01ccc61842
commit
8ca403fd08
41 files changed
+330
-82
No files matched your search
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.
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -191,3 +191,11 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO.
|
||||
- **A fresh git worktree has no compiled game binaries.** `Binaries/` is gitignored, so `UnrealEditor-Cmd` on a new worktree exits "abnormally (error code: 1)" before running the Python script, with no Python error in the log. Run `Engine/Build/BatchFiles/Linux/Build.sh GigLineEditor Linux Development -project=<worktree>/Game/GigLine/GigLine.uproject` first.
|
||||
- `/tmp/gigline/*.txt` result files are **shared across worktrees**. Reading `/tmp/gigline/demo-map.txt` after a run can show another worktree's stale output — check the file mtime, or use a per-worktree result path.
|
||||
- **Flat Constant3Vector materials read as plastic.** Giving each surface a roughness plus a world-space-noise blend between two shades (WorldPosition → Multiply → Noise → Lerp between two Constant3Vectors → BaseColor) is enough to stop the blockout looking like a toy; no textures required.
|
||||
|
||||
## 2026-11-07 — The Y-side bug (found when the frontage was added)
|
||||
|
||||
- **UE convention in this project: south = +Y, north = −Y.** Ground truth is the street mesh: `Sidewalk_North` is Y −1912..−1053 and `Sidewalk_South` Y +718..+1447.
|
||||
- The hero facade had been placed at **Y −1450 (north side)** and X −12024..−9420 — 26 m east of the 6840 footprint and on the wrong side of the street. It only looked right because it stood alone in an empty field; the approved screenshots were of a building with no context.
|
||||
- The two north-side buildings (TCL, Tussaud's) were similarly on the **south** side: `export_north_buildings.py` mirrored Y, which put them where the frontage belongs.
|
||||
- Fix: hero at X −13336 / Y +1307 (the frontage gap between 6902 and 6838); frontage and north buildings exported **without** a Y mirror (the FBX preset already maps Blender −Y south to UE +Y south).
|
||||
- Lesson: **place a building only against a neighbour or the street mesh, never in isolation.** A single object in an empty map hides any number of placement errors; adding the adjacent frontage immediately exposed this one.
|
||||
@@ -23,8 +23,9 @@ and exits — about a minute. The camera list lives in
|
||||
|
||||
## Shot list
|
||||
|
||||
All shots ☑ approved 2026-11-07, including the material look pass that changed
|
||||
every demo surface.
|
||||
Review-map shots ☑ approved. **Demo-map shots: needs review** — the block
|
||||
frontage pass (2026-11-07) added the neighbouring buildings and corrected the
|
||||
hero and north-building placement, so all four demo views changed.
|
||||
|
||||
| # | File | Preview | Map | View | What it shows |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
@@ -38,10 +39,10 @@ every demo surface.
|
||||
| 8 | `review-hero-portals.png` | [<img src="review-hero-portals.png" alt="hero portals" width="180">](review-hero-portals.png) | Review | 8 m, eye height | Three genuine 1.2 m portal recesses with flights and plinth |
|
||||
| 9 | `review-hero-facade-front.png` | [<img src="review-hero-facade-front.png" alt="hero facade front" width="180">](review-hero-facade-front.png) | Review | road side, straight-on | Hero façade elevation and column rhythm |
|
||||
| 10 | `review-hero-facade-oblique.png` | [<img src="review-hero-facade-oblique.png" alt="hero facade oblique" width="180">](review-hero-facade-oblique.png) | Review | north-west | Body depth and column line standing proud of the mass |
|
||||
| 11 | `demo/review-demo-spawn-view.png` | [<img src="demo/review-demo-spawn-view.png" alt="spawn view" width="180">](demo/review-demo-spawn-view.png) | Demo | spawn point | Spawn view from the north sidewalk: the hero façade across the road under fixed daytime light |
|
||||
| 12 | `demo/review-demo-street-level.png` | [<img src="demo/review-demo-street-level.png" alt="street level" width="180">](demo/review-demo-street-level.png) | Demo | eye height, north side | The façade colonnade and columns, sunlit with cast shadows |
|
||||
| 13 | `demo/review-demo-crossing.png` | [<img src="demo/review-demo-crossing.png" alt="crossing" width="180">](demo/review-demo-crossing.png) | Demo | along the crosswalk | The designated mid-block crossing at s=130 m (UE X -14956): three continental zebra bars on the asphalt, kerbs flushed to ramps |
|
||||
| 14 | `demo/review-demo-north-buildings.png` | [<img src="demo/review-demo-north-buildings.png" alt="north buildings" width="180">](demo/review-demo-north-buildings.png) | Demo | across the Blvd | North-side background buildings (TCL, Tussaud's), lit against the sky |
|
||||
| 11 | `demo/review-demo-spawn-view.png` | [<img src="demo/review-demo-spawn-view.png" alt="spawn view" width="180">](demo/review-demo-spawn-view.png) | Demo | north sidewalk | The whole block: hero façade between its neighbours, both sidewalks and the road |
|
||||
| 12 | `demo/review-demo-street-level.png` | [<img src="demo/review-demo-street-level.png" alt="street level" width="180">](demo/review-demo-street-level.png) | Demo | eye height, north side | The hero colonnade with the adjacent frontage buildings either side |
|
||||
| 13 | `demo/review-demo-crossing.png` | [<img src="demo/review-demo-crossing.png" alt="crossing" width="180">](demo/review-demo-crossing.png) | Demo | along the crosswalk | The designated mid-block crossing at s=130 m (UE X -14956): three zebra bars on the asphalt, with the south frontage and the hero colonnade behind |
|
||||
| 14 | `demo/review-demo-north-buildings.png` | [<img src="demo/review-demo-north-buildings.png" alt="north buildings" width="180">](demo/review-demo-north-buildings.png) | Demo | across the Blvd | North-side buildings (TCL, Tussaud's) seen from the south side across the road |
|
||||
|
||||
## Scene conventions
|
||||
|
||||
|
||||
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.
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.
@@ -84,7 +84,7 @@ The MPFB character asset is planned as the NPC template (see `ROADMAP.md`). Keep
|
||||
- [A] Collect reference photography for manual façade work. Local only, never committed: `Art/reference/` is gitignored. **72 images in eleven folders**: hero façades to 4k, the El Capitan Theatre exterior series, premiere-night staging, Ovation Hollywood, the north side, and the Lee Drug neighbour. Gaps largely closed by the Flickr/web-search pass: the hero entrance is now documented (three portals with individual short flights — the inherited "eight steps, 12 m wide" is overturned), and the 6806–6822 retail run appears in an oblique 2013 frame. Still missing: a clean isolated frame of the door recess and a night frame of 6840 itself.
|
||||
- [x] Download reference photography for the two north-side buildings inside the 50 m buffer — TCL Chinese Theatre (OSM way 424105908, 6925 Hollywood Blvd) and Madame Tussaud's (way 424105889, 6933 Hollywood Blvd). Done 2026-11-06 with `Tools/commons_fetch.py` against the Wikimedia Commons API: eleven frames in the local `Art/reference/north-chinese/` and `Art/reference/north-tussauds/`, provenance in each `sidecar.json`, nothing committed.
|
||||
- [x] Model hero façade for the El Capitan Entertainment Centre site. **Second pass built 2026-11-07** (proportions recalibrated from the 2009 photograph: entablature 3.4 m, parapet 2.2 m, architrave and cornice bands, square pedestals — the first pass had 5.7 m of blank wall above the capitals and read as a warehouse). **First pass built 2026-11-07** (`Tools/hero_facade_build.py` → `Art/blender/hero/hero-facade-2026-11-07.blend` + JSON part report with evidence per part → `Tools/ue_hero_facade_import.py` → `/Game/Hollywood/ElCapitan/SM_HeroFacade`, 1892 tris, 4 materials, placed on the measured building line). Six columns at 4.96 m over the 25.75 m frontage, plinth, three portal flights (5 risers, not the old 8), entablature 2.2 m, parapet 1.6 m with motto band and medallions. **Screenshot approved** (`Screenshots/review-hero-portals`, `review-hero-facade-front/oblique`). Next pass: banner and window placement, then materials.
|
||||
- [A] Model surrounding block frontage.
|
||||
- [A] Model surrounding block frontage. **Implemented 2026-11-07, screenshots awaiting approval.** The five remaining south-side buildings verified for the block (`Geo/verification/2026-11-06-el-capitan-block.md`) are exported in place from the OSM blockout by `Tools/export_block_frontage.py` -> `Tools/ue_import_block_frontage.py` -> `/Game/Hollywood/Frontage/`, and staged by the demo builder: 6922, 6902, 6838 El Capitan Theatre, 6822 Budget, 6806-6820, 6800 Lee Drug. **Adding them exposed a pre-existing placement bug**: UE south is +Y (the south sidewalk is Y +718..+1447) but the hero facade sat at Y -1450 (north side) and X -12024..-9420, i.e. 26 m east of its own footprint and on the wrong side of the street; the two north-side buildings were likewise on the south side. The hero is now at X -13336 / Y +1307 (inside the frontage gap between 6902 and 6838) and the north buildings are back on the north side (Y -1802..-9431). The sun was raised to pitch -62 so both frontages read instead of one being silhouetted.
|
||||
- [x] Model simplified background buildings directly across Hollywood Boulevard. Done 2026-11-07, the two in-scope north-side buildings — TCL Chinese Theatre (SM_TCL_Chinese_Theatre) and Madame Tussaud's (SM_Madame_Tussauds) — taken from the verified OSM blockout volumes and exported with `ue_metric_v1`, with a Y-mirror so they land north of Hollywood Blvd across the street from the hero (TCL spans Unreal Y 1802..9431, Tussaud's 1888..7586; road centreline ≈ 0, hero façade at Y −1450). Staged in the DemoMap as `North_TCL_Chinese` / `North_Madame_Tussauds`; demo shot `review-03-demo-north-buildings` captured. Simple flat facade materials (surfaces are the `0.1.4` patch).
|
||||
- [A] Build sidewalks, roads, and collision meshes. Terrain, road, sidewalks and kerbs exist (`Art/blender/terrain/`, `street/`) and are assembled in `site/site-2026-11-06.blend`; collision and details (crossing markings, kerb radii, aprons) are not built. Ground must follow the DEM: 3.94 m fall along the block, ~2 % crown between the gutters at ±10–11 m from the centreline, north sidewalk higher than south. Kerb height is an unresolved assumption — the DEM does not resolve it (`Geo/verification/2026-11-06-cross-sections.md`).
|
||||
- [x] Materials and look development for all exported assets. **Done 2026-11-07, screenshots approved.** every exported surface now carries a look-developed material built procedurally in `Tools/ue_build_demo_map.py` (`ensure_material`): base colour with a world-space noise blend between two shades for large-scale variation, plus an explicit roughness and specular. Set is `M_Asphalt` 0.92, `M_Concrete` 0.88, `M_KerbConcrete` 0.85, `M_Ground` 0.98, `M_RoadPaint` 0.62, `M_FacadeStone` 0.72 (hero façade) and `M_Stucco` 0.86 (TCL, Tussaud's), assigned by mesh and by actor label. Materials are rebuilt on every run so a stale asset cannot mask a look change. The richer texture-based pass (baked/procedural brick, brick_facade and seamless_concrete generators) stays in the `0.1.4` façade patch.
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# Export the south-side block frontage from the OSM blockout.
|
||||
#
|
||||
# blender -b --factory-startup Art/blender/blockout/blockout-2026-11-06.blend \
|
||||
# --python Tools/export_block_frontage.py -- --out /tmp/gigline/frontage
|
||||
#
|
||||
# The building set is the one verified in
|
||||
# `Geo/verification/2026-11-06-el-capitan-block.md` ("South frontage, west to
|
||||
# east"), minus 6840 which is modelled by hand as SM_HeroFacade. Everything is
|
||||
# already in the shared project frame (metres, X east / Y north / Z up, origin
|
||||
# Hollywood x Highland), so each object exports at its own world position with no
|
||||
# transform: these are south-side buildings and need no Y mirror.
|
||||
#
|
||||
# The block runs from Highland (X 0) to Orange Drive (X -279.6 m). Objects that
|
||||
# are OSM `element` placeholders are named by their verified address instead, so
|
||||
# the Unreal asset names say what the building is.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
import bpy
|
||||
|
||||
# blockout object name -> (asset name, note). Addresses from the verification doc.
|
||||
BUILDINGS = {
|
||||
# Way 424024151, 6922, commercial 12 levels - the west end of the frontage.
|
||||
"element.020": ("SM_Hollywood_6922", "6922, west end of the frontage"),
|
||||
# Way 206486872, 6902, retail, height 13.8.
|
||||
"element": ("SM_Hollywood_6902", "6902, retail, H 13.8"),
|
||||
# Way 424024148, 6838, El Capitan Theatre - distinct from 6840.
|
||||
"El Capitan Theatre": ("SM_ElCapitanTheatre", "6838, cinema, 6 levels"),
|
||||
# Way 424024144, 6822, Budget car rental.
|
||||
"Budget": ("SM_Budget_6822", "6822, car rental, H 5.5"),
|
||||
# Way 424024150, 6806-6820, retail, height 12.1.
|
||||
"element.019": ("SM_Hollywood_6806", "6806-6820, retail, H 12.1"),
|
||||
# Way 424024149, 6800, Lee Drug Building.
|
||||
"Lee Drug Building": ("SM_LeeDrug_6800", "6800, Lee Drug Building, H 12.1"),
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--out", default="/tmp/gigline/frontage")
|
||||
args = ap.parse_args(argv)
|
||||
os.makedirs(args.out, exist_ok=True)
|
||||
|
||||
print(f"[frontage] scene objects: {len(bpy.data.objects)}")
|
||||
exported = 0
|
||||
for obj_name, (asset_name, note) in BUILDINGS.items():
|
||||
obj = bpy.data.objects.get(obj_name)
|
||||
if obj is None or obj.type != "MESH":
|
||||
print(f"[frontage] MISSING blockout object {obj_name!r}")
|
||||
continue
|
||||
|
||||
mesh = obj.data
|
||||
if not mesh.materials:
|
||||
mat = bpy.data.materials.new(f"M_{asset_name}")
|
||||
mat.diffuse_color = (0.72, 0.70, 0.66, 1.0)
|
||||
mat.use_nodes = False
|
||||
mesh.materials.append(mat)
|
||||
|
||||
# No Y mirror: the FBX preset lands Blender -Y (south) on Unreal +Y,
|
||||
# which is the south side of the street (south sidewalk Y +718..+1447).
|
||||
new_mesh = obj.data
|
||||
new_obj = obj
|
||||
|
||||
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, asset_name + ".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,
|
||||
)
|
||||
world = new_obj.matrix_world
|
||||
zs = [(world @ v.co).z for v in new_mesh.vertices]
|
||||
ys = [(world @ v.co).y for v in new_mesh.vertices]
|
||||
xs = [(world @ v.co).x for v in new_mesh.vertices]
|
||||
print(f"[frontage] {asset_name:22} {note:34} "
|
||||
f"X {min(xs):7.1f}..{max(xs):6.1f} Y {min(ys):6.1f}..{max(ys):6.1f} "
|
||||
f"H {max(zs):5.1f} verts {len(new_mesh.vertices):5} -> {path}")
|
||||
exported += 1
|
||||
|
||||
print(f"[frontage] exported {exported} of {len(BUILDINGS)} frontage buildings")
|
||||
|
||||
|
||||
main()
|
||||
@@ -40,27 +40,11 @@ def main():
|
||||
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()
|
||||
# No copy and no Y mirror: the FBX preset already lands Blender +Y
|
||||
# (north) on Unreal -Y, and UE north is -Y here (north sidewalk
|
||||
# Y -1912..-1053). The old mirror put both buildings on the south side.
|
||||
new_obj = obj
|
||||
new_mesh = mesh
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
new_obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = new_obj
|
||||
@@ -80,6 +64,7 @@ def main():
|
||||
path_mode="AUTO",
|
||||
bake_space_transform=False,
|
||||
)
|
||||
world = new_obj.matrix_world
|
||||
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}")
|
||||
|
||||
@@ -146,7 +146,7 @@ def build():
|
||||
log(f"could not create {MAP}")
|
||||
return
|
||||
|
||||
removed = clear(("Demo_", "PlayerStart", "Hero_Facade"))
|
||||
removed = clear(("Demo_", "PlayerStart", "Hero_Facade", "Frontage_"))
|
||||
log(f"cleared {removed} previous demo actors")
|
||||
|
||||
# --- lighting: fixed daytime ------------------------------------------
|
||||
@@ -162,7 +162,7 @@ def build():
|
||||
# 3. Ambience. A height fog gives the street depth and hides the terrain
|
||||
# edge that otherwise reads as a black band at the horizon.
|
||||
sun = spawn(unreal.DirectionalLight, unreal.Vector(0, 0, 2000), "Demo_Sun",
|
||||
unreal.Rotator(pitch=-50.0, yaw=120.0, roll=0.0))
|
||||
unreal.Rotator(pitch=-62.0, yaw=120.0, roll=0.0))
|
||||
if sun:
|
||||
comp = sun.get_component_by_class(unreal.DirectionalLightComponent)
|
||||
if comp:
|
||||
@@ -181,7 +181,7 @@ def build():
|
||||
comp.set_mobility(unreal.ComponentMobility.MOVABLE)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
log(f"sun mobility not set: {exc!r}")
|
||||
log("staged: Demo_Sun (pitch -50, yaw 120, intensity 4, warm)")
|
||||
log("staged: Demo_Sun (pitch -62, yaw 120, intensity 4, warm; higher sun so both frontages read)")
|
||||
|
||||
sky = spawn(unreal.SkyLight, unreal.Vector(0, 0, 2000), "Demo_SkyLight")
|
||||
if sky:
|
||||
@@ -246,9 +246,14 @@ def build():
|
||||
log("staged: Demo_PostProcess (fixed exposure, min=max brightness 1.0)")
|
||||
|
||||
# --- hero facade on the measured building line ------------------------
|
||||
# Hero placement, corrected 2026-11-07 when the neighbouring frontage was
|
||||
# added: UE south is +Y (the south sidewalk is Y +718..+1447) and the block
|
||||
# frontage sits at X -24276..-12082 with a gap at -14591..-12082 for 6840.
|
||||
# The old (-10722.5, -1443) put the facade 26 m east of its footprint and on
|
||||
# the NORTH side of the street, which only looked right while it stood alone.
|
||||
hero = unreal.EditorAssetLibrary.load_asset("/Game/Hollywood/ElCapitan/SM_HeroFacade")
|
||||
if hero:
|
||||
actor = spawn(unreal.StaticMeshActor, unreal.Vector(-10722.5, -1443.0, 0.0), "Hero_Facade")
|
||||
actor = spawn(unreal.StaticMeshActor, unreal.Vector(-13336.0, 1307.0, 0.0), "Hero_Facade")
|
||||
if actor:
|
||||
actor.static_mesh_component.set_static_mesh(hero)
|
||||
actor.static_mesh_component.set_mobility(unreal.ComponentMobility.MOVABLE)
|
||||
@@ -323,14 +328,47 @@ def build():
|
||||
assigned += 1
|
||||
log(f"assigned look materials to {assigned} facade/background actors")
|
||||
|
||||
# --- surrounding block frontage ---------------------------------------
|
||||
# The other five south-side buildings verified for the block
|
||||
# (Geo/verification/2026-11-06-el-capitan-block.md), exported in place from
|
||||
# the OSM blockout with a Y mirror so they sit on the south side with the
|
||||
# hero. The 6840 site itself is the hand-modelled SM_HeroFacade above.
|
||||
FRONTAGE = (
|
||||
("SM_Hollywood_6922", "6922"),
|
||||
("SM_Hollywood_6902", "6902"),
|
||||
("SM_ElCapitanTheatre", "6838 El Capitan Theatre"),
|
||||
("SM_Budget_6822", "6822 Budget"),
|
||||
("SM_Hollywood_6806", "6806-6820"),
|
||||
("SM_LeeDrug_6800", "6800 Lee Drug"),
|
||||
)
|
||||
staged_frontage = 0
|
||||
for asset_name, label in FRONTAGE:
|
||||
mesh = unreal.EditorAssetLibrary.load_asset(f"/Game/Hollywood/Frontage/{asset_name}")
|
||||
if mesh is None:
|
||||
log(f"MISSING frontage {asset_name} — run Tools/ue_import_block_frontage.py")
|
||||
continue
|
||||
actor = spawn(unreal.StaticMeshActor, unreal.Vector(0, 0, 0), f"Frontage_{asset_name}")
|
||||
if actor:
|
||||
comp = actor.static_mesh_component
|
||||
comp.set_static_mesh(mesh)
|
||||
comp.set_mobility(unreal.ComponentMobility.MOVABLE)
|
||||
# The two theatre buildings read as stone; the retail run as stucco.
|
||||
mat_name = "M_FacadeStone" if "Theatre" in asset_name else "M_Stucco"
|
||||
if mat_name in built:
|
||||
comp.set_material(0, built[mat_name])
|
||||
staged_frontage += 1
|
||||
log(f"staged {staged_frontage} frontage buildings")
|
||||
|
||||
# --- player start: north sidewalk, facing the hero frontage -------------
|
||||
# Signs were measured from the imported meshes rather than assumed: the FBX
|
||||
# preset flips north, so in Unreal the road spans Y -1382..+1047, the NORTH
|
||||
# sidewalk is at Y -1912..-1053 and the SOUTH sidewalk at Y +718..+1447. The
|
||||
# facade stands at Y -1450. Stand on the north sidewalk and look north (-Y).
|
||||
spawn(unreal.PlayerStart, unreal.Vector(-10722.5, -3500.0, 120.0), "Demo_PlayerStart",
|
||||
unreal.Rotator(pitch=0.0, yaw=0.0, roll=0.0))
|
||||
log("staged: Demo_PlayerStart on the north sidewalk facing south")
|
||||
# North sidewalk (Y -1912..-1053), facing south (+Y) across the road at the
|
||||
# hero on the south side. Yaw 90 looks along +Y.
|
||||
spawn(unreal.PlayerStart, unreal.Vector(-13336.0, -1700.0, 120.0), "Demo_PlayerStart",
|
||||
unreal.Rotator(pitch=0.0, yaw=90.0, roll=0.0))
|
||||
log("staged: Demo_PlayerStart on the north sidewalk facing south (+Y)")
|
||||
|
||||
# A lockable LFS .umap checks out read-only, which makes save_map silently
|
||||
# return False — chmod u+w first or the staged actors never persist.
|
||||
|
||||
@@ -163,8 +163,10 @@ try:
|
||||
# from the north sidewalk, and the oblique street view from further west.
|
||||
# Hero placement in Unreal centimetres (see Geo/manifests/local-origin.md):
|
||||
# front plane on the building line, body behind it.
|
||||
hero_x = -12024.5 + 1302.0
|
||||
hero_y = -1450.0 + 7.0
|
||||
# Corrected 2026-11-07 with the block frontage: UE south is +Y (south
|
||||
# sidewalk Y +718..+1447) and 6840 occupies the frontage gap X -14591..-12082.
|
||||
hero_x = -13336.0
|
||||
hero_y = 1307.0
|
||||
hero = unreal.EditorAssetLibrary.load_asset("/Game/Hollywood/ElCapitan/SM_HeroFacade")
|
||||
# The imported mesh spans Y -7..+1250 cm in local space (front plane at -7, the
|
||||
# body behind it) and is centred on X, so the actor sits at building line + 7 cm.
|
||||
@@ -274,12 +276,12 @@ try:
|
||||
demo_shots = [
|
||||
# 14 m back so the 14.5 m elevation fits: at 2 m the camera sees only
|
||||
# the colonnade's underside.
|
||||
("demo-spawn-view", unreal.Vector(-10722.5, -3500, 165), unreal.Vector(-10722.5, -1450, 700)),
|
||||
("demo-spawn-view", unreal.Vector(-13336, -3100, 420), unreal.Vector(-13336, 1300, 620)),
|
||||
# Street level, from the north sidewalk: the old camera sat at Y -400,
|
||||
# inside the facade body (which spans Y -1457..-200), so it looked at
|
||||
# the unlit back face. Y -2600 is on the sidewalk in front of the lit
|
||||
# elevation.
|
||||
("demo-street-level", unreal.Vector(-10850, -2600, 170), unreal.Vector(-10722.5, -1450, 400)),
|
||||
("demo-street-level", unreal.Vector(-13420, -1650, 170), unreal.Vector(-13336, 1300, 400)),
|
||||
# The designated mid-block crossing. Street arc length runs from the
|
||||
# west end (s=0 at X -27966 cm), so s=130.1 m is UE X -14956, not the
|
||||
# -24291 the old camera used (that is the s=36.6 crossing). Camera sits
|
||||
@@ -288,7 +290,7 @@ try:
|
||||
("demo-crossing", unreal.Vector(-15250, -2500, 400), unreal.Vector(-14956, 400, 150)),
|
||||
# the two north-side background buildings (TCL, Tussaud's) seen from
|
||||
# the south sidewalk, across Hollywood Blvd: their frontage and mass.
|
||||
("demo-north-buildings", unreal.Vector(-22800, -1000, 400), unreal.Vector(-22800, 3000, 300)),
|
||||
("demo-north-buildings", unreal.Vector(-22800, 2600, 420), unreal.Vector(-22800, -4200, 300)),
|
||||
]
|
||||
seq = spawn(unreal.GigLineShotActor, unreal.Vector(0, 0, 300), "ShotSequencer")
|
||||
if seq:
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# Import the south-side block frontage FBX set into Unreal.
|
||||
#
|
||||
# blender ... --python Tools/export_block_frontage.py -- --out /tmp/gigline/frontage
|
||||
# <engine>/Engine/Binaries/Linux/UnrealEditor-Cmd <uproject> -run=pythonscript \
|
||||
# -script=<repo>/Tools/ue_import_block_frontage.py -nullrhi -unattended -nopause -stdout
|
||||
#
|
||||
# Each mesh already sits at its world position in the project frame (the FBX was
|
||||
# exported without moving the object), so the actor is spawned at the origin and
|
||||
# the geometry carries the offset. Destination: /Game/Hollywood/Frontage/<name>.
|
||||
#
|
||||
# Staging into the DemoMap is done by Tools/ue_build_demo_map.py, which also
|
||||
# assigns the look materials; this script only produces the assets.
|
||||
|
||||
import glob
|
||||
import os
|
||||
|
||||
import unreal
|
||||
|
||||
SRC = "/tmp/gigline/frontage"
|
||||
DEST = "/Game/Hollywood/Frontage"
|
||||
RESULT = "/tmp/gigline/frontage-import.txt"
|
||||
lines = []
|
||||
|
||||
|
||||
def log(msg):
|
||||
lines.append(str(msg))
|
||||
unreal.log(str(msg))
|
||||
|
||||
|
||||
def import_fbx(path, name):
|
||||
task = unreal.AssetImportTask()
|
||||
task.filename = path
|
||||
task.destination_path = DEST
|
||||
task.destination_name = name
|
||||
task.automated = True
|
||||
task.save = True
|
||||
task.replace_existing = True
|
||||
|
||||
ui = unreal.FbxImportUI()
|
||||
ui.import_mesh = True
|
||||
ui.import_materials = True
|
||||
ui.import_textures = False
|
||||
ui.import_as_skeletal = False
|
||||
smd = ui.static_mesh_import_data
|
||||
smd.import_uniform_scale = 1.0
|
||||
smd.combine_meshes = True
|
||||
smd.convert_scene_unit = False
|
||||
smd.force_front_x_axis = False
|
||||
smd.normal_import_method = unreal.FBXNormalImportMethod.FBXNIM_IMPORT_NORMALS
|
||||
task.options = ui
|
||||
unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task])
|
||||
|
||||
mesh = unreal.EditorAssetLibrary.load_asset(f"{DEST}/{name}")
|
||||
if mesh is None:
|
||||
log(f"MISSING after import: {DEST}/{name}")
|
||||
return
|
||||
# Buildings are solids the player can walk into the side of: simple + complex
|
||||
# so the blockout blocks the player without expensive per-triangle queries.
|
||||
try:
|
||||
body = mesh.get_editor_property("body_setup")
|
||||
body.set_editor_property("collision_trace_flag",
|
||||
unreal.CollisionTraceFlag.CTF_USE_SIMPLE_AND_COMPLEX)
|
||||
mesh.set_editor_property("body_setup", body)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
log(f"{name}: collision flag not set ({exc!r})")
|
||||
box = mesh.get_bounding_box()
|
||||
mn, mx = box.min, box.max
|
||||
# World-space placement, in Unreal centimetres, straight from the mesh bounds.
|
||||
log(f"{name:22} X {mn.x:8.0f}..{mx.x:8.0f} Y {mn.y:7.0f}..{mx.y:7.0f} "
|
||||
f"Z {mn.z:5.0f}..{mx.z:5.0f}")
|
||||
|
||||
|
||||
def main():
|
||||
files = sorted(glob.glob(os.path.join(SRC, "*.fbx")))
|
||||
if not files:
|
||||
log(f"no FBX in {SRC}; run Tools/export_block_frontage.py first")
|
||||
return
|
||||
for path in files:
|
||||
name = os.path.splitext(os.path.basename(path))[0]
|
||||
import_fbx(path, name)
|
||||
unreal.EditorLoadingAndSavingUtils.save_dirty_packages(True, True)
|
||||
|
||||
|
||||
try:
|
||||
main()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
import traceback
|
||||
log(f"FAILED: {type(exc).__name__}: {exc}")
|
||||
log(traceback.format_exc())
|
||||
|
||||
with open(RESULT, "w") as f:
|
||||
f.write("\n".join(lines) + "\n")
|
||||
Reference in new issue
Block a user