Cesium4--地形(OSGB到3DTiles)

发布于:2025-09-15 ⋅ 阅读:(17) ⋅ 点赞:(0)

1 OSBG

OSGB(OpenSceneGraph Binary)是基于 OpenSceneGraph(OSG) 三维渲染引擎的二进制三维场景数据格式,广泛用于存储和传输倾斜摄影测量、BIM、点云等大规模三维模型,尤其在国产地理信息与智慧城市项目中应用普遍。

这个格式是国产的,涉及到的软件就有点尴尬,国产软件的德行都知道,难用还很多坑。。。

几个免费的可以下载练手OSBG的地方。

来源 内容类型 下载方式 适用练习
GitCode 武汉景点倾斜摄影模型 城市 / 景区实景三维 项目页 下载 加载、浏览、简单分析
GitCode 通用倾斜摄影数据 城市 / 建筑模型 项目页 下载(密码:123321) 格式测试、性能验证
GitCode 倾斜摄影示例数据 小范围示例场景 项目页 下载 教学演示、功能测试
GitCode 三维山地模型(含 3DTiles) 山地河谷、村落、BIM 项目页 下载 多格式兼容、场景分析
GitCode 城市级倾斜摄影数据 大规模城市模型 项目页 下载 性能测试、城市级渲染
百度网盘 台北市倾斜模型 城市级倾斜模型 网盘(提取码:ae9w) 城市建模、地形分析

2 格式转换

目前基本上就几个软件能弄,一个是CesiumLab,一个是SuperMap iDesktop。剩下还有很多不知名的软件。。。

2.1 CesiumLab

CesiumLab听着像官方产品,实际不是,是北京一个公司。而且还不能单独装,先要装一个他们的全家桶“地球可视化实验室”,然后在里面安装这个CesiumLab。

安装了之后点运行,15分钟都没能启动起来。看了一下changelog,居然还有用户名是中文就异常的BUG。。。

好不容易启动了找到怎么转换,研究了半天参数准备转换。结果弹出来。。。让去新地方注册。

看了一下。

真实姓名,电话号码,工作单位全部都要填进去,就差没弄个户口本进去。折腾完了终于看可以转换了,一点开始转换。直接没了。。。

又看了一下。

貌似还得上传工牌,公司盖章。。。

算了,放弃治疗了。。

2.2 SuperMap iDesktop

下载之后又是要授权。。

我看我这边全是否,估计着是要钱才行。算了吧。。。

2.3 老子云

这个是B站看到的,名字确实有点点霸气。网址是:https://www.laozicloud.com/

也是要注册一大堆,估计以后也是要收费的,不过确实还能免费用。

转换的时间很长,110MB的数据就差不多半个小时。

3 3Dtiles

转换出来的数据大概是这样的。

每个tile里面是这样。一个json和一堆glb

3.1 rootTileset.json

