Cesium Terrain Builder(CTB)功能扩展与源码修改实践
本文基于 Cesium Terrain Builder(CTB)源码,系统讲解了 Quantized Mesh Terrain 的结构与生成流程,并实现了非 gzip Terrain 输出及指定瓦片范围生成等生产级功能扩展与编译实践。
基于 Cesium Terrain Builder(CTB)源码实现:
- 支持输出非 gzip 压缩 Quantized Mesh Terrain
- 支持按指定瓦片范围输出 Terrain Tile
一、项目背景
Cesium Terrain Builder(CTB)是一个用于生成 Cesium Terrain Tile 的开源工具。
官方项目:
- geo-data/cesium-terrain-builder
- quantized-mesh terrain specification
CTB 可以:
- 从 DEM(GeoTIFF)生成 Terrain Tile
- 输出:
- heightmap-1.0
- quantized-mesh-1.0
二、业务问题
CTB 默认输出:
textgzip 压缩 terrain tile
即:
text*.terrain
文件实际为:
textgzip(binary terrain data)
默认 gzip 的问题#
在某些业务场景:
- Terrain 为内网访问
- 本地 SSD
- 局域网
- 浏览器缓存命中高
此时:
textgzip 解压增加浏览器 CPU 消耗
因此:
希望支持输出非 gzip terrain tile。
三、CTB 源码结构分析
1. Terrain 数据对象#
heightmap-1.0#
textTerrainTile
quantized-mesh-1.0#
textMeshTile
官方 quantized-mesh 规范:
textTerrain tiles are served gzipped.
2. Terrain 生成器#
TerrainTiler#
生成:
textTerrainTile
MeshTiler#
生成:
textMeshTile
3. Terrain 序列化器#
核心:
textCTBFileTileSerializer
负责:
texttile -> 文件
四、功能扩展:支持非 gzip 输出
1. 增加 gzip 参数#
文件:
texttools/ctb-tile.cpp
TerrainBuild 增加:
cppbool gzib;
构造函数默认:
cppgzib(false)
2. 增加命令行参数#
cppstatic void setGzib(command_t* command) { static_cast(Command::self(command))->gzib = true; }
main 注册:
cppcommand.option( "-G", "--gzip", "use gzip compress file(default uncompress)", TerrainBuild::setGzib );
3. 修改 serializeTile#
文件:
textCTBFileTileSerializer.cpp
增加:
cppbool gzibFlag
核心代码:
cppif (gzibFlag) { CTBZFileOutputStream ostream(temp_filename.c_str()); tile->writeFile(ostream, writeVertexNormals); ostream.close(); } else { FILE *fp = fopen(temp_filename.c_str(), "wb"); CTBFileOutputStream ostream(fp); tile->writeFile(ostream, writeVertexNormals); fclose(fp); }
4. buildMesh 传递参数#
cppserializer.serializeTile( tile, writeVertexNormals, command->gzib );
五、功能扩展:指定范围输出
1. 增加参数#
TerrainBuild 增加:
cppint layerStartX; int layerStartY; int layerEndX; int layerEndY;
默认:
cpplayerStartX(-1), layerStartY(-1), layerEndX(-1), layerEndY(-1)
2. 注册参数#
cppcommand.option("-A", "--start-x <sx>", "tile start x", TerrainBuild::setLayerStartX); command.option("-D", "--end-x <ex>", "tile end x", TerrainBuild::setLayerEndX); command.option("-W", "--start-y <sy>", "tile start y", TerrainBuild::setLayerStartY); command.option("-S", "--end-y <ey>", "tile end y", TerrainBuild::setLayerEndY);
3. buildMesh 范围过滤#
核心逻辑:
cppif ( coordinate->x >= layerStartX && coordinate->x <= layerEndX && coordinate->y >= layerStartY && coordinate->y <= layerEndY )
六、编译
Linux#
bashsudo apt install build-essential cmake libgdal-dev zlib1g-dev bash mkdir build cd build cmake .. make -j8
七、命令行说明
默认 terrain#
bashctb-tile -o terrain dem.tif
quantized mesh#
bashctb-tile -f Mesh -o terrain dem.tif
指定范围#
bashctb-tile.exe -o D:/test/tile D:/test/dem.tif -f Mesh -s 6 -e 6 -A 105 -D 107 -W 45 -S 47
gzip 输出#
bashctb-tile -G -f Mesh -o terrain dem.tif
八、完整参数
| 参数 | 说明 |
|---|---|
| -V | 输出版本 |
| -h | 帮助 |
| -o | 输出目录 |
| -p | geodetic / mercator |
| -f | Terrain / Mesh |
| -c | 线程 |
| -t | tile size |
| -s | start zoom |
| -e | end zoom |
| -r | 重采样 |
| -R | 不覆盖 |
| -G | gzip |
| -A | start x |
| -D | end x |
| -W | start y |
| -S | end y |
九、DEM 预处理
NoData 处理#
textCon(IsNull("xxxx.tif"),0,"xxxx.tif")
作用:
textNoData -> 0
PixelType#
推荐:
textfloat -> int16/int32
十、生产建议
非 gzip 适合:#
- 内网
- SSD
- 本地 terrain
- 高并发
大范围 terrain#
推荐:
- 分块生成
- 局部更新
- 分 zoom 生产
十一、相关项目
- geo-data/cesium-terrain-builder
- ahuarte47/cesium-terrain-builder
- CesiumGS/quantized-mesh
- tum-gis/ctb-quantized-mesh
十二、结论
本次源码扩展实现:
1. 非 gzip terrain 输出#
解决:
text浏览器解压 CPU 开销
问题。
2. 指定范围 terrain 输出#
支持:
text局部 terrain 更新
降低:
- 生成时间
- 磁盘占用
- 更新成本