Commit Graph

39 Commits

Author SHA1 Message Date
bc845444bb fix: restore live V2X signal and vehicle fidelity in Cesium preview
The ported overlay used the correct REST paths but lost the data handling
from the source dashboard's live-intersection view (HologramCross), so
signals rendered permanently red and vehicles often never appeared.

- Lamp status codes now follow the dashboard dictionary (11/21/22/23/31).
  The previous 2/3 reading made every real push fall through to red. The
  dictionary lives only in the overlay; the preview consumes normalized
  {nodeKeys, color, countDown} entries so the two copies cannot drift.
- Bind V2X phases to native signal heads geometrically. The runtime
  document has no phaseNo, so the old lookup fell back to signal.id and
  never matched, leaving the dynamic assembly dark. Travel heading is
  recovered as faceHeadingDegrees + 180, per the generator's
  mast = travel - 90 / face = travel + 180. Verified 7/7 exact matches
  against the fengshu-er-road runtime document.
- A phase now lights every approach it drives; the phase -> single entity
  map silently overwrote all but the last.
- Drive the countdown assets from the push's countDown field.
- All three sockets heartbeat every 30s and reconnect with backoff,
  replaying their subscription frame. Without this the service dropped
  the connection and the scene emptied after about a minute.
- The OBU socket sends its bounds frame on connect and on camera move;
  it previously sent nothing at all.
- Vehicles are swept when a push goes stale and their slots reused, so
  they no longer accumulate as ghosts. Models follow the dashboard's
  car_obu.glb / ${type}${subType}.glb naming.
- Parse vehicle pushes leniently, since the dashboard uses saferEval and
  the payload is not guaranteed to be strict JSON. Failures are counted
  and surfaced rather than dropped; no eval is introduced.
- Drop FlowTravelRatio/queryListWeek, which is not part of this view.

Also corrects a stale spec rule that required vehicleModelNames to be
empty. Live V2X vehicles need packaged models; the real invariant is no
generated routes or traffic simulation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 09:20:50 +08:00
bb2a1449ac fix: keep V2X intersection code out of login UI 2026-08-24 14:47:25 +08:00
b7031f145a fix: use live V2X vehicles only in preview 2026-08-24 14:42:31 +08:00
ee273c5cd6 feat: add live V2X Cesium preview overlay 2026-08-24 14:20:16 +08:00
5403936ae4 feat: add native preview traffic simulation 2026-08-18 16:57:27 +08:00
396df5127c Refactor area preview orchestration 2026-08-04 12:55:20 +08:00
463cb06be4 Add configurable area asset budgets 2026-08-04 12:28:43 +08:00
e1f5207e97 Add OSM area preflight 2026-08-04 11:58:12 +08:00
5874cf9379 Add full stage manifests 2026-08-04 11:37:20 +08:00
7fcc4ee8cc Add area quality gate 2026-08-04 10:42:10 +08:00
2832383f6e Add GLB stage manifests 2026-08-04 09:45:51 +08:00
d4c3baf608 Add area diagnostics command 2026-08-04 09:16:14 +08:00
95f8458ad2 Fix OSM multipolygon buildings 2026-08-03 18:15:22 +08:00
7ba85946dc Add optional GLB compression stage 2026-08-03 17:50:21 +08:00
dbb5705d8e Adopt Shapespark vegetation assets 2026-08-03 17:10:17 +08:00
e58a92803d Record rejected low-poly bush experiment 2026-08-03 15:55:06 +08:00
0d2dc2228c Improve Cesium cruise smoothness 2026-08-03 15:17:51 +08:00
f569d45e74 Clean stale tuft density comment 2026-08-03 14:20:18 +08:00
ff18217af5 Add feature registry dispatch 2026-08-03 14:02:28 +08:00
0f3c1ee635 Refactor road assembly module 2026-08-03 13:39:05 +08:00
032922ae99 Refactor building assembly module 2026-08-03 12:52:10 +08:00
627105555f Refactor fountain assembly module 2026-08-03 12:35:51 +08:00
68829214fb docs: Archive osmassets refactor plan 2026-08-03 12:12:49 +08:00
eb4a0d9b2a fix: 树发黑的真正原因是反照率没提亮,并加饱和度让远看更绿
emissive 提到 0.8 仍然发黑:它乘的是本来就很暗的反照率,0.8 × 深绿约等于
sRGB [0.22, 0.31, 0.11],还是暗的。要提的是反照率本身。

Cesium 截图定位:草亮黄绿、建筑近白、路面浅灰,只有树暗。这棵树图集的叶片
本来就是深绿(绿色系像素均值 sRGB [0.249, 0.35, 0.12]),按真实反照率渲染
是对的,但场景里其他材质都被手工提亮过——EXPORT_TINTS 草 0.72、带肋墙面
0.86,EXPORT_EMISSION_OVERRIDES 建筑 0.18,全是针对 Cesium 偏白的默认光照
调出来的。新资产没调过,是唯一如实渲染的东西,放旁边就显得发黑。