{
    "asset": {
        "gltfUpAxis": "Z",
        "version": "1.0"
    },
    "extensionsUsed": [
        "3DTILES_content_gltf"
    ],
    "geometricError": 2000,
    "root": {
        "boundingVolume": {
            "box": [
                -74.0523910522461,
                22.896909713745117,
                309.3908233642578,
                85.72734832763672,
                0.0,
                0.0,
                0.0,
                112.13745307922363,
                0.0,
                0.0,
                0.0,
                56.62489318847656
            ]
        },
        "children": [
            {
                "boundingVolume": {
                    "box": [
                        -109.0,
                        -44.450782775878906,
                        296.45343017578125,
                        43.68748474121094,
                        0,
                        0,
                        0,
                        43.6874885559082,
                        0,
                        0,
                        0,
                        43.6875
                    ]
                },
                "content": {
                    "uri": "./Tile_+001_+000/tileset.json"
                },
                "geometricError": 4.36875
            },
            {
                "boundingVolume": {
                    "box": [
                        -95.49225616455078,
                        16.0,
                        304.4522705078125,
                        42.26628875732422,
                        0,
                        0,
                        0,
                        42.266265869140625,
                        0,
                        0,
                        0,
                        42.266265869140625
                    ]
                },
                "content": {
                    "uri": "./Tile_+001_+001/tileset.json"
                },
                "geometricError": 4.226628875732422
            },
            {
                "boundingVolume": {
                    "box": [
                        -109.0,
                        84.25462341308594,
                        310.2703857421875,
                        50.77973937988281,
                        0,
                        0,
                        0,
                        50.77973937988281,
                        0,
                        0,
                        0,
                        50.77972412109375
                    ]
                },
                "content": {
                    "uri": "./Tile_+001_+002/tileset.json"
                },
                "geometricError": 5.077973937988282
            },
            {
                "boundingVolume": {
                    "box": [
                        -39.0,
                        -41.21886444091797,
                        299.5376281738281,
                        44.396854400634766,
                        0,
                        0,
                        0,
                        48.02167892456055,
                        0,
                        0,
                        0,
                        44.3968505859375
                    ]
                },
                "content": {
                    "uri": "./Tile_+002_+000/tileset.json"
                },
                "geometricError": 4.802167892456055
            },
            {
                "boundingVolume": {
                    "box": [
                        -39.81702423095703,
                        16.0,
                        314.52374267578125,
                        51.491981506347656,
                        0,
                        0,
                        0,
                        51.491981506347656,
                        0,
                        0,
                        0,
                        51.491973876953125
                    ]
                },
                "content": {
                    "uri": "./Tile_+002_+001/tileset.json"
                },
                "geometricError": 5.149198150634766
            },
            {
                "boundingVolume": {
                    "box": [
                        -39.81702423095703,
                        69.45303344726563,
                        304.82012939453125,
                        39.80249786376953,
                        0,
                        0,
                        0,
                        39.80249786376953,
                        0,
                        0,
                        0,
                        40.469970703125
                    ]
                },
                "content": {
                    "uri": "./Tile_+002_+002/tileset.json"
                },
                "geometricError": 4.0469970703125
            }
        ],
        "geometricError": 11.213745307922364,
        "transform": [
            -0.0,
            1.0,
            0.0,
            0.0,
            0.0,
            -0.0,
            1.0,
            0.0,
            1.0,
            0.0,
            0.0,
            0.0,
            6378137.0,
            0.0,
            0.0,
            1.0
        ]
    }
}
  • asset
    数据集的基本信息,版本、坐标轴方向等。

  • geometricError
    顶层误差阈值,控制LOD(细节层级)切换。

  • root
    根瓦片(root tile),定义了整个模型的范围和第一个瓦片。

    • boundingVolume:瓦片的空间范围(box / region / sphere)。

    • geometricError:当前瓦片的最大几何误差,决定是否继续向下加载子瓦片。

    • refineREPLACEADD,决定加载子瓦片时是替换父瓦片,还是叠加细节。

    • children:子瓦片信息。

  • content
    指向实际的模型文件(如 .b3dm.glb.pnts)。

3.2 tileset.json

格式和root几乎大同小异。

实在太长,就简单摘抄一部分吧。

