OSGB 倾斜摄影数据转换为 3D Tiles 技术文档
本文整理了 OSGB 倾斜摄影模型从数据检查、坐标处理、工具转换、3D Tiles 优化、服务发布到 CesiumJS 加载与验收排查的完整技术流程。
适用场景:将无人机/航空倾斜摄影、ContextCapture / Smart3D / 大疆智图等软件输出的 OSGB 模型,转换为 CesiumJS、三维数字孪生平台、WebGIS 三维场景可流式加载的 3D Tiles 数据。
推荐目标:生成tileset.json + b3dm/glb结构,或 3D Tiles 1.1 的tileset.json + glb结构,并通过 Nginx / Tomcat / Spring Boot 静态资源服务发布。
1. 文档目标#
本文档解决以下问题:
- OSGB 是什么,为什么不能直接在 CesiumJS 中加载。
- 3D Tiles 的基本结构是什么,OSGB 转换后应生成哪些文件。
- OSGB 转 3D Tiles 有哪些工具路线。
- 如何完成从数据检查、坐标确认、转换、优化、发布到 Cesium 加载的完整流程。
- 如何处理常见问题:位置偏移、模型倒置、高度不对、加载慢、白模、纹理丢失、跨域、gzip、LOD 闪烁等。
2. 基础概念#
2.1 OSGB 是什么#
OSGB 在倾斜摄影领域通常指 OpenSceneGraph Binary 格式,不是英国国家格网坐标系 Ordnance Survey National Grid 的 OSGB36。
OSGB 是 OpenSceneGraph 的二进制场景格式,常用于存储倾斜摄影模型。一个完整的倾斜摄影成果通常不是单个 .osgb 文件,而是由大量分块模型、纹理图片、LOD 层级和索引文件组成的目录结构。
常见结构如下:
textData/ ├── Tile_+000_+000/ │ ├── Tile_+000_+000.osgb │ ├── Tile_+000_+000_L00.osgb │ ├── Tile_+000_+000_L01.osgb │ └── texture/ │ ├── xxx.jpg │ └── xxx.png ├── Tile_+000_+001/ │ └── ... └── metadata.xml / meta.xml / config.xml
OSGB 的特点:
- 适合本地桌面三维软件加载。
- 数据量大,文件数量多。
- 纹理和模型通常采用相对路径关联。
- 常包含多级 LOD。
- 坐标可能是地方投影、高斯投影、CGCS2000、WGS84、ENU 局部坐标或无明确地理坐标。
- CesiumJS 不能直接把 OSGB 目录当作三维瓦片加载,需要转换为 3D Tiles。
2.2 3D Tiles 是什么#
3D Tiles 是面向大规模三维地理数据流式传输和渲染的开放标准,适合倾斜摄影、三维建筑、BIM/CAD、点云等数据类型。
一个典型 3D Tiles 数据集结构如下:
textoutput_3dtiles/ ├── tileset.json ├── 0/ │ ├── 0.b3dm │ ├── 1.b3dm │ └── ... ├── 1/ │ └── ... └── textures/
核心文件是 tileset.json,它描述:
- 根节点和子节点的空间层级关系。
- 每个瓦片的
boundingVolume。 - 每个瓦片的
geometricError。 - 每个瓦片的内容地址,如
.b3dm、.glb、.pnts。 - 根节点或子节点的坐标变换
transform。
3D Tiles 1.0 常见瓦片内容格式:
| 格式 | 用途 |
|---|---|
.b3dm |
批量三维模型,倾斜摄影和三维建筑常用 |
.i3dm |
实例化三维模型,如树木、风机、路灯 |
.pnts |
点云数据 |
.cmpt |
组合瓦片,可包含多个子瓦片内容 |
3D Tiles 1.1 更强调直接使用 glTF / GLB 内容,传统的 .b3dm、.i3dm、.pnts、.cmpt 在新规范中逐步被 glTF 内容和元数据机制替代。工程上仍大量使用 3D Tiles 1.0 的 .b3dm,兼容性最好。
2.3 OSGB 转 3D Tiles 的本质#
OSGB 转 3D Tiles 不是简单改后缀,而是要完成以下转换:
textOSGB 层级模型 ↓ 读取模型节点、LOD、纹理、坐标 ↓ 转换几何数据和纹理引用 ↓ 生成 glTF / GLB 或 b3dm ↓ 重建空间层级和包围体 ↓ 生成 tileset.json ↓ 优化、压缩、发布
转换过程主要涉及 5 类关键问题:
- 格式转换:OSGB 的几何和纹理转换为 glTF / GLB / b3dm。
- 空间层级转换:OSGB 的瓦片树转换为 3D Tiles 的 tile tree。
- 坐标转换:地方坐标或投影坐标转换为 Cesium 可识别的 ECEF / WGS84 空间位置。
- LOD 控制:设置合理的
geometricError,保证远近切换自然。 - Web 优化:压缩纹理、压缩几何、gzip、HTTP 缓存、切片大小控制。
3. 转换前准备#
3.1 数据准备清单#
转换前应确认以下内容:
| 检查项 | 要求 |
|---|---|
| OSGB 根目录 | 应包含完整瓦片目录,不要只复制部分 .osgb 文件 |
| 纹理文件 | 确认 .jpg、.png、.dds 等纹理路径完整 |
| 元数据文件 | 检查是否有 metadata.xml、meta.xml、metadata.json、Data 目录 |
| 坐标系统 | 明确是 WGS84、CGCS2000、高斯投影、UTM、本地坐标还是无坐标 |
| 单位 | 一般为米,若模型过大或过小,需要确认单位 |
| 高程基准 | 明确是否为椭球高、正常高、相对高程 |
| 数据范围 | 记录中心点经纬度、范围、高程 |
| 输出目标 | 明确要生成 3D Tiles 1.0 .b3dm 还是 3D Tiles 1.1 .glb |
3.2 推荐目录规范#
建议将原始数据、转换结果、发布目录分开管理:
textproject/ ├── 00_raw_osgb/ # 原始 OSGB 数据,只读保存 ├── 01_checked_osgb/ # 检查修正后的 OSGB ├── 02_3dtiles_output/ # 转换结果 ├── 03_optimized_3dtiles/ # 压缩优化后结果 ├── 04_publish/ # Web 发布目录 ├── logs/ # 转换日志 └── docs/ # 坐标说明、转换参数记录
不要直接在原始 OSGB 目录上执行覆盖式转换,避免损坏原始成果。
3.3 坐标系统确认#
OSGB 倾斜摄影数据最常见的问题是坐标不明确。转换前至少要拿到以下信息之一:
- 模型中心点经纬度。
- EPSG 坐标系编号。
- 投影坐标范围。
- 生产软件导出的 metadata 文件。
- 外业控制点成果。
- 与正射影像、DOM、DEM 或矢量边界可对齐的参考数据。
常见情况:
| 原始坐标类型 | 处理方式 |
|---|---|
| WGS84 经纬度 | 可直接用于 Cesium 定位 |
| CGCS2000 经纬度 | 与 WGS84 在多数工程展示中差异很小,但严谨项目应明确转换参数 |
| CGCS2000 / 西安80 / 北京54 高斯投影 | 需要投影转换为 WGS84 或 ECEF |
| UTM | 需要 EPSG 编号,如 EPSG:32650 |
| 地方独立坐标 | 需要七参数、四参数或控制点配准 |
| 无坐标模型 | 只能按手动经纬度、高程和旋转参数放置 |
Cesium 的全球场景通常使用 WGS84 椭球和 ECEF 坐标。3D Tiles 的 transform 可以把局部坐标系中的瓦片放置到地球上的正确位置。
4. 工具路线选择#
4.1 路线 A:商业/桌面工具转换,适合生产交付#
适用场景:
- 项目交付要求稳定。
- 数据量大。
- 需要图形界面检查。
- 不希望自己编译开源工具。
- 对坐标、压缩、发布有较高要求。
常见工具:
| 工具 | 说明 |
|---|---|
| Cesium ion | 可将多类三维数据转换和托管为 3D Tiles,但不一定适合内网私有化和 OSGB 本地批量处理 |
| Bentley ContextCapture / iTwin Capture Modeler | 倾斜摄影生产软件,部分流程可直接输出 3D Tiles |
| SuperMap iDesktop / iServer | 国内 GIS 项目中常用于倾斜摄影切片、S3M、3D Tiles、服务发布 |
| ArcGIS Pro | 可处理 I3S / SLPK 等三维场景图层;OSGB 支持能力与版本、扩展和工作流有关 |
| GISBox / CesiumLab 等工具 | 常用于 OSGB、3D Tiles、S3M 等格式转换与发布 |
| FME | 数据转换能力强,适合复杂格式 ETL,但授权成本较高 |
推荐结论:
- 政务内网、国产化交付、倾斜摄影批量处理:优先考虑 SuperMap、GISBox、CesiumLab 这类成熟桌面工具。
- 公网展示或 SaaS 可接受:可考虑 Cesium ion。
- 已有 ContextCapture 生产链:优先从生产软件侧直接导出 3D Tiles,减少二次转换损失。
4.2 路线 B:开源命令行工具转换,适合可控自动化#
适用场景:
- 希望在服务器或脚本中批量转换。
- 可接受编译、调参和排错。
- 有开发人员维护工具链。
- 需要纳入自动化处理流程。
常见开源工具:
| 工具 | 作用 |
|---|---|
fanvanzh/3dtiles |
支持 OSGB、Shapefile、FBX 转 3D Tiles,支持网格优化、Draco、KTX2 等能力 |
osgb23dtiles |
基于 fanvanzh/3dtiles 的 Python 包,可转换 OSGB 到 3D Tiles 或 GLB |
CesiumGS/3d-tiles-tools |
Cesium 官方工具,主要用于 3D Tiles 分析、gzip、合并、升级、b3dm/glb 互转和优化,不是通用 OSGB 读取器 |
gltf-pipeline |
glTF / GLB 优化、glTF 1.0 到 2.0 转换、Draco 压缩 |
gltf-transform |
glTF 2.0 资产检查、纹理压缩、几何压缩、优化 |
OpenSceneGraph osgconv |
可将单个 OSGB 转为 OBJ/DAE/OSG 等中间格式,但不负责生成完整 3D Tiles 层级 |
推荐结论:
- OSGB → 3D Tiles:优先使用专门支持 OSGB 的工具,如
fanvanzh/3dtiles、osgb23dtiles或成熟商业工具。 - 3D Tiles 转换后的检查和优化:使用
3d-tiles-tools、gltf-pipeline、gltf-transform。 - 不要把 osgconv 当作完整 OSGB 倾斜摄影转 3D Tiles 的主工具。它更适合单模型格式转换,不适合重建大规模瓦片层级。
5. 推荐技术流程#
完整流程如下:
text原始 OSGB 数据 ↓ 数据完整性检查 ↓ 坐标系统确认 ↓ 选择转换工具 ↓ OSGB 转 3D Tiles ↓ 检查 tileset.json ↓ 模型空间位置校正 ↓ 纹理/几何/瓦片优化 ↓ Web 服务发布 ↓ CesiumJS 加载 ↓ 效果检查与问题修正
6. 方案一:使用桌面工具转换#
不同工具界面不同,但核心参数基本一致。以下以通用流程描述。
6.1 新建转换任务#
- 打开转换工具。
- 选择数据类型:倾斜摄影 / OSGB。
- 指定 OSGB 根目录。
- 选择输出格式:3D Tiles。
- 指定输出目录。
注意:输入目录通常应选择包含 Data、metadata.xml 或瓦片根节点的上级目录,而不是某一个最底层 .osgb 文件。
6.2 设置坐标参数#
需要配置:
| 参数 | 说明 |
|---|---|
| 源坐标系 | 原始 OSGB 数据坐标系 |
| 目标坐标系 | 通常为 WGS84 / ECEF |
| 中心点 | 模型中心经纬度和高程 |
| 高程偏移 | 用于修正模型悬浮或下沉 |
| 旋转角度 | 用于修正模型方向不一致 |
| 单位 | 通常为米 |
| 原点 | 局部坐标模型需要设置地理原点 |
如果工具支持自动读取 metadata,可先自动识别;如果加载后位置明显偏移,再手动修正。
6.3 设置切片参数#
常见参数建议:
| 参数 | 建议值 | 说明 |
|---|---|---|
| 输出格式 | 3D Tiles 1.0 b3dm | 兼容性最好 |
| 根瓦片几何误差 | 500–2000 | 大范围模型取大值,小范围取小值 |
| 最大屏幕误差 | 16 | Cesium 默认常用值 |
| 单瓦片目标大小 | 1–10 MB | 过大会卡顿,过小会请求过多 |
| 纹理最大尺寸 | 1024 / 2048 | 根据清晰度和性能平衡 |
| 纹理格式 | jpg / webp / ktx2 | Web 端优先考虑压缩纹理 |
| 法线 | 可保留 | 有光照需求时保留 |
| Draco | 视工具支持开启 | 可减小几何体积,但会增加解码开销 |
| 合并小瓦片 | 建议开启 | 减少请求数量 |
| 空瓦片剔除 | 建议开启 | 减少无效数据 |
6.4 执行转换#
转换过程中应保存日志,记录:
- 工具名称与版本。
- 输入路径。
- 输出路径。
- 源坐标系。
- 目标坐标系。
- 中心点。
- 高程偏移。
- 几何误差参数。
- 纹理压缩参数。
- 是否启用 Draco / KTX2。
- 转换开始和结束时间。
- 错误日志。
6.5 转换结果检查#
转换完成后,输出目录至少应包含:
textoutput_3dtiles/ ├── tileset.json └── 若干 .b3dm / .glb / 子目录
检查项:
tileset.json是否存在。tileset.json中的asset.version是否合理。root.boundingVolume是否存在。root.geometricError是否大于子节点。content.uri路径是否能访问。.b3dm或.glb文件大小是否异常为 0。- 纹理是否随结果一起输出。
- 目录路径大小写是否一致。
7. 方案二:使用开源工具 fanvanzh/3dtiles 转换#
说明:开源工具版本变化较快,具体命令参数以项目 README 为准。本文给出工程流程和常用命令示例,实际项目应先用小范围样例测试,再批量处理。
7.1 环境准备#
建议环境:
text操作系统:Windows 10/11、Ubuntu 20.04+、macOS CPU:8 核以上 内存:32 GB 起步,大数据建议 64 GB+ 磁盘:SSD,剩余空间至少为原始数据 2–3 倍 Node.js:用于 3d-tiles-tools / gltf-pipeline Python:用于辅助脚本
安装 Node.js 后:
bashnode -v npm -v
安装官方 3D Tiles 工具:
bashnpm install -g 3d-tiles-tools npm install -g gltf-pipeline
7.2 获取 OSGB 转换工具#
如果使用 fanvanzh/3dtiles,通常需要下载预编译版本或源码编译。
示例目录:
texttools/ └── 3dtiles/ ├── 3dtiles.exe └── README.md
检查工具是否可执行:
bash3dtiles --help
如果使用 Python 包 osgb23dtiles:
bashpip install osgb23dtiles
7.3 执行 OSGB 转 3D Tiles#
通用命令示意:
bash3dtiles \ -f osgb \ -i /data/project/00_raw_osgb \ -o /data/project/02_3dtiles_output
不同版本参数可能不同,也可能使用类似:
bash3dtiles osgb \ --input /data/project/00_raw_osgb \ --output /data/project/02_3dtiles_output
使用 Python 包示例:
pythonfrom osgb23dtiles import osgb_to_b3dm_3dtiles osgb_to_b3dm_3dtiles( "D:/project/00_raw_osgb", "D:/project/02_3dtiles_output" )
转换后检查:
bashls /data/project/02_3dtiles_output
应看到:
texttileset.json *.b3dm / 子目录
7.4 坐标参数处理#
如果原始 OSGB 是局部坐标,转换工具可能只能生成局部 tileset,加载到 Cesium 后会出现在地心、海面附近或完全看不到。这时需要设置 tileset.json 的根节点 transform。
Cesium 常用方式是根据经纬度、高度生成 East-North-Up 到 Fixed Frame 的矩阵:
javascriptconst position = Cesium.Cartesian3.fromDegrees(116.391, 39.907, 50); const transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
如果转换工具不支持写入 transform,可在前端加载后动态设置:
javascriptconst tileset = await Cesium.Cesium3DTileset.fromUrl('/data/osgb_3dtiles/tileset.json'); const position = Cesium.Cartesian3.fromDegrees(116.391, 39.907, 50); const matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position); tileset.modelMatrix = matrix; viewer.scene.primitives.add(tileset); viewer.zoomTo(tileset);
更推荐在转换阶段或后处理阶段写入 tileset.json,这样不同客户端加载结果一致。
8. 3D Tiles 后处理与优化#
8.1 使用 3d-tiles-tools 检查#
安装:
bashnpm install -g 3d-tiles-tools
分析单个 b3dm:
bashnpx 3d-tiles-tools analyze \ -i ./output_3dtiles/0/0.b3dm \ -o ./analyze/0_0
分析结果可用于检查:
- b3dm 头信息。
- glb 是否有效。
- feature table / batch table。
- 是否存在 glTF 1.0。
- 是否存在 Draco 扩展。
- 是否存在贴图路径异常。
8.2 gzip 压缩#
对整个 tileset 进行 gzip:
bashnpx 3d-tiles-tools gzip \ -i ./02_3dtiles_output \ -o ./03_optimized_3dtiles
注意:
- 如果
.b3dm文件已经 gzip 压缩,Web 服务器必须返回Content-Encoding: gzip。 - 如果服务端没有返回该头,Cesium 会按未压缩二进制解析,导致加载失败。
- 如果文件未压缩但服务端错误返回
Content-Encoding: gzip,也会加载失败。
8.3 b3dm 几何优化和 Draco 压缩#
如果数据是 .b3dm,可尝试:
bashnpx 3d-tiles-tools optimizeB3dm \ -i ./input.b3dm \ -o ./output.b3dm \ --options --draco.compressMeshes --draco.compressionLevel=7
注意:
- Draco 可显著减小几何体积,但首次加载会有解码开销。
- 对纹理占比很高的倾斜摄影,Draco 对整体体积的降低可能有限。
- 不建议不经测试就全量最高压缩,可能导致解码变慢或兼容性问题。
- 建议抽样测试 1–2 个区域,比较压缩前后体积、首屏时间、帧率和清晰度。
8.4 glTF / GLB 优化#
如果输出为 .glb 或可从 .b3dm 提取 GLB,可使用 gltf-pipeline:
bashgltf-pipeline -i model.gltf -o model.glb
Draco 压缩:
bashgltf-pipeline -i model.gltf -o model_draco.gltf -d
对于现代 Web 三维项目,也可考虑 gltf-transform 做纹理压缩、meshopt、去重等优化。倾斜摄影项目中更应关注纹理大小、瓦片粒度和请求数量,而不是只压缩几何。
8.5 geometricError 调整#
geometricError 决定 LOD 切换时机。常见问题:
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 远处过早加载高清瓦片 | geometricError 偏小 | 增大父节点 geometricError |
| 近处仍模糊 | geometricError 偏大或子节点缺失 | 减小子节点 geometricError,检查 LOD |
| LOD 跳变明显 | 层级误差不连续 | 保证父子误差递减平滑 |
| 请求数过多 | 瓦片过碎或误差过小 | 合并小瓦片,提高误差 |
9. Web 服务发布#
9.1 Nginx 发布目录#
示例目录:
textD:/web/data/osgb_3dtiles/ ├── tileset.json ├── 0/ ├── 1/ └── ...
Nginx 配置示例:
nginxserver { listen 8090; server_name localhost; location /data/osgb_3dtiles/ { alias D:/web/data/osgb_3dtiles/; add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods "GET, OPTIONS" always; add_header Access-Control-Allow-Headers "Origin, Range, Accept, Content-Type, Authorization" always; types { application/json json; application/octet-stream b3dm; application/octet-stream i3dm; application/octet-stream pnts; application/octet-stream cmpt; model/gltf-binary glb; model/gltf+json gltf; image/jpeg jpg jpeg; image/png png; image/ktx2 ktx2; } expires 30d; add_header Cache-Control "public, max-age=2592000" always; if ($request_method = OPTIONS) { return 204; } } }
访问测试:
texthttp://localhost:8090/data/osgb_3dtiles/tileset.json
9.2 gzip 数据的 Nginx 配置#
如果 .b3dm、.i3dm、.pnts、.cmpt 文件本身已经 gzip 压缩,需要加响应头:
nginxlocation ~* \.(b3dm|i3dm|pnts|cmpt)$ { root D:/web; add_header Access-Control-Allow-Origin * always; add_header Content-Encoding gzip always; add_header Cache-Control "public, max-age=2592000" always; default_type application/octet-stream; }
但要注意:
- 只有文件实际是 gzip 压缩时才添加
Content-Encoding: gzip。 - 如果只是普通未压缩 b3dm,不要添加该头。
- 建议不要混合压缩和未压缩文件放在同一目录,除非有明确规则区分。
更稳妥的做法:
text03_optimized_3dtiles_gzip/ # 所有 tile 内容均 gzip 03_optimized_3dtiles_raw/ # 所有 tile 内容均不 gzip
9.3 Tomcat / Spring Boot 发布#
Spring Boot 静态发布目录示例:
textsrc/main/resources/static/3dtiles/osgb/ └── tileset.json
或外部目录映射:
yamlspring: web: resources: static-locations: - file:D:/web/data/
然后访问:
texthttp://localhost:8080/3dtiles/osgb/tileset.json
对于大规模 3D Tiles,不建议把数据打进 Jar 包,建议放外部静态目录,由 Nginx 或对象存储直接发布。
10. CesiumJS 加载示例#
10.1 基础加载#
新版 CesiumJS 推荐使用 Cesium3DTileset.fromUrl:
javascriptconst viewer = new Cesium.Viewer('cesiumContainer', { terrain: Cesium.Terrain.fromWorldTerrain() }); const tileset = await Cesium.Cesium3DTileset.fromUrl( 'http://localhost:8090/data/osgb_3dtiles/tileset.json' ); viewer.scene.primitives.add(tileset); await viewer.zoomTo(tileset);
10.2 设置最大屏幕误差#
javascriptconst tileset = await Cesium.Cesium3DTileset.fromUrl(url, { maximumScreenSpaceError: 16, maximumMemoryUsage: 1024 });
说明:
maximumScreenSpaceError越小,加载越精细,请求越多。maximumScreenSpaceError越大,加载越粗略,性能越好。- 倾斜摄影通常可从 16 开始测试,必要时调到 8 或 24。
10.3 模型高度调整#
如果模型整体悬浮或下沉,可通过 modelMatrix 做高度偏移:
javascriptfunction update3dtilesMaxtrix(tileset, heightOffset) { const boundingSphere = tileset.boundingSphere; const cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center); const surface = Cesium.Cartesian3.fromRadians( cartographic.longitude, cartographic.latitude, 0.0 ); const offset = Cesium.Cartesian3.fromRadians( cartographic.longitude, cartographic.latitude, heightOffset ); const translation = Cesium.Cartesian3.subtract( offset, surface, new Cesium.Cartesian3() ); tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation); } const tileset = await Cesium.Cesium3DTileset.fromUrl(url); viewer.scene.primitives.add(tileset); update3dtilesMaxtrix(tileset, 20);
10.4 模型定位到指定经纬度#
对于无地理坐标的局部模型:
javascriptconst tileset = await Cesium.Cesium3DTileset.fromUrl(url); const longitude = 116.391; const latitude = 39.907; const height = 50; const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height); tileset.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position); viewer.scene.primitives.add(tileset); viewer.zoomTo(tileset);
如果方向不对,需要叠加旋转矩阵。
10.5 调试开关#
javascripttileset.debugShowBoundingVolume = true; tileset.debugShowGeometricError = true; tileset.debugShowRenderingStatistics = true;
调试完成后关闭,否则影响性能和展示效果。
11. 质量检查方法#
11.1 文件级检查#
检查输出目录:
bashfind ./output_3dtiles -name "tileset.json" find ./output_3dtiles -name "*.b3dm" | head find ./output_3dtiles -name "*.glb" | head
检查空文件:
bashfind ./output_3dtiles -type f -size 0
检查大文件:
bashfind ./output_3dtiles -type f -size +100M
如果单瓦片超过 100 MB,应考虑重新切片或压缩,否则 Web 端加载体验很差。
11.2 HTTP 检查#
检查 tileset.json:
bashcurl -I http://localhost:8090/data/osgb_3dtiles/tileset.json
检查 b3dm:
bashcurl -I http://localhost:8090/data/osgb_3dtiles/0/0.b3dm
重点看:
textHTTP/1.1 200 OK Access-Control-Allow-Origin: * Content-Type: application/octet-stream Content-Encoding: gzip # 仅压缩文件需要
11.3 Cesium 端检查#
在浏览器开发者工具中检查:
tileset.json是否 200。.b3dm/.glb是否 200。- 是否有 CORS 错误。
- 是否有
Unexpected token、Invalid typed array length等二进制解析错误。 - 是否有纹理 404。
- 网络请求是否过多。
- 单个请求是否过大。
- GPU 内存是否持续升高。
12. 常见问题与处理#
12.1 加载后看不到模型#
可能原因:
tileset.json路径错误。- 跨域失败。
- 模型位置在地球另一侧。
- 模型高度异常。
boundingVolume错误。- 瓦片内容文件 404。
- gzip 头错误。
处理:
javascriptviewer.zoomTo(tileset); tileset.debugShowBoundingVolume = true;
同时检查浏览器 Network 面板和 Console 面板。
12.2 模型出现在海上或偏移很远#
原因:
- 原始 OSGB 是地方坐标或投影坐标。
- 转换时未设置 EPSG。
- 经纬度顺序写反。
- 高斯投影带号错误。
- CGCS2000 / WGS84 / 地方坐标没有正确转换。
处理:
- 确认原始坐标 EPSG。
- 确认模型中心点。
- 使用已知控制点校正。
- 在转换工具中重新设置源坐标系。
- 必要时通过
modelMatrix做平移、旋转、高程修正。
12.3 模型整体悬浮或下沉#
原因:
- 高程基准不一致。
- 原始数据为正常高,Cesium 以椭球高显示。
- 地形服务与模型高程基准不同。
- 转换时高度偏移错误。
处理:
- 设置高度偏移。
- 与地形贴合时,明确 DEM 高程基准。
- 对展示型项目,可用整体偏移解决。
- 对测绘精度项目,应进行高程基准转换。
12.4 模型方向旋转不对#
原因:
- OSGB 局部坐标轴与 Cesium ENU 坐标轴不一致。
- 转换工具未正确处理 Up Axis。
- 模型原点和方向缺少元数据。
处理:
- 在转换工具中设置方向。
- 前端通过矩阵叠加 Heading/Pitch/Roll。
- 检查是 X/Y 轴互换,还是 Z 轴方向问题。
示例:
javascriptconst position = Cesium.Cartesian3.fromDegrees(116.391, 39.907, 50); const hpr = new Cesium.HeadingPitchRoll( Cesium.Math.toRadians(90), 0, 0 ); const matrix = Cesium.Transforms.headingPitchRollToFixedFrame(position, hpr); tileset.modelMatrix = matrix;
12.5 模型白模或纹理丢失#
原因:
- 纹理没有复制到输出目录。
- 纹理路径大小写不一致。
- 纹理格式浏览器不支持。
- 纹理路径中有中文、空格或特殊字符。
- 转换工具未正确处理相对路径。
处理:
- 避免中文路径和特殊字符。
- 统一路径大小写。
- 将
.dds等纹理转换为.jpg、.png或.ktx2。 - 重新导出时选择“复制纹理”或“嵌入纹理”。
12.6 加载很慢#
原因:
- 单瓦片太大。
- 瓦片太碎,请求过多。
- 纹理过大。
- 未开启 HTTP 缓存。
- 未使用 gzip / Draco / 纹理压缩。
maximumScreenSpaceError设置过低。- 服务端带宽不足。
处理:
- 控制单瓦片 1–10 MB。
- 合并过小瓦片。
- 纹理最大尺寸控制在 1024 或 2048。
- 开启 HTTP 缓存。
- 测试 gzip / Draco / KTX2。
- Cesium 中适当增大
maximumScreenSpaceError。 - 使用 Nginx 直接发布静态数据。
12.7 LOD 闪烁或跳变明显#
原因:
- geometricError 不合理。
- LOD 层级缺失。
- 父子瓦片包围体不连续。
- 转换工具生成的瓦片树不稳定。
- 摄像机移动时加载延迟明显。
处理:
- 调整
geometricError。 - 增大缓存。
- 合理设置 Cesium 的
maximumScreenSpaceError。 - 优化瓦片大小。
- 减少瓦片数量和服务延迟。
12.8 浏览器报二进制解析错误#
常见报错:
textInvalid typed array length Invalid magic Unexpected token Failed to load tile
原因:
- gzip 头错误。
- b3dm 文件损坏。
- Content-Type 不合理一般不是致命问题,但 Content-Encoding 错误会致命。
- 服务器返回了 HTML 错误页,而不是 b3dm。
- 文件路径区分大小写导致 404。
处理:
bashcurl -I http://localhost:8090/data/osgb_3dtiles/0/0.b3dm
确认状态码是 200,不是 404/500,也不是登录页 HTML。
13. 生产环境建议#
13.1 数据规模建议#
| 项目规模 | 建议 |
|---|---|
| < 1 GB | 单机桌面工具即可 |
| 1–20 GB | 桌面工具或服务器命令行均可 |
| 20–100 GB | 建议服务器批处理,SSD,64 GB 内存 |
| > 100 GB | 建议分区转换、分区发布、按需加载 |
| > 500 GB | 建议对象存储/CDN/瓦片服务化,避免单目录超大文件数 |
13.2 输出切片建议#
- 不要让单个
.b3dm过大。 - 不要让瓦片过碎。
- 尽量使用稳定的层级结构。
- 大范围数据按行政区、工程区或网格分块发布。
- 多个 tileset 可通过业务图层控制加载,不一定要合成一个巨型 tileset。
- 对展示型首页场景,可单独生成轻量版模型。
- 对精细浏览场景,保留高清版模型并按需加载。
13.3 发布建议#
优先推荐:
textNginx 静态资源发布 + CesiumJS 前端加载 + 业务系统记录 tileset.json 地址和模型元数据
不建议:
- 把几十 GB 的 3D Tiles 放进后端 Jar 包。
- 通过 Java Controller 流式转发每个 b3dm。
- 每次加载都动态计算瓦片内容。
- 把 OSGB 原始数据直接放到 Web 前端尝试加载。
14. 与 Vue / Vite / Cesium 项目集成#
14.1 封装加载函数#
javascriptconst tileset = await Cesium.Cesium3DTileset.fromUrl(url, { maximumScreenSpaceError: options.maximumScreenSpaceError ?? 16, maximumMemoryUsage: options.maximumMemoryUsage ?? 1024 }); if (options.modelMatrix) { tileset.modelMatrix = options.modelMatrix; } viewer.scene.primitives.add(tileset); if (options.flyTo !== false) { await viewer.zoomTo(tileset); } return tileset; }
14.2 图层管理#
建议业务系统维护三维模型图层表:
| 字段 | 说明 |
|---|---|
| id | 模型 ID |
| name | 模型名称 |
| tileset_url | tileset.json 地址 |
| type | 倾斜摄影 / 建筑 / BIM / 点云 |
| lon | 中心经度 |
| lat | 中心纬度 |
| height_offset | 高度偏移 |
| heading | 旋转角 |
| visible | 是否默认显示 |
| max_sse | 最大屏幕误差 |
| remark | 备注 |
前端根据表配置动态加载模型,避免把地址和参数写死在代码里。
15. 自动化批处理示例#
15.1 Windows 批处理示例#
bat@echo off set INPUT=D:\project\00_raw_osgb set OUTPUT=D:\project\02_3dtiles_output set OPT=D:\project\03_optimized_3dtiles echo Start OSGB to 3D Tiles... 3dtiles -f osgb -i %INPUT% -o %OUTPUT% echo Gzip tileset... npx 3d-tiles-tools gzip -i %OUTPUT% -o %OPT% echo Done. pause
15.2 Linux / macOS 脚本示例#
bash#!/usr/bin/env bash set -e INPUT="/data/project/00_raw_osgb" OUTPUT="/data/project/02_3dtiles_output" OPT="/data/project/03_optimized_3dtiles" echo "Start OSGB to 3D Tiles..." 3dtiles -f osgb -i "$INPUT" -o "$OUTPUT" echo "Gzip tileset..." npx 3d-tiles-tools gzip -i "$OUTPUT" -o "$OPT" echo "Done."
15.3 转换记录文件#
建议每次转换生成 convert_record.md:
markdown# OSGB 转 3D Tiles 转换记录 - 项目名称: - 原始数据路径: - 原始数据大小: - 原始坐标系: - 中心点: - 转换工具: - 工具版本: - 输出格式: - 输出路径: - 是否 gzip: - 是否 Draco: - 纹理最大尺寸: - geometricError: - 转换时间: - 操作人: - 问题记录:
16. 验收标准#
16.1 数据验收#
| 项目 | 标准 |
|---|---|
| 文件完整性 | tileset.json 和瓦片文件完整,无 0 字节文件 |
| 坐标正确性 | 与底图、影像、矢量边界基本重合 |
| 高程正确性 | 无明显悬浮或下沉 |
| 纹理完整性 | 无大面积白模、黑块、纹理丢失 |
| 层级正确性 | 远近 LOD 切换正常 |
| 加载性能 | 首屏可接受,浏览不卡死 |
| 服务访问 | HTTP 200,无跨域错误 |
| 浏览器兼容 | Chrome / Edge 正常加载 |
16.2 性能验收#
建议测试指标:
| 指标 | 建议目标 |
|---|---|
| 首次显示时间 | 小范围 < 5 秒,大范围按项目要求 |
| 单瓦片大小 | 常规 1–10 MB |
| 最大单文件 | 尽量 < 50 MB |
| 请求失败率 | 0 |
| 帧率 | 普通办公电脑 > 25 FPS,展示机 > 30 FPS |
| 显存占用 | 不持续无限增长 |
| LOD 切换 | 无明显大面积闪烁 |
17. 推荐实施方案#
对于一般政务内网三维平台,推荐以下实施路线:
17.1 稳定交付路线#
textOSGB 原始数据 ↓ 桌面工具转换为 3D Tiles 1.0 b3dm ↓ 抽样检查坐标和纹理 ↓ Nginx 静态发布 ↓ CesiumJS 加载 ↓ 按图层表管理模型
优点:
- 稳定。
- 可控。
- 适合项目交付。
- 便于运维和问题排查。
17.2 自动化处理路线#
textOSGB 原始数据 ↓ 命令行工具批量转换 ↓ 3d-tiles-tools 分析和 gzip ↓ 自动生成转换记录 ↓ 发布到 Nginx 静态目录 ↓ 前端动态注册图层
优点:
- 可批处理。
- 可纳入数据生产流水线。
- 适合多旗县、多工程区、多期模型数据。
18. 最终目录示例#
text/opt/3d-data/ ├── xilingol/ │ ├── abaga/ │ │ ├── tileset.json │ │ └── ... │ ├── xwq/ │ │ ├── tileset.json │ │ └── ... │ └── dlx/ │ ├── tileset.json │ └── ... └── nginx.conf
前端图层配置:
json[ { "id": "abaga-osgb", "name": "阿巴嘎旗倾斜摄影", "url": "http://server:8090/3d-data/xilingol/abaga/tileset.json", "type": "oblique_3dtiles", "maximumScreenSpaceError": 16, "heightOffset": 0, "visible": false } ]
19. 关键注意事项#
- OSGB 不能直接作为 CesiumJS 三维瓦片加载,必须转换为 3D Tiles。
tileset.json是 3D Tiles 的入口文件。- 坐标系统是 OSGB 转换中最容易出错的环节。
- 不要把英国 OSGB36 坐标系和 OpenSceneGraph Binary 的 OSGB 文件格式混淆。
- gzip 文件必须和
Content-Encoding: gzip响应头匹配。 - 纹理缺失多数是路径、格式、大小写或转换工具配置问题。
- 倾斜摄影性能优化优先关注瓦片粒度、纹理大小、请求数量和缓存。
- Cesium 新版加载 3D Tiles 推荐使用
Cesium.Cesium3DTileset.fromUrl()。 - 大数据不要打包进后端 Jar,应使用 Nginx、对象存储或专门三维服务发布。
- 每次转换必须记录参数,方便复现和排错。
20. 参考资料#
OGC 3D Tiles Standard:
https://www.ogc.org/standards/3dtiles/OGC 3D Tiles Specification 1.1:
https://docs.ogc.org/cs/22-025r4/22-025r4.htmlCesium 3D Tiles Specification GitHub:
https://github.com/CesiumGS/3d-tilesCesiumJS
Cesium3DTileset官方文档:
https://cesium.com/learn/cesiumjs/ref-doc/Cesium3DTileset.htmlCesium 3D Tiles Tools:
https://github.com/CesiumGS/3d-tiles-toolsCesium glTF Pipeline:
https://github.com/CesiumGS/gltf-pipelineGoogle Draco 3D Graphics Compression:
https://google.github.io/draco/Luciad OSGB Format Documentation:
https://dev.luciad.com/portal/productDocumentation/LuciadFusion/docs/documentation.html?subcategory=lls_osgbfanvanzh/3dtiles:
https://github.com/fanvanzh/3dtilesawesome-3d-tiles 工具资源列表:
https://github.com/pka/awesome-3d-tiles
21. 一句话总结#
OSGB 转 3D Tiles 的核心不是单纯格式转换,而是把本地层级化倾斜摄影模型重构为带空间索引、LOD、坐标变换和 Web 优化能力的三维瓦片数据,从而让 CesiumJS 能够在浏览器中按需流式加载和高效渲染。