4.3 KiB
4.3 KiB
Extract road module
Goal
Move Blender road assembly out of blender/generate_scene.py into a dedicated
bpy-layer module, keeping generated .blend / .glb / metadata structure
unchanged. This completes the P2 feature-module extraction except for the
deferred full features/ registry.
Background
.trellis/spec/guides/artifact-parity-guide.mdrecords P2 as partial:water.py,grass.py,scrub.py,tree.py,fountain.py, andbuilding.pyare already split out, while roads still live ingenerate_scene.py.blender/generate_scene.py:148definesadd_geojson_layer(), which reads one osm2streets GeoJSON road layer, filters by bounds, projects coordinates, clips polygons, batches them asRoad_<layer>, and returns a feature count.blender/generate_scene.py:656createsroad_matsby zippingcatalog.ROAD_LAYERSwithcatalog.road_material_specs().blender/generate_scene.py:741runscatalog.check_layers(geojson_dir)and printsLayer catalog warning:messages before iteratingROAD_LAYERS.blender/generate_scene.py:750falls back to simple OSM highway polylines whenroad_counts["road_surface"]is zero.blender/generate_scene.py:866storesscene["road_feature_counts"]; the sameroad_countsobject is emitted inSCENE_DONEasroad_features.
Requirements
- Add a new bpy-layer module at
blender/osmassets/roads.py. - Move the current roads assembly behavior into the new module:
- GeoJSON layer mesh assembly currently in
add_geojson_layer(); - simple OSM highway fallback currently in the
road_surface == 0block.
- GeoJSON layer mesh assembly currently in
- Keep
generate_scene.pyresponsible for:- creating
road_matsfromcatalog.ROAD_LAYERSandcatalog.road_material_specs(); - running
catalog.check_layers()and printing existing warning text; - owning
road_counts; - writing
scene["road_feature_counts"]; - writing the existing
SCENE_DONEJSON shape.
- creating
- Preserve existing road object names and mesh names:
Road_<layer_id>OSM_Road_<way_id>
- Preserve existing GeoJSON behavior:
- missing layer file returns count
0; - feature is skipped when
feature_in_bounds()is false; - rings come from
geometry_rings(); - projected rings are clipped with
clip_polygon(); - only rings with at least three points are batched and counted.
- missing layer file returns count
- Preserve existing OSM fallback behavior:
- fallback triggers only when
road_counts.get("road_surface", 0) == 0; - only ways with a
highwaytag and at least two coordinates are drawn; - widths remain
secondary: 7.0,residential: 5.5,service: 3.5, default4.0; - fallback material remains
road_mats["road_surface"]; - fallback z remains
0.03; - fallback does not add to
road_counts.
- fallback triggers only when
- Do not introduce a full
features/registry in this task. - Do not modify
ROAD_LAYERS,SCENE_LAYERS, material definitions,MATERIALSorder, GeoJSON schema, z-index/z-height values, stdout markers, parity ignore lists, or known unrelated defects D1-D3.
Acceptance Criteria
blender/osmassets/roads.pycontains road assembly behavior and imports only bpy-layer-safe dependencies.blender/generate_scene.pyimports and calls the new roads module; no inlineadd_geojson_layer()remains there.road_counts,scene["road_feature_counts"], andSCENE_DONEroad_featuresremain unchanged.- Existing
Layer catalog warning:print behavior remains ingenerate_scene.py. python3 -m py_compile blender/osmassets/roads.pypasses.python3 -m py_compile blender/generate_scene.pypasses.python3 -m unittest blender/tests/test_pure.pypasses.- A before/after parity comparison is run for the Blender/Cesium stages and any non-ignored diff is either absent or explicitly explained as expected. For this refactor, the expected result is no contract diff.
Out Of Scope
- Full
features/registry implementation. - Any change to osm2streets road splitting,
SCENE_LAYERS, or QGIS pipeline behavior. - Any change to
catalog.ROAD_LAYERS, material names, color values, or order. - Any change to fallback highway widths, z values, object names, or counts.
- Turning
catalog.check_layers()warnings into errors. - Moving
road_matscreation orroad_feature_countsscene metadata out ofgenerate_scene.py.
Open Questions
None.