{
    "asset": {
        "extensionsUsed": [
            "3DTILES_content_gltf"
        ],
        "gltfUpAxis": "Z",
        "version": "1.0"
    },
    "geometricError": 1000,
    "root": {
        "boundingVolume": {
            "box": [
                -109.0,
                -44.450782775878906,
                296.45343017578125,
                43.68748474121094,
                0,
                0,
                0,
                43.6874885559082,
                0,
                0,
                0,
                43.6875
            ]
        },
        "children": [
            {
                "boundingVolume": {
                    "box": [
                        -109.0,
                        -44.529869079589844,
                        296.2623291015625,
                        43.747650146484375,
                        0,
                        0,
                        0,
                        43.747650146484375,
                        0,
                        0,
                        0,
                        43.747650146484375
                    ]
                },
                "children": [
                    {
                        "boundingVolume": {
                            "box": [
                                -109.0,
                                -44.41993713378906,
                                296.2623291015625,
                                43.68302917480469,
                                0,
                                0,
                                0,
                                43.68303298950195,
                                0,
                                0,
                                0,
                                43.68304443359375
                            ]
                        },
                        "children": [
                            {
                                "boundingVolume": {
                                    "box": [
                                        -108.79536437988281,
                                        -31.627532958984375,
                                        297.58258056640625,
                                        39.55524444580078,
                                        0,
                                        0,
                                        0,
                                        39.55524444580078,
                                        0,
                                        0,
                                        0,
                                        39.55523681640625
                                    ]
                                },
                                "children": [
                                    {
                                        "boundingVolume": {
                                            "box": [
                                                -117.75,
                                                -31.122161865234375,
                                                296.3058776855469,
                                                17.014083862304688,
                                                0,
                                                0,
                                                0,
                                                17.01408576965332,
                                                0,
                                                0,
                                                0,
                                                17.01409912109375
                                            ]
                                        },
                                        "children": [
                                            {
                                                "boundingVolume": {
                                                    "box": [
                                                        -117.72776794433594,
                                                        -37.15178680419922,
                                                        296.82281494140625,
                                                        10.89080810546875,
                                                        0,
                                                        0,
                                                        0,
                                                        10.868576049804688,
                                                        0,
                                                        0,
                                                        0,
                                                        10.868560791015625
                                                    ]
                                                },
                                                "children": [
                                                    {
                                                        "boundingVolume": {
                                                            "box": [
                                                                -117.72532653808594,
                                                                -37.15178680419922,
                                                                296.8204345703125,
                                                                10.850723266601563,
                                                                0,
                                                                0,
                                                                0,
                                                                10.826057434082031,
                                                                0,
                                                                0,
                                                                0,
                                                                10.8260498046875
                                                            ]
                                                        },
                                                        "content": {
                                                            "boundingVolume": {
                                                                "box": [
                                                                    -117.72532653808594,
                                                                    -37.15178680419922,
                                                                    296.8204345703125,
                                                                    10.850723266601563,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    10.826057434082031,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    10.8260498046875
                                                                ]
                                                            },
                                                            "uri": "./Tile_+001_+000_L22_001200.glb"
                                                        },
                                                        "geometricError": 1.0850723266601563,
                                                        "name": "Tile_+001_+000_L22_001200.osgb"
                                                    }
                                                ],

可以看到,root里面的uri是下层的json。这里则是对应的glb文件。

3.3 Tile_+001_+000_L17_0.glb

没啥好多说的,就是切小了的glb文件。关于glb在前面写过了。。。

3.4 小节

从上面可以看出。Cesium 的 3D Tiles(比如 3DTileset)本质上就是:

把一个很大的 3D 模型(GLB/OBJ/las 点云等)切分成多个小块,再通过一个 JSON 索引文件(tileset.json) 来描述这些小块的层级、边界和加载逻辑。这样 Cesium 在浏览时就可以做到 按需加载、分层细节(LOD)管理,避免一次性加载超大模型。

4 Cesium加载

最后还是能加载了。只是问题很多,主要是方向。

代码如下:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Cesium基础地球</title>
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Cesium.js"></script>
  <link href="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
  <style>
    #cesiumContainer { width: 100%; height: 100vh; }
  </style>
</head>
<body>
 
<div id="cesiumContainer"></div>
<script>
  // 初始化 Cesium Viewer
  Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzYjVkMmRhYy03OGMxLTQwM2EtYWY0Ny00MDM4YjhjZmVkNzIiLCJpZCI6MzA0Mzc4LCJpYXQiOjE3NDc3MzE5NDN9.kzP84v1ibzx6iJP_ESqc-PiJ6-fTbHQvCR2KMc9lvws';
  const viewer = new Cesium.Viewer("cesiumContainer", {
    terrainProvider: new Cesium.EllipsoidTerrainProvider()
  });

  // 加载 3D Tiles (指向 rootTileset.json)
  const tileset = new Cesium.Cesium3DTileset({
    url: "data/rootTileset.json"   // 相对路径,index.html 同级目录下的 data 文件夹
  });

  viewer.scene.primitives.add(tileset);

  tileset.readyPromise.then(function() {
  const longitude = 139.7101;
  const latitude = 35.6852;
  const height = 50.0;

  const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);

  // 设置旋转角度(弧度制)
  const heading = Cesium.Math.toRadians(90); // 水平方向
  const pitch   = Cesium.Math.toRadians(0);   // 上下倾斜
  const roll    = Cesium.Math.toRadians(300);   // 翻滚

  const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
  const modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(position, hpr);

  // 如果需要缩放,可以加这一句(比如缩小 0.1 倍)
  const scale = 0.1;
  tileset.modelMatrix = Cesium.Matrix4.multiplyByUniformScale(modelMatrix, scale, new Cesium.Matrix4());

  // 相机飞过去
  viewer.zoomTo(tileset);
});

</script>
 
</body>
</html>