
简介面向GIS与三维Web可视化开发者这一实用工具负责将倾斜摄影测量生成的OSGB模型转换为Cesium可直接调用的3DTiles格式。转换过程中整合了数据解析、空间参考系转换、瓦片切分以及Draco压缩编码等关键环节有效解决大规模倾斜模型在网页端渲染卡顿与加载缓慢的问题。压缩包共含121个文件大小约9.22MB其中包含主程序执行文件、28个动态运行库、一批GDAL坐标系转换所需的配置表与空间参考定义文件以及示例模型和使用说明结构完整便于离线使用。已有2509人学习下载。借助内置的分块与压缩策略使用者可将海量OSGB数据自动输出为B3DM格式的三维瓦片直接嵌入场景中流畅展示同时附带的坐标系统文件支持自定义源坐标系调整适用于智慧城市、测绘工程和实景三维快速发布等场景。1. 为什么倾斜摄影模型上线会卡死问题出在格式而不是机器一提起 osgb 转 3dtiles 工具很多人第一反应是“格式换一下而已”真做起来才知道卡住你的往往不是命令而是坐标系。倾斜摄影拍出来的 OSGB 模型在本地看图软件里跑得流畅一旦交给 Cesium 这类 WebGL 框架要么白屏要么模型直接飘进海里——根因在 OSGB 为桌面渲染设计而 3DTiles 是为 Web 流式加载而生。osgb2cesiumApp V1.9 的作用就是把 OSGB 模型拆成 3DTiles 瓦片并把坐标系统一到 WGS84 体系让数据能直接进浏览器。这套资源适合两类人一类是 Web 端 GIS 开发者想把倾斜摄影数据快速搬上 Cesium 另一类是测绘交付工程师需要在网页里做成果汇报。开始阅读前你只需确认两件事手里 OSGB 文件的结构是哪种以及源坐标系到底是哪一个。2. OSGB 与 3DTiles 的底层差异换的不只是格式而是整套渲染逻辑2.1 OSGB 是桌面场景图3DTiles 是 Web 瓦片体系OSGBObject Scene Geometry Binary是 OpenSceneGraph 体系下的二进制场景图格式。一个 OSGB 文件不只是几何体它内部由节点树组成根节点记录包围盒和坐标系元数据子节点挂几何节点、纹理节点、属性节点以及多级 LOD。多个 OSGB 文件按 Data 目录组织起来每一级目录代表一个 LOD 层。这种结构在本地渲染引擎里效率很高因为 OSG 可以直接把节点树加载进内存预取相邻瓦片。但浏览器有它的限制。Cesium 虽然也是三维引擎跑的却是 WebGL 管线讲究一个 Tile 按需加载、一个 Tile 一个请求资源需要能被浏览器以二进制 Blob 方式接收并解析。3DTiles 的规范定义了一个 tileset.json 入口描述整棵瓦片树的包围盒、几何误差、屏幕空间误差和子节点索引真正的几何数据按 b3dm、i3dm、pnts、cmpt 等格式封装。整个体系是围绕“增量请求”设计的不是把一整棵场景图倒进内存。对比项OSGB3DTiles组织方式二进制的 OSG 场景节点树tileset.json 索引的瓦片树渲染目标桌面端 OpenGL 程序浏览器 WebGL 引擎加载方式整节点树预加载按视锥体范围分页请求常见载体.osgb 文件 Data 目录.b3dm / .i3dm tileset.json坐标基准可附带各类地方坐标系统通常以 WGS84 为基准组织这组差异决定了不能靠简单的“文件后缀替换”完成转换。能转的前提是先把第一种结构拆开、重组成第二种结构这也是 osgb2cesiumApp 这类工具最核心的工程量所在。市面上确实有实验性的 OSG 加载插件但性能不可同日而语没有分块调度、没有 LOD 层级映射大场景直接卡死某些在线预览工具靠后台全量转 glTF 再丢给浏览器文件体积翻倍纹理路径频繁出错。做生产数据交付不建议走那条路。2.2 为什么转换后的瓦片通常是 B3DM还带 Draco3DTiles 规范里有多种瓦片格式B3DMBatched 3D Model适合承载批量三角网格I3DM 用于实例化模型比如树木、路灯PNTS 是点云。倾斜摄影 OSGB 转 3DTiles 的主角是 B3DM——它本质上是 glTF 二进制格式.glb外面再包一层 FeatureTable 和 BatchTableCesium 对这种封装的原生解析能力最成熟。Draco 是 Google 开源的几何压缩库压缩顶点坐标、法线和纹理坐标压缩率通常在 70% 以上对几何数据。osgb2cesiumApp V1.9 的压缩选项就是调用这块能力。但需要注意Draco 压缩不是零成本浏览器下载完瓦片之后要在 CPU 侧解压再提交给 GPU。模型很小的时候压缩收益不明显反而增加解压耗时模型在几百 MB 以上时开启 Draco 对网络带宽的节省是值得的。我一般在小场景调试时关掉压缩交付大场景时再打开这样两头都占不到坑。说得更直白一点OSGB 文件里每个子块自带包围盒和子 LOD 引用转换工具需要把这些信息映射到 3DTiles 的 boundingVolume 和 geometricError 字段上。很多人转换完发现模型整体加载没问题但拉远后闪退或白块就是因为几何误差和屏幕空间误差的映射没配好。osgb2cesiumApp 的默认参数按常规倾斜数据给出如果你手里的模型单体特别碎就要主动调低 tile 分块大小如果是连片地形则相反调大分块减少请求数量。这部分参数化内容第四章会给到具体数值。2.3 坐标系是转换链路里最容易被低估的一环OSGB 数据通常由倾斜摄影空三处理而来它的坐标系跟着工程设置走可能是 WGS84 经纬度可能是 CGCS2000 的 3 度带投影也可能是西安80、北京54 的地方独立坐标。3DTiles 在没有做外部处理时按 WGS84 或局部笛卡尔坐标组织包围盒。转换工具一般把“读取源坐标系、转换到目标坐标系”作为一条独立链路处理这是最容易出问题、也最需要懂原理的部分。我配合这套资源常用的做法是先用工具自带数据建立一个坐标系字典让目标坐标和源 EPSG 代码能映射遇到自定义基准面时再把参数表顶上去。一批 CSV 参数文件里pcs.csv 和 gcs.csv 负责列出坐标系projop_wparm.csv 和 gt_datum.csv 负责投影变换和基准面偏移它们的关系会在下一章拆开讲。3. 坐标转换参数文件怎么用把模型从地方坐标摆回真实经纬度3.1 认识那批 CSV不是摆设是转换精度的底层保证先看资源包里那批 CSV很多人第一次拿到会以为是乱码实际上它们是 PROJ/GDAL 体系的坐标系参数表。倾斜摄影转换工具运行时源坐标系怎么识别、目标坐标系怎么投影、基准面偏移量从哪里取全部依赖这几张表。参数文件职责pcs.csv投影坐标系定义如 CGCS2000 3 度带、UTM 各分带gcs.csv地理坐标系定义如 WGS84、CGCS2000、西安80gdal_datum.csv基准面定义决定椭球体和参考框架datum_shift.csv基准面之间的七参数/三参数偏移量gt_datum.csv网格改正数据引用用于更高精度的基准变换projop_wparm.csv投影操作参数记录操作码、参数序列unit_of_measure.csv单位定义转换长度/角度单位用s57expectedinput.csv、s57attributes.csv、s57objectclasses.csvS-57 海图标准相关字段常规地形转换用不到实际使用中最常打交道的是前六张。pcs.csv 和 gcs.csv 负责告诉工具“模型现在在哪个坐标系里”projop_wparm.csv 负责把老的投影坐标变成地理坐标datum_shift.csv 和 gt_datum.csv 负责当源数据的基准面和目标基准面不一致时做偏移补偿。把这张表理解成“坐标字典”后面排查模型飘海里的问题就有方向了。这里有个容易忽略的细节坐标转换操作不是单纯的“查表—代入”而是查表拿到参数后执行一连串投影计算。projop_wparm.csv 里记录的就是这些操作参数比如从 CGCS2000 高斯投影转到 WGS84 经纬度中间要经过“投影反算 基准面替换 椭球变换”三个步骤。工具日志里如果出现某个操作码找不到多半就是这张表没读全或被误删。3.2 两种工作模式EPSG 直选与自定义参数绝大多数项目用 EPSG 代码就够了。以 CGCS2000 的 3 度带投影为例中央经线 114 度对应 37 带EPSG:4542117 度对应 38 带EPSG:4543但国内倾斜摄影最常碰到的是带号写进坐标里的“加带号坐标”比如 X 约 39 开头、Y 约 38 开头。这里要分清楚是带号坐标还是去带号坐标去带号坐标可以直接选对应的西部编号加带号坐标则需要结合 False_Easting 参数做带号扣除。常见做法的判断顺序打开 OSGB 同目录的 Metadata.xml找 SRS 节点看是否写了 EPSG 代码没有的话取模型范围任意一个点的经纬度和平面坐标做反算确定投影分带中央经线按 Lon3*N 计算3 度带 Nint(lon/30.5)注意保留整数后再代入把计算结果填进工具“源坐标系”的自定义模板里。如果源数据是用地方独立坐标系做的比如城市地方坐标没有 EPSG 编号就需要用七参数。工具里通常提供“自定义基准面”入口把这七个参数或三参数填进去工具把它引入到坐标转换链中。这时如果工具找不到对应偏移会退回到 gdal_datum.csv 里匹配基准面名称——这两张表的作用就在这里。坐标系统还牵扯一个很容易被忽略的维度高程基准。OSGB 模型里的 Z 值可能是 1985 国家高程基准、可能带高程异常改正也可能是椭球高程。3DTiles 的包围盒用的是椭球面高程相对 WGS84 椭球。两者差值在城市区域往往有几米到几十米。转换工具一般不做自动高程拟合需要你在源坐标系设置里指定高程基准类型有“椭球高/正常高”切换的地方一定要选对。测绘内业交付的多数 OSGB 会用正常高记录 Z转 Web 后最明显的症状是建筑底座不贴地面这在第五章一并排查。3.3 转换精度验证三个控制点足够揪出大部分坐标问题转换完不要直接丢进浏览器先做精度抽检。我的习惯是转换前在 OSGB 模型里选三个特征点最好是墙角或者地物轮廓拐角记录它们的模型坐标转换完成后用 Cesium 或任何能读 tileset 的客户端定位同一位置对比平面偏差。控制点原模型坐标转后 3DTiles 坐标偏差P1取 Metadata 或工具输出tileset.json transform 包围盒反算记录偏移P2同上同上记录偏移P3同上同上记录偏移这个逻辑不复杂但要真跑一遍。出现整体偏移几十米到几百米的情况优先核对 datum_shift.csv 是否成功加载常见原因是工具没读到该表的路径——参数文件放错目录比坐标系选错更隐蔽。出现旋转或比例不对则优先怀疑七参数填错顺序。参数文件的加载状态不是黑匣子工具一般会在转换日志里写“Loading datum_shift.csv...OK”日志里没有这一行就要回头检查路径。4. osgb2cesiumApp V1.9 实战从目录导入到 tileset.json 输出4.1 转换前的目录体检多数失败来自路径和 Data 结构先看目录。常规倾斜摄影建模软件导出的 OSGB 默认长这样Data/ Tile_000_000/L18/xxx.osgb Tile_000_000/L17/xxx.osgb ... Metadata.xml根目录放 Metadata.xmlData 目录按 Tile 分块、按 LOD 层级组织子目录。转换工具识别的是这个结构不是随便一个目录下堆几百个文件。转换前花两分钟做的检查项全路径不能含中文和空格尤其是 Windows 下很多转换库的路径解析对中文目录支持极差OSGB 根目录是否有 Metadata.xml没有元数据文件时坐标系识别会退化为手动指定硬盘剩余空间至少是 OSGB 总大小的 1.5 倍因为中间过程会输出临时瓦片文件如果数据是网络映射盘拷贝出来的检查文件是否完整.osgb 文件缺失会让转换中途失败。这几条在转换前做完能避开后面多半的坑。4.2 界面参数设置每个选项背后的取舍osgb2cesiumApp V1.9 是图形界面操作核心参数集中在“转换设置”面板拿其中几个高频项目说明含义。参数项含义推荐值源坐标系告诉工具 OSGB 当前所在坐标系直接决定后面所有坐标计算按 Metadata.xml 或 EPSG 填写目标坐标系输出的 3DTiles 组织坐标一般选 WGS84(4326) 或 Cartesian(4978)纹理压缩是否对 JPEG/PNG 纹理做再压缩调试阶段关闭交付阶段打开Draco 压缩是否对几何数据启用 Draco模型总量 500MB 建议开启LOD 深度保留 OSGB 原始几级 LOD默认即可碎单体调小分块大小单个 b3dm 瓦片承载的面片规模默认单体碎调小说明一点目标坐标系选 4326 时输出是经纬度包围盒选 4978 时是地心笛卡尔坐标。对 Cesium 加载来说两种都能正常工作但 4978 可以减少一次坐标变换误差积累。如果你后续还要做 GIS 分析用 4326 更通用。参数并不是越多越复杂就好这一版工具把多数规则用默认值封装了改动前先问自己一个问题我知不知道这个参数改动的代价不知道就不要动用默认转一版再看效果。还有一种常见操作给模型做自动 LOD。原始 OSGB 本身带 5 到 8 级 LOD但部分是模型重建过程的中间产物顶端 LOD 面片质量参差。转换工具提供“构建统一 LOD”选项会自动生成从最粗到最细的完整瓦片链。开启后输出时间变长但浏览器的缩放体验明显更平滑。如果你的数据用于保存归档而不是网页展示则没必要开保持原始 LOD 反而更接近源模型真实结构。4.3 输出检查tileset.json 里藏着的关键信息转换结束后输出目录大概长这样output/ tileset.json tiles/ 0/xxx.b3dm ...用文本编辑器打开 tileset.json开头部分可以看到{ asset: {version: 1.0}, geometricError: 486.2, root: { boundingVolume: { box: [ ... ] }, transform: [...] } }写一段 Python 代码做快速验证import json import math with open(tileset.json, encodingutf-8) as f: tileset json.load(f) transform tileset[root][transform] box tileset[root][boundingVolume][box] cx, cy, cz box[0], box[1], box[2] # transform 是 4x4 矩阵按列优先存储 x transform[0]*cx transform[4]*cy transform[8]*cz transform[12] y transform[1]*cx transform[5]*cy transform[9]*cz transform[13] z transform[2]*cx transform[6]*cy transform[10]*cz transform[14] lon math.degrees(math.atan2(y, x)) hyp math.hypot(x, y) lat math.degrees(math.atan2(z, hyp)) print(瓦片中心大致经纬度: %.8f, %.8f % (lon, lat))这段代码把 transform 和包围盒中心结合起来转成大致经纬度来对照原模型范围是一个快速验证手段。如果输出的经纬度和源数据所在区域差得离谱不用看渲染坐标链路已经有问题。参数说明box 数组前三位是中心点坐标transform 是 4×4 矩阵按列优先存储这里手动展开矩阵乘法是为了不依赖第三方库。需要说明的是3DTiles 的坐标系是右手系地心笛卡尔坐标这里转出的经纬度没有考虑椭球高到大地高的换算但精度足够定位到城市级别。如果有人用更精细的控制点验证应该回到 3.3 做完整比对而不是只依赖脚本输出。4.4 纹理内嵌与外链检查 b3dm 体积是最快手段转换后的 b3dm 默认会把纹理内嵌进 glb不再引用外部图片文件——这是好事但也意味着纹理丢失被掩盖在二进制里。如果转换时勾选了“外链纹理”输出目录会出现 textures 文件夹这种情况不要让文件随意移动否则纹理路径会断。验证方法看文件体积同面片规模下带了纹理的 b3dm 明显比纯几何大更专业一点的做法是打开 b3dm 头部正常结构应能看到“B3DM”和“glTF”两个魔数标识。如果你的输出目录里 b3dm 文件普遍只有几百 KB而源 OSGB 单块动辄几十 MB那基本可以断定纹理没有进去。这时候别急着查模型本身先回转换设置里检查纹理压缩和路径90% 的问题出在这两个环节。5. 转换避坑五个高频翻车点与排查记录5.1 模型整体飞到海里坐标没对上现象转换成功但 Cesium 里加载后模型出现在非洲西海岸或太平洋某处根本不落在原区域。原因源坐标系识别错误或默认成 WGS84OSGB 是用 CGCS2000 地方投影做的直接当经纬度用投影坐标被当成经纬度解释数值量级完全对不上。解决回到第四章的坐标验证脚本先打印出瓦片中心经纬度确认和源区域是否一致。不一致就重新指定源坐标系优先参考 Metadata.xml 里的 EPSG 代码没有元数据文件时按 3.2 的中央经线推导法把带号算出来。飞海的模型不用整包重转在工具里改完源坐标系再转一次几分钟的事。5.2 建筑底座悬空或陷进地面高程基准没选对现象平面位置对但楼整体“浮”在空中或者只有地基露出地面看起来像模型和地形没贴合。原因OSGB 用正常高记录 Z3DTiles 按椭球高解释高程两者在城市区域差值几米到几十米。这个差值不是固定常数会随位置变化所以不能靠统一平移一劳永逸。解决找到工具里“高程基准”或“垂直坐标系”设置把正常高选项开启或手动填入高程异常改正值。如果工具没有这个选项就在输出后用 Cesium 的模型矩阵做一次全局 Z 平移比较土但能救急。注意这个方案只适合小范围场景大范围地形数据还是要回到源坐标系里把高程基准选对。5.3 瓦片边缘出现空洞或破面LOD 间隙与几何误差失配现象拉近看某几块瓦片边缘“缺肉”拉远整体完整旋转视角时破面忽隐忽现。原因OSGB 的 LOD 层级与 3DTiles 的 error 映射不匹配子瓦片被提前裁剪或滞后加载。倾斜摄影数据里相邻瓦片的重叠区并不保证完全闭合模型重建时的接边误差会在 Web 端暴露得更明显。解决加大 tile 的“几何误差/LOD 间隙”参数或在转换设置里把构建统一 LOD 开启让瓦片链完整生成。破面集中在固定几块时优先怀疑原始 OSGB 本身有问题先到本地 OSG 查看器里确认同一位置是否破损别把锅全甩给转换工具。5.4 转换到一半内存爆掉或卡死现象转换进度条停在某个百分比不动任务管理器看内存几乎占满甚至直接闪退。原因数据集过大时采用了全量加载或分块大小设置过大单个块几何面数太多。有些 OSGB 文件在建模软件里就被切得极碎转换工具对单块解析时要临时建索引内存开销会叠得很高。解决按 Tile 目录分批转换再合并输出工具支持指定部分 Tile把分块大小调小一档关掉 Draco 再试排除解压过程的内存压力。如果源 OSGB 单文件超过 2GB先检查文件是否完整很多卡死源于损坏文件读了一半。5.5 纹理发黑或大面积白模纹理压缩与路径都可能是元凶现象几何体都在但表面材质变成黑色、灰色或直接是素模接近看贴图糊成一片。原因纹理压缩选项对某些 JPEG 格式支持不好压缩后纹理数据损坏或输出采用了外链纹理文件移动后路径断掉。另一个隐蔽原因是源 OSGB 里的贴图本身用了相对路径转换工具解析不了带../的引用。解决先关掉纹理压缩重转一版能恢复就说明是压缩器问题输出选择“内嵌纹理”而不是外链。检查 b3dm 文件体积正常带纹理的 b3dm 远比纯几何大如果只有几百 KB说明纹理根本没进去。源文件里贴图路径不规范的情况只能在建模软件里重新导出一次没有更好的后悔药。6. 验证与进阶把 tileset 挂上 Cesium 前先做这三步6.1 Cesium 加载 3DTiles 的三行核心代码加载本身不复杂但经常有人在图层添加顺序上踩坑。const viewer new Cesium.Viewer(cesiumContainer, { animation: false, timeline: false, baseLayerPicker: false, }); const tileset await Cesium.Cesium3DTileset.fromUrl(/output/tileset.json); viewer.scene.primitives.add(tileset); viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0, -0.5, 5000));说明第一段创建 Viewer 时把动画控件关掉倾斜摄影场景一般用不到fromUrl 返回 Promise必须 await 或 then 处理直接拿返回值会得到 undefined这是最常见的加载失败原因zoomTo 的第三个参数是初始视距按模型体量调整建筑单体 2000 到 5000 米整城区可以放到 8000 以上。6.2 用 Network 和 Console 快速定位加载问题打开浏览器 F12按 Network 过滤请求重点看几个点tileset.json 是否返回 200b3dm 瓦片是否成批加载Console 里有没有 WebGL 相关警告。排查顺序tileset.json 404输出路径不对检查服务器静态目录配置tileset.json 200 但 b3dm 全是 404输出目录结构不完整瓦片路径引用错重新转换b3dm 正常加载但画面空白检查 viewer 的 scene 模式地形开得太大可能把模型盖住Cesium 报“Draco decompression failed”压缩数据损坏关掉 Draco 重转。6.3 坐标差一点时的兜底技巧globalOffset 和 modelMatrix转换后如果还有少量位置偏差犯不着整条链路重新跑。Cesium 的 Cesium3DTileset 支持加载完成后做二次矩阵修正。tileset.modelMatrix Cesium.Matrix4.fromTranslation( new Cesium.Cartesian3(20.5, -13.2, 8.0) );这段代码的作用是把整棵瓦片树沿 X、Y、Z 方向平移指定米数。注意这里用的是局部笛卡尔增量不是经纬度增量20.5 代表沿本地坐标系 X 轴偏移 20.5 米。做这种修正前先在模型上选一个已知精确坐标的特征点用测量工具量出偏差值再填进矩阵。这个最土的办法反而最快。翻车现场回顾我刚上手时转换了一批城市级倾斜数据输出位置偏差约 10 米直接就想改源坐标重新转一遍结果两小时白等。后来学会用 modelMatrix 做快速校准十分钟量偏差、填矩阵两天后才腾出空弄清到底哪一步偏了。从那以后我每次转换前都强制走一遍“目录体检 → 坐标系反算 → tileset.json 中心验证”这三步再交给渲染环节位置错的转换基本在输出检查时就会被拦下。希望帮到你。本文还有配套的精品资源点击获取