# Phase 3:Manifest 驱动的道路渲染设计 ## Boundary 道路编译器是图层事实源,输出 `/manifest.json`;Blender 是渲染适配器,读取 manifest 并用宿主 `catalog.MATERIALS` / `ROAD_LAYERS` 完成材质与高度映射。建筑、植被、水体、OSM legacy 图层不改变。 ``` compiler CLI -> native-road/manifest.json + 12 declared GeoJSON sources -> generate_scene.py -> osmassets/native_roads.py -> catalog material/z lookup -> roads.assemble_geojson_layer ``` ## Manifest v1.1 `manifest.json` 顶层包含 `contract: "native-road-package/v1.1"`、`areaId` 和 `layers`。`layers` 必须恰好声明编译器输出的 12 个 source: - `road_surface`, `intersection_surface`, `sidewalk_surface`, `edge_lines`, `lane_separators`, `center_lines`, `crosswalks`, `vehicle_stop_lines`, `direction_arrows`, `turn_arrows` - `lane_centerlines`, `connectors` 每项字段: ```json { "source": "center_lines", "role": "marking", "materialLayer": "center_lines", "splitBy": { "prop": "color", "cases": [ {"match": "white", "material": "native_center_line_white"}, {"default": true, "material": "center_lines"} ] } } ``` `role` 为 `surface` 或 `marking` 时必须有 `materialLayer`;`semantic` 不得有材质要求,Blender 必须跳过其 GeoJSON。`splitBy` 只支持精确属性匹配和一个 default 分支,避免把渲染表达式语言复制进编译器。 编译器在原子提升前校验:每个声明 source 都对应 `layers/.geojson`,目录中没有未声明的 GeoJSON;manifest 自身必须是有效 JSON。新增 manifest 不改变已有文件内容。 ## Blender Adapter 新建 `blender/osmassets/native_roads.py`,公开一个接收 `native_road_dir`, `projector`, `collection`, `road_mats`, `material_layers` 的装配函数。模块负责读取/校验 manifest、解析 split cases、调用既有 `roads.assemble_geojson_layer`;不拥有图层注册表、不创建材质、不维护场景总计数。 `generate_scene.py` 仅负责 native-road 目录存在性、catalog material lookup、调用 adapter 和合并 `road_counts`。删除 `catalog.NATIVE_ROAD_LAYERS`;保留 `catalog.ROAD_LAYERS` 作为宿主材质和 z 高度事实源。 未知 `materialLayer`、缺少 source 文件、重复/遗漏 source、非法 role 或非法 splitBy 必须抛出 `RuntimeError`,不能静默跳过。semantic 图层必须不读取 GeoJSON、不创建对象、不增加 road count。 ## Compatibility and Rollback 编译器契约从 `native-road-package/v1` 增加到 `v1.1`;manifest 是 v1.1 的必需输出。Blender 不提供旧 manifest fallback,因为新消费边界必须尽早暴露旧 compiler;回滚时恢复 `NATIVE_ROAD_LAYERS` 内联分支即可。旧 v1 产物仍可由旧 compiler tag 生成,不被本阶段改写。 ## Verification - 两个支持区域的 native-road 文件 parity:除新增 `manifest.json` 外所有现有 hash、orderHash、bytes 不变。 - Blender 结构摘要和预览图与 Phase 0 基线一致;完整 Blender/Metal 运行需提权。 - 纯 Python schema/manifest 测试覆盖 12 source、semantic skip、splitBy white/yellow、未知材质、缺文件和额外文件。 - throwaway `debug_probe.geojson` + manifest 实测:不改宿主代码即可生成 Blender 几何;验证后删除 probe 并再次跑 parity。