Type: task Status: ready-for-human Labels: ready-for-human, wayfinder:task
继续重做被维护者两次否决的房屋模型。2026-09-24 明确反馈:地形穿透仍在;需按顶视卫星图逐栋建模,非特写近景也要有房屋样貌;允许调用本地 Blender / 3ds Max,同类模型复用。沿用本会话认领,不另开重复票。
当前实现是 地形遮挡修复 + Blender 房屋库 + 影像足印示范街区。不是完整县城交付,也没有获得维护者视觉验收。
旧版 90% 结论撤回。穿透问题已完成真实渲染回归;Blender资产库、城市覆盖底册、规则小区高置信度样片以及三套空间LOD树已完成。2026-09-29 按维护者三条反馈重做旧城生成:旧城不再沿道路造房(道路改为纯排除几何),改为只接受 OSM 建筑面与 z19 卫星屋顶分割足印;所有模型强制落在主场景区内(新增 primary-area.mjs 统一裁剪/包含契约 + 6 项测试);样式由 8 种已认可变体按来源建筑确定性分配,不再是整城统一橙色尖顶。当前经 verify-city-models.mjs 验收:主场景区外 0、交通道路上 0、居民地掩膜外 0。
2026-09-30 找到权威建筑来源,影像分割方案已被取代。 按维护者要求先取 GIS 建筑数据:本地此前只用过 OSM 的 169 个建筑面,但 D:\GIS\ArcGIS\yuanling\ 下有两份 1:500 测绘 CAD 图(沅陵20240110.dwg、沅陵20240510.dwg),其 JMD(居民地)图层含 60,771 个房屋面,另有 泵站厂房/BYQ/KZD/WSL/YSL 等专业图层。用本机 ArcGIS Desktop 10.8 的 arcpy 转成 GIS 后实测:主场景区内 60,744 个房屋轮廓,41,101 个规整四角矩形、19,643 个 L 形/天井等复杂外轮廓;1:1 z19 影像对照显示轮廓精确贴合屋顶(含街面进深、天井、组合体量),精度显著优于卫星分割(后者只能给旋转矩形)。面积中位 17.1 m²、p75 68.5 m²、p95 210.4 m²;37,151 个落在既有居民地掩膜内,其余 23,593 个为掩膜外村庄/散建。数据缺失:注记 54,663 条里只有 10 条带结构类型,层高需另行估计。
2026-09-30 BIM 管线已建立并跑通(维护者确认"先尝试制作")。 链路:prepare-cad-bim.mjs(足印→ENU、城区/乡村分级、按面积估层数)→ sample-terrain-offline.mjs(原始量化网格 DEM 采样)→ seat-cad-bim.mjs(平地/台基落地 + 轮廓有效性校验)→ assemble-cad-bim.py(Blender 导出空间 LOD 树)→ verify-lod-district.mjs。
分型策略:足印矩形度 ≥0.85 且尺寸落在 asset-fit.json 窗口内的用已认可精细资产(带窗、阳台、屋面),其余按真实测绘轮廓挤出体量棱柱——不再把 L 形/天井强行套成矩形,这正是此前"误差很大"的主因。层数按足印面积估(测绘注记不含可用层数)。
计划量与座落:足印 60,744 → 建模 54,455(精细资产 13,554 / 体量 40,901;城区 33,054 / 乡村 21,401;6,289 个 <4 m² 噪点跳过)→ DEM 座落后 48,425 栋(平地 46,934 / 台基 1,491;36 个自相交/塌缩轮廓、5,772 栋因高差超出合规台基而排除并记录原因)。
城区 BIM 已 100% 导出(本轮完成,6 批次全部通过验收):全量 48,425 栋单次导出体量过大(LOD0 逾 880MB 时被取消、无完整 manifest,未作为交付),改为 select-cad-bim-batch.mjs 按 tier/掩膜确定性切批(支持 --exclude 传入此前批次 manifest 去重;修掉 --key value 空格分隔参数解析 bug),每批 8,000 栋以内、--grid 16 --coarse-grid 4。六批明细:
| 批次 | 目录 | 导出 | 细分片/粗父 | LOD1 | LOD0 | 验收 |
|---|---|---|---|---|---|---|
| 1 试点 | lod-pilot |
2,942 | 68/9 | 24.0MB | 77.3MB | passed |
| 2 | lod-batch-urban8000 |
7,851 | 68/9 | 33.9MB | 132.3MB | passed |
| 3 | lod-batch-urban8000b |
7,712 | 70/9 | 31.7MB | 136.8MB | passed |
| 4 | lod-batch-urban8000c |
7,590 | 70/10 | 32.0MB | 121.3MB | passed |
| 5 | lod-batch-urban-final |
5,867 | 65/11 | 29.7MB | 114.5MB | passed |
| 6 尾批 | lod-batch-urban-tail |
506 | 23/3 | 0.9MB | 1.1MB | passed |
去重后城区覆盖 29,755 / 29,755 = 100%。体量棱柱按真实轮廓挤出,L 形/天井/街面进深保留;精细资产用于矩形度高的房屋。第 6 批 506 栋是各批资产窗口装不下的矩形,改按真实轮廓挤出(精度反而更高),不再硬套资产。
乡村 3 批(全部通过验收):lod-batch-rural1(7,820 栋,LOD1 35.4MB/LOD0 144.5MB)、lod-batch-rural2(7,658 栋,LOD1 35.1MB/LOD0 131.0MB)、lod-batch-rural3(2,788 栋,LOD1 20.3MB/LOD0 64.2MB),乡村房屋按真实轮廓挤出为主,辅以可承载的精细资产。
全场景 CAD BIM 汇总:城区 29,755 栋 100% 导出,乡村 18,266 栋分三批导出;加上 404 栋资产窗口兜底为真实轮廓体量后,去重覆盖 48,425 / 48,425 = 100%。共 10 个批次,每批通过 verify-lod-district.mjs;LOD0 合计约 923MB。
修掉的导出器缺陷(子代理首版遗留、由本人定位并修复):① 棱柱墙面四边形被加入两遍且第二遍反向绕序,每条墙边关联 4 个面、网格非流形,recalc_face_normals 无法定向,细长轮廓体积自检误判"内外翻转"——去掉重复面后恢复;② 体积自检与棱柱顶点原先用绝对 ENU 坐标(离原点约 2 km,mathutils 单精度),改为按 positionENU 构建局部坐标并加对象位移,自检数值稳定且导出节点位移与计划一致;③ 体量建筑原先额外生成"外接矩形埋地基础",与棱柱侧面共面闪烁、并在 L 形/细长轮廓上伸出建筑之外——体量棱柱已下探到 foundationBottom,故只对精细资产保留独立基础;④ 材质索引按三角面数而非面数填写,已改为"n 个墙面 + 两个顶底盖"。
剩余事项已按 2026-10-08 维护者决定收敛:层高保留按足印面积估算,不再作为阻塞;需解决全量 10 批次约 923MB 的运行态加载压力,并在真实驾驶舱验收贴地、遮挡、尺度及墙体/屋顶/门窗样式。
模型审查入口(辅助):preview.html#cad-bim 可快速检查 CAD BIM 批次几何,但不作为最终验收;最终外观与运行态验收在实际驾驶舱 http://127.0.0.1:8000/cockpit#/cockpit 完成。
createViewer() 未开启 globe.depthTestAgainstTerrain。在不透明球面/本地 DEM 下完全埋入的红色 GLB 仍显示 2916 像素;仅开启该项后为 0。已在 Viewer 创建和视图图层切换时保持开启;地下管线透视仍由显式 globe.translucency 控制。doubleSided 和法线自洽检查不能证明屋顶闭合。goHome(options) 的参数传入,实际没有改变预设距离;旧截图文件名中的“2400m/1200m”等不能作为视距证据。cesiumEngine.js 默认与图层切换保持 depthTestAgainstTerrain=true。tools/city-massing/verify-occlusion.mjs 在实际本地 DEM 场景验证默认地面0红像素、关闭深度2916、深度开启0、管线半透明2916、回地面0。负对照能复现原问题。regular-estate 有 5 处影像描绘屋顶与 OSM 巷道互相矛盾待人工判定。tools/city-massing/primary-area.mjs 作为唯一裁剪/包含契约(clipFeatureToBounds 对道路用 bboxClip、对建筑面用 intersect),city-atlas.mjs 与生成器都改用它;primary-area.test.mjs 6/6 通过;verify-city-models.mjs 对三套导出树实测主场景区外 0、交通道路上 0、居民地掩膜外 0。regular-estate 的 5 处影像描绘屋顶与 OSM residential 巷道重叠(15%–55%)作为 sourceConflicts 如实记录,未擅自删楼或改路。district/lod-preview(37单元,LOD1 7.04MB/790,296三角,LOD0 10.04MB/1,094,016三角)、city/regular-estate/lod-preview(15单元,LOD1 5.35MB/314,640三角,LOD0 8.12MB/449,424三角)、city/oldtown/lod-preview(4,601模块、319细分片、39粗父节点,LOD1 124.5MB/30,913,288三角,LOD0 662.6MB/43,942,492三角)。三棵树均通过 verify-lod-district.mjs 静态回验;oldtown 体量已大幅上升,运行时性能尚未复测,不能据此声称通过。map.tilesets[].lighting:true 归一化后,Cesium按tileset地理包围球配置稳定局部DirectionalLight与IBL;默认配置仍关闭模型,不改变无模型部署。tileFailed同步捕获内容阶段错误。.scratch/cockpit-shell-panel-layout/verify/artifacts/t35/runtime-lod/report.json(该文件描述的是改造前的旧树,已过期)。tools/city-massing/convert-dwg-to-gis.py:用 ArcGIS Desktop 10.8 的 arcpy 把测绘 DWG 转成文件地理数据库并盘点图层(CAD 无坐标系,按 CGCS2000 3 度带 GK CM 111E / EPSG:4546 定义;CADToGeodatabase 必须给参考比例,本图取 1:500)。tools/city-massing/export-cad-layers.py:按 CAD 图层名取出要素、定义坐标系、投影到 WGS84 输出 SHP;跳过 MultiPatch(三维重复几何)与 Annotation(文字框)。tools/city-massing/cad-shp-to-geojson.py:把 SHP 转成只含主场景区的 GeoJSON,并统计面积分布。city/cad-buildings.geojson(60,744 个房屋轮廓,SHA256 4266B3EC…)、city/cad-building-labels.geojson(54,663 条注记)、city/cad-extract-report.json。tools/city-massing/verify-cad-buildings.mjs → city/cad-buildings-z19-core.png(1:1 影像 + 轮廓描边,本人已读图确认贴合)、city/cad-buildings-overlay.png、city/cad-buildings-core.png。复现命令(路径含中文,故先复制到 ASCII 临时目录):
$tmp="$env:TEMP\city-dwg"; New-Item -ItemType Directory -Force -Path $tmp | Out-Null
Copy-Item 'D:\GIS\ArcGIS\yuanling\沅陵20240510.dwg' "$tmp\yuanling-20240510.dwg" -Force
& 'C:\Python27\ArcGIS10.8\python.exe' tools/city-massing/convert-dwg-to-gis.py "$tmp\yuanling-20240510.dwg" "$tmp\cad-20240510.gdb" 500
& 'C:\Python27\ArcGIS10.8\python.exe' tools/city-massing/export-cad-layers.py "$tmp\cad-20240510.gdb" "$tmp\shp" JMD
& 'C:\Python27\ArcGIS10.8\python.exe' tools/city-massing/cad-shp-to-geojson.py "$tmp\shp" tools/city-massing/city "110.328749941417,28.3917230659234,110.465779226663,28.4913038992907"
node tools/city-massing/verify-cad-buildings.mjs
注:city/cad-building-outlines.geojson(43MB,JMD 线要素)与多边形重复,为控制仓库体积已删除,需要时按上面命令重新导出。
tools/city-massing/house-library/house-library.blend、library.json、独立 GLB 和 preview.png:房屋资产库(8 个变体,已被维护者认为单栋质量基本够用)。tools/city-massing/asset-fit.json:足印模块 ↔ 资产变体的唯一缩放窗口契约,生成器与 Blender 导出器共用,防止两段各自放宽标准。tools/city-massing/primary-area.mjs + primary-area.test.mjs:主场景区裁剪与包含的单一契约(6 项测试)。tools/city-massing/segment-imagery-footprints.mjs + city/imagery-footprints.geojson + imagery-footprints-report.json:z19 卫星屋顶分割(6,000 足印,阈值与逐掩膜可靠性写在报告里)。tools/city-massing/verify-imagery-footprints.mjs + city/imagery-footprints-verify.png:1:1 卫星底图对照图,用于人工判读足印是否真的压在屋顶上。tools/city-massing/generate-oldtown-fill.mjs:来源足印 → 模块计划(含 sources 与逐条 excluded 原因)。tools/city-massing/seat-oldtown.mjs:平地/台基/台阶三档落地,terraced 记录台阶切分。tools/city-massing/verify-city-models.mjs + city/city-model-verification.json:主场景区/交通道路/掩膜/来源验收,并把无法自动判定的来源冲突单列。tools/city-massing/draw-model-coverage.mjs + city/city-model-coverage.png / city-model-coverage-core.png:生成足印叠在卫星底图上的覆盖对照。tools/city-massing/district/generated/coverage.json、geometry-verification.json:示范街区的来源覆盖与 GLB 坐标检验。本地工具:Blender 5.2.2 LTS 位于 D:/Steam/steamapps/common/Blender/blender.exe,批处理制作与导出成功。3ds Max 2024 批处理探针未进入脚本就绪状态,本次已停止,未声称用 Max 制作成功。
独立审查页:http://127.0.0.1:8092/preview.html(serve-review.mjs,只监听本机并复用8001的引擎/GIS)。不写入生产产物。旧 map.tilesets 已置空;新街区只通过审查入口展示,未擅自正式启用。
primary-area.test.mjs 6/6、oldtown-geometry.test.mjs 5/5、verify-lod-district.mjs 三棵树全通过、verify-city-models.mjs passed:true(主场景区外 0 / 交通道路上 0 / 掩膜外 0,5 处来源冲突如实列出)。city/imagery-footprints-verify.png(1:1 卫星底图 + 足印描边)与 city/city-model-coverage-core.png(生成足印压在城市核心卫星图上)已由本人读图判读:足印落在屋顶、街区内、河岸与山体保持空白。http://127.0.0.1:8092/preview.html 仍在,但它依赖 8001 的 dev 服务取 Cesium;本轮 8001 未在运行,因此没有重新取得运行态截图或帧率。项目规则禁止擅自启动 dev/调试服务,故运行态验收留待维护者开启服务后进行。房屋外观比旧版实质改善,样式也不再单一,但不能把有窗的详细单元等同逐栋真实建筑复原。楼层与立面是估计;DEM 自身精度、屋顶视差和历史影像错配依然存在。影像分割足印是最小外接矩形,贴邻无阴影分隔的两栋会并成一栋、暗屋顶会漏、L 形与天井不表达,位置不确定度约 0.3–0.6 m。掩膜 63/130 的影像足印已被判为不可信并排除,但这属于人工读图判读,不是自动质量指标。允许保留数值证据,不允许据此重新声称“全城达标”。
city/cad-bim/ 下全部 11 个 LOD 批次重新执行 verify-lod-district.mjs,全部 passed:true,栋数与正文逐批一致(pilot 2,942 / urban8000 7,851 / urban8000b 7,712 / urban8000c 7,590 / urban-final 5,867 / urban-tail 506 / dedup 5,138 / unfitted-fallback 404 / rural 7,820+7,658+2,788)。preview.html#cad-bim 的 10 个 tileset 清单与去重账目吻合(dedup 5,138 = urban8000 7,851 − 被其它批覆盖的 2,713)。serve-review.mjs 与 preview.html 在位,dev 服务 8001 未运行;按项目规则(不擅自启动 dev/调试服务)本轮未取得运行态截图与帧率。http://127.0.0.1:8092/preview.html#cad-bim 目测验收 → 运行态实测达标 + 层高来源落定后,本票即可 100% 关闭。/cockpit#/cockpit 驾驶舱中验收;模型必须与真实地形、影像、相机和照明一起工作。.env.local 新增 /gis/cad-bim 静态挂载,public/cockpit/config.json 已挂入 10 个 CAD BIM 根 tileset;未复制 923MB 资产。3D Tiles 加载失败(Unexpected token '<');进一步核对显示 /gis/cad-bim/lod-pilot/tileset.json 返回的是 Vite HTML fallback,而非 JSON。原因是 8000 进程尚未重启,未读取新增静态挂载配置,不代表 tileset 或模型内容失败。http://127.0.0.1:8000/cockpit#/cockpit,先核对 CAD BIM tileset 返回 application/json,再进行真实场景的遮挡、贴地、尺度、墙体/屋顶/门窗样式和运行态性能验收。/gis/cad-bim/lod-pilot/tileset.json 返回 200 application/json,内容生成器为 Blender CAD/BIM massing LOD。http://127.0.0.1:8000/cockpit#/cockpit,驾驶舱状态显示 3D Tiles 10 个;10 个批次的根节点请求均返回 200,DEM 和本地影像也正常返回 200,原先的 Unexpected token '<' 已消失。ready-for-human / 97%。下一步应先按城区/乡村或批次做分级加载、降低首屏同时加载的 10 批次压力,再在真实驾驶舱逐级验收墙体、屋顶、门窗、贴地和遮挡。Cesium3DTileset 现在启用 skipLevelOfDetail、baseScreenSpaceError=1024、skipScreenSpaceErrorFactor=16、skipLevels=1、maximumScreenSpaceError 默认 24,优先使用低面数 LOD1,近景才请求 LOD0。dynamicScreenSpaceError、foveatedScreenSpaceError、cullRequestsWhileMoving、loadSiblings=false;Cesium 自带每 tile 视锥剔除,不在摄像机视锥内的 tile 不进入渲染/请求选择。maximumDistance,本机 10 批统一设为 18 km;相机变化时按 tileset 包围球距离切换 instance.show,并在地图销毁时移除监听。mapService.js 中已有的重叠图层函数合并残片,该残片曾导致 Vite HMR 报 mapService.js:1 invalid JS syntax。mapService.js、cesiumEngine.js、cockpitConfig.js、mapLayers.js 均通过 node --check;本机配置 JSON 合法,10 批全部为 SSE=24 / maximumDistance=18000;8000 的配置与 tileset HTTP 端点均返回 200。维护者实测前述 LOD/剔除优化后仍卡顿,决定不在实际驾驶舱加载零散乡村房屋。本机运行配置已移除 lod-batch-rural1、lod-batch-rural2、lod-batch-rural3 三批,约减少 18,266 栋模型及其 LOD 请求;城区 lod-pilot、urban8000-dedup、urban8000b、urban8000c、urban-final、urban-tail 与 unfitted-fallback 保留。乡村资产文件不删除,后续如需恢复可重新加入配置。
下一步:重启/刷新 8000 后重新实测城区范围帧率与近景交互;若仍卡顿,再继续拆分城区批次或降低城区 LOD0 面数。
lod-pilot 保持 eager=true;其余 6 个城区/fallback 批次改为 eager=false,启动阶段只读取各自根 tileset.json 的包围盒元数据,不执行 Cesium3DTileset.fromUrl。loadDistance=6000m,相机进入批次根包围盒 6km 范围后才初始化对应 tileset;只有一个懒批次同时加载,避免城区批次并发抢占主线程和显存。maximumDistance 与加载距离的较大值后,从场景移除并销毁,返回该区域时可重新按需加载。http://127.0.0.1:8000/cockpit#/cockpit 后,驾驶舱状态显示 3D Tiles 1 个,控制台无新的地图解析/Cesium 初始化错误;说明首屏已从“同时挂 7 批”收敛为只初始化 pilot。维护者实测按需加载后帧率仍低。根因判断:远景/中景时精细批次的 LOD1 细分网格(单批约 350 万三角、全城逾千万)仍参与渲染,懒加载只省了初始化、没省渲染三角形数。本轮改为距离分层:
/gis/city/tileset.json(旧 town.glb 全城粗模,9.7MB,坐标已回验)标记 role:"far"、eager:true 常驻。相机离全部精细批次超过 6km 时显示它、隐藏全部精细批次——远看县城轮廓由它承担;进入 6km 后反向切换。两层互斥,不会出现双重楼体。eager:false,进入对应批次 6km 才初始化,离开 12km 销毁释放;单并发加载。cacheBytes=512MB / maximumCacheOverflowBytes=256MB,超限由 Cesium 淘汰 LOD 内容,防止多批次交替加载把内存推到崩溃。refreshOverlayReadiness() 对 globe.tilesLoaded 这个昂贵 getter 从每帧一次节流到约 6Hz。node --check;config JSON 合法;/gis/city/tileset.json 返回 200 application/json。下一步:维护者刷新 8000 复测远景帧率(预期显著回升)与 6km 内近景交互;若近景单批次仍卡,再做批次内减面(LOD1 面数压低或 draco 压缩重导出)。
维护者实测:靠近城区瞬间明显卡顿。根因:跨入显示阈值时,整个批次(约 5km 范围、68 个 LOD1 单元、约 350 万三角、数千 draw call)一帧内全部上屏,且 SSE=24 立即触发 LOD0 高模请求洪峰。本轮处理:
maximumScreenSpaceError 24→96、baseScreenSpaceError 1024→4096、skipLevels 1→2、skipScreenSpaceErrorFactor 16→32、动态 SSE 密度 0.00278→0.01 —— 只让视口中央占屏很大的单元才细化,进入批次时先以粗层渲染,近了再逐单元细化。RequestScheduler.maximumRequests=16 / perServer=8(默认 50),GLB 下载与解码分帧流入,消除整秒级渲染停顿。loadDistance 6km→10km,批次在相机抵达前加载完成,加载尖峰与显示切换解耦。SSE=96 / load=10000)。下一步:维护者刷新 8000 复测"靠近"瞬间;若近景静置仍低于可接受帧率,剩余手段是资产级减面(Blender 重导出:LOD1 面数减半或 draco 压缩),需要另起一次生成管线运行。
运行时优化用尽后维护者批准资产级减面。对 assemble-cad-bim.py 新增三项能力并全量重导出:
--decimate-lod1/--decimate-lod0 对资产库模板挂 Decimate 修改器(实例共享网格,一减全减),期望三角形数改从求值网格实测(库清单数字随之失效);--draco 启用 KHR_draco_mesh_compression(Blender 5.2 属性名为 export_draco_mesh_compression_enable);必须 export_apply=True 烘焙修改器,否则导出仍是全细节网格(试点首跑 60,900 vs 期望 21,748 的自检失败正是漏了它);纯体量批次(urban-tail、unfitted-fallback,无资产模板)合法跳过减面、仅 Draco。manifest 新增 reduction 字段记录参数。--decimate-lod1 0.35 --decimate-lod0 0.6 --draco --grid 16 --coarse-grid 4。verify-lod-district.mjs;/gis/cad-bim/*/tileset.json 与 GLB 经 8000 HTTP 返回 200(dev 静态挂载直读磁盘,无需重启);Cesium 原生内置 Draco 解码器,KHR 扩展无需额外配置。下一步:维护者硬刷新(Ctrl+F5,避免浏览器缓存旧 GLB)后复测远景/靠近/近景三段帧率与楼房观感。
维护者裁定:LOD 应按距离判定(不用相机高度);真正卡顿源是模型加载一启动、整个场景都卡。本轮改加载调度而非 LOD 数字:
requestRenderMode: true + maximumRenderTimeChange: 0.5——相机静止且无新瓦片时 Cesium 完全停渲染循环,GLB 解码与 GPU 上传独占空闲帧;瓦片到货、相机一动立即出帧。已核实自转(rAF 循环 + 相机修改)与雾动画(绑定相机运动)在按需模式下不受影响,0.5s 兜底帧保证雾 uniform 最迟半秒可见。positionWC 差值),代码中无任何相机高度参与 LOD 判定的路径;雾的高度收口是独立特效(票 38),不属 LOD。RequestScheduler 16/8 → 10/5,模型加载期间给地形与影像留网络与解码余量。node --check 通过。预期行为变化:靠近城区时移动本身流畅;相机停下约 0.6s 后批次才开始流入,流入期间画面依旧流畅(按需渲染让解码不占渲染帧)。代价:停下后模型延迟约 0.6s+ 加载时长才出现,粗模层在此期间维持轮廓显示(无空白)。
下一步:维护者硬刷新后复测——重点感受"移动是否全程流畅、停下后模型是否平滑流入";若停下后的流入仍有顿挫,下一步把 GLB 解码迁到 debounce 分帧上传(Cesium 无原生钩子,需要拆分 tile 加载回调)。