- FOLIAGE_ALBEDO_GAIN = 2.1,在抠图植被 dilate 那一遍顺带乘上。用增益而非
  tint:其他材质是单一表面,而这是同时装着叶片/树皮/果实的图集,往绿色混会
  把树干染绿。缩放保留色相关系,只把整体抬到和邻居一样的曝光。
- FOLIAGE_SATURATION = 1.75,绕各像素自身 Rec.709 亮度做饱和度拉伸。图集本
  来就偏灰(平均饱和度 0.22),远看时 mip 把叶片、树皮、缝隙混在一起会更往
  中性靠。绕亮度拉伸把叶片推绿而基本不动本来中性的部分,也没有绿色 tint 强
  加给树干的色相偏移。叶片 sRGB → [0.262, 0.529, 0.021],饱和度 0.22 → 0.34,
  过曝到纯白的像素占 0.3%。
- FOLIAGE_EMISSION 回调 0.25,它只负责给背光面兜底。
- 新增 triangulate_mesh():export_tangents 打开后刷了 55 行「切向空间只能只算
  三角/四边形」,MeshBatch 建的 OSM 轮廓都是 n-gon。glTF 只有三角形,导出时
  无论如何都会三角化,提前做不改变任何输出三角形(三角数 51719 前后一致),
  切线 49/102 → 102/102,警告归零。

被数据排除的假设:贴图颜色全链路逐位一致;模拟 mip 链可见像素亮度
0.127→0.124;法线贴图抠图区是干净平面法线;GLB 重新导入 Blender 渲染正常。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 13:23:44 +08:00
afada31469 fix: 树在 Cesium 远看发黑 — 补 emissive 并导出切线
黑色色块修掉后仍存在:近看正常,远看整棵树是暗色块。逐项排除:

- 贴图颜色全链路无偏移,源 4k / 降采样 2k / GLB 内 PNG 的 opaque 均值
  都是 sRGB [0.409, 0.406, 0.362],不是 gamma 问题。
- 模拟 GPU mip 链,可见像素亮度 mip0→mip6 只从 0.127 变到 0.124,
  覆盖率稳定 0.42,不是 mipmap 变暗。
- 法线贴图抠图区域是干净的平面法线 [0.494, 0.512, 0.988],无黑像素。

真实原因是缺 emissive 补偿。预览页 skyBox / skyAtmosphere / sun 全部关闭
且未配置环境贴图,Cesium 只剩很弱的默认球谐环境光,太阳直射不到的面接近
全黑——这正是 EXPORT_EMISSION_OVERRIDES 存在的原因(建筑 0.18,程序化树冠
0.015~0.02)。树冠绝大部分是背光叶片卡片,远看塌成一团暗色,近看能看到
向阳面所以还行。apple 材质不在那张表里。

- 抠图植被把 diffuse 接回 Emission Color,FOLIAGE_EMISSION = 0.22。
  用带贴图的自发光而非平坦颜色:常量会把树干染成叶子绿,而这样每个像素
  下限是自身反照率的一个比例。不增加字节,emissiveTexture 指向 base color
  已在用的同一张图。
- 打开 export_tangents:apple 有法线贴图但图元无 TANGENT,缺失时切线由
  渲染器推导,在双面薄片叶子卡上不可靠。49/102 图元带上切线,顺带修正
  建筑法线贴图,GLB +0.83MB。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 12:00:06 +08:00
2139990818 feat: 树渲染改用 apple/fattree 模型,修复 Cesium alpha 抠图丢失
tree_style 新增 apple(SpeedTree Red Delicious,4475 tris,alpha 抠图叶片
+ 法线贴图)和 fattree(低面数卡通树,2238 tris,实体几何)。

高度改为按模型自身包围盒归一化到目标高度,树根落在 z=0,不再用魔数;
每棵树按序号做确定性抖动(缩放 ±14%、黄金角偏航、±3° 倾斜),
tree_row 采样高度全部相同,不抖动就是同一棵树盖章 156 次。

移除 polyhaven 样式和 island_tree_01 资产(76MB)+ ingest_tree.py:
该样式 append 的 *_LOD1 并不是完整的树,枝干只有 0.41 单位高,叶片是
挂在原点下方的平面簇,本是给源文件几何节点散布用的碎片。

Cesium 侧修三处:

- make_export_material 把 Alpha 恒定写死为 1.0,叶片卡片整块导出,而
  SpeedTree 图集抠掉的区域是纯黑,在 Cesium 里就是黑色色块。
- Blender 4.2 起 glTF 导出不再读 blend_method(仍可写但已失效,写 CLIP
  读回来是 HASHED),改为从节点树推断 alpha 模式,alpha 直连 BSDF 会落到
  BLEND。新增 materials.link_alpha_clip() 构造导出器识别的
  1 - (alpha < cutoff) 结构,得到 alphaMode=MASK。
- 新增 alpha_dilated_image():把不透明像素颜色向抠图区域外扩 8 圈,
  避免 mipmap 把黑色平均进叶缘。叶缘相邻的纯黑像素 10.3% → 0.6%。

另修两个既有 bug:

- 材质槽在 mesh 上,181 棵树共享一个 datablock,第一棵替换后其余会把结果
  再包一层,产生 Cesium Cesium Cesium... 的材质名;烘焙图缓存按材质名索引,
  每轮再嵌一份同样的贴图。GLB 22.46MB → 20.76MB,materials 270 → 23。
- shrub_02 从 glTF 带进来一个 Math 节点接在 Alpha 上,但其 JPEG 贴图 alpha
  全是 1.0,只判断「连了 Alpha」会误判为抠图材质。

模型资产为第三方素材,已 gitignore,缺失时回落到 natural;
来源见 assets/models/SOURCES.md。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:30:16 +08:00
b35b094ed2 docs: changelog 更新 — P0-P3 refactor + island_tree_01
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-30 09:22:04 +08:00
24e02e2041 refactor: 抽 osmassets 包,要素注册表,材质单一定义源 (P0-P3)
generate_scene.py 从 1271 → 816 行 (-455)

P0: 纯函数搬家
- osmassets/osm.py: parse_osm / Projector / parse_height
- osmassets/geom.py: clip_polygon / point_in_polygon / distance_to_ring / sample_tree_row 等
- blender/tests/test_pure.py: 42 个 unittest (脱离 bpy 运行)

P1: 单一定义源
- osmassets/catalog.py: ROAD_LAYERS + MATERIALS (含 cesium 导出参数)
- 对接 osm2streets_scene_style.json 做图层一致性 warning
- 干掉 road_mats / layer_z / 材质参数三份副本

P2: 要素注册表
- osmassets/{water,grass,scrub}.py: 每个要素一个 assemble() 函数
- build() 中的 if/elif 链收缩为注册表调用
- 计数器集中到 counts 字典

P3: 材质契约化
- catalog.py 扩展 CESIUM_EXPORT 段 (tint/metallic/emission)
- 标记已发现的死条目 Office White Metal Facade (四表各一组)

校验:
- parity.js + scene_digest.py + glb-digest.js 三位一体
- control-1 vs p0/p1/p2a/p2b/p3-counts: 两区域全 PARITY OK
- 42 个纯 Python 测试全部通过

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-29 17:59:32 +08:00
59628cba82 feat: add reimport stage for hand-edited GeoPackages
QGIS 手工修正后的回导流程此前是 README 里的三段 shell:一个硬编码
area-id 和 ogr2ogr 绝对路径的 for 循环、一段内联 node heredoc、再加一次
npm run build。改为一个 reimport 阶段:

  npm run build -- --config config/areas/<area-id>.json \
    --stages reimport,blender,cesium

scripts/reimport-gpkg.js 先把全部图层导出到临时目录并逐个校验,全部通过
才写回 osm2streets_web_out/。ogr2ogr 对不存在的图层退出码非 0 但仍会留下
0 字节文件,原先逐图层 mv 会静默用空图层覆盖好数据。

intermediates 与 reimport 同时指定直接报错——前者用 OSM 重建 GeoPackage,
正好抹掉后者要读回的手工修改。reimport 不含在 all 中。

同时新增 scripts/lib/scene-layers.js 作为 9 个渲染图层的唯一定义源。此前
该表在合并场景、场景样式 JSON、生成的 QGIS 工程、README 手工流程中各有
一份副本,改一处漏其余会导致图层叠放顺序出错并流入 Blender/Cesium。

验证:同一 OSM 输入下,改动前后 intermediates 产物逐字节一致
(scene_style.json、.qgz 符号定义、9 个图层几何与属性);reimport 对
未修改图层无损回导。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 17:21:59 +08:00
694f18826a Add multi-vehicle cruise selection preview 2026-07-27 15:55:29 +08:00
633f1ee364 Restore lightweight cruise car and keep lane offset 2026-07-27 14:53:40 +08:00
d93212b685 Use clean ToyCar model and lane-offset cruise route 2026-07-27 14:31:56 +08:00
f1ddedf889 Add experimental Cesium vehicle cruise preview 2026-07-27 13:52:43 +08:00
633c39e5e1 Remove Nantaizi building render overrides 2026-07-27 13:41:02 +08:00
5919684888 Treat mislabeled Nantaizi buildings as offices 2026-07-27 13:28:55 +08:00
a5c3ad3cf3 Generate Cesium preview pages from area builds 2026-07-27 13:06:57 +08:00
61e4820a4c Refactor pipeline around area asset builds 2026-07-27 12:56:13 +08:00
cf69c99d20 通用化项目结构:Blender 脚本去硬编码、config 路径占位符、layerPrefix 配置
- blender/generate_nantaizi.py → blender/generate_scene.py(去硬编码路径,
  --geojson 改为可选,--office-overrides 替代硬编码 way ID)
- blender/export_cesium.py CLI 参数改为必传,修复隐藏物体导出崩溃
- blender/README.md 重写为中文通用文档
- config/default.json 路径改为占位符,template.json 新增 blender 配置块
- scripts/build-osm2streets-qgis.js 新增 layerPrefix 配置驱动 QGIS 图层名
- package.json name → osm-gis-pipeline
- README.md 重写并增加实际运行示例
2026-07-24 17:09:43 +08:00
dc22543e9a Initial osm2streets QGIS workflow 2026-07-21 17:03:27 +08:00