3d-tiles

3d-tiles

十月 16, 2021

3d-tiles

参考资料

  1. https://github.com/CesiumGS/3d-tiles
  2. https://blog.csdn.net/qq_31709249/article/details/102643371
  3. https://zhuanlan.zhihu.com/p/350265716

正篇

3D Tiles

3D Tiles是用于流式传输大规模异构3D地理空间数据集的开放规范。为了扩展Cesium的地形和图像流,3D Tiles将用于流式传输3D内容,包括建筑物,树木,点云和矢量数据。

3D Tiles 在glTF的基础上,加入了分层HLOD的概念(可以把3D Tiles简单地理解为带有H LOD 的 glTF ),3D Tiles和二维地图中的瓦片组织非常相似,它定义了一种数据分层结构和一组切片格式,用于渲染数据内容。瓦片被组织在一个树中,它结合了层次细节级别 (HLOD) 的概念,以实现空间数据的最佳渲染。每个图块都有一个边界体积,一个定义空间范围的对象,完全包围其内容。树具有空间连贯性;子图块的内容完全在父图块的边界体积内。3D Tiles 没有为数据的可视化定义明确的规则,客户可以按照自己合适的方式来可视化 3D 空间数据。同时,3D Tiles 也是 OGC 标准规范成员之一,可用于在台式机、Web端和移动应用程序中实现与海量异构3D地理空间数据的共享、可视化、融合以及交互功能。

https://github.com/CesiumGS/3d-tiles/blob/main/specification/figures/tree.png?raw=true

Tileset—瓦片集

通常,一个3D Tiles 数据会使用一个主 tileset JSON 文件作为定义 tileset 的入口点,一般是以 tileset.json 文件命名(当然该文件名称可以修改)。tileset JSON 至少包含三个顶级属性:asset、geometricError、root。下面是一个tileset.json文件的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
{
"asset": {
"generatetool": "cesiumlab2@www.cesiumlab.com/model2tiles",
"version": "1.0"
},
"properties": null,
"geometricError": 3.6255706558004,
"root": {
"boundingVolume": {
"box": [
-1.04773789644241e-9,
1.9557774066925e-8,
5.49168255459517,
0.410892067127861,
0,
0,
0,
1.8127853279002,
0,
0,
0,
4.49168282654136
]
},
"children": [
{
"boundingVolume": {
"box": [
5.5309181290486e-8,
7.38692391921703e-7,
5.49168255574461,
0.4108913511616,
0,
0,
0,
1.8127834921778,
0,
0,
0,
4.49168282572488
]
},
"content": {
"uri": "NoLod_0.b3dm"
},
"geometricError": 0,
"refine": "REPLACE"
}
],
"geometricError": 3.6255706558004,
"transform": [
-0.895779813464058,
-0.444498060502289,
0,
0,
0.285164241402339,
-0.574680507450024,
0.767087784925827,
0,
-0.340969032634527,
0.687141752891415,
0.641542149992959,
0,
-2177749.05056977,
4388733.74629915,
4070061.61183291,
1
]
}
}

1)asset
asset包含整个tileSet的元数据对象。asset.Version属性,用于定义3D Tiles版本,该版本指定tileset的JSON模式和基本的tileset格式。tileVersion属性可选,用于定义特定的应用程序的tileset。

2)properties
properties是一个对象,包含tileset中每个feature属性的对象。上面的例子是一个建筑物的3DTiles,因此每个瓦片都含有三维建筑物模型,每个三维建筑物模型都有高度属性,所以上面的例子中就定义了Height属性。属性中每个对象的名称与每个要素属性的名称相对应(如例子中的Height对应高度),并且包含该属性的最大值和最小值,这些值用于创建样式的颜色渐变非常有用。

3)geometricError
geometricError是一个非负数,是通过这个几何误差的值来计算屏幕误差,确定Tileset是否渲染。如果在渲染的过程中,当前屏幕误差大于这里定义的屏幕误差,这个Tileset就不渲染。即根据屏幕误差来控制Tileset中的root是否渲染。

4)root
root 是一个 JSON 对象,定义了最根级的 Tile ,它存储的是真正的Tile 。也就是说,root 的数据组织方式与 Tile 的数据组织方式是一样的。

需要注意的是,root.geometricError 与 tileset 的顶级 geometricError 不同,tileSet的geometricError是根据屏幕误差来控制tileSet中的root是否渲染,而root(tile)中的geometricError则是用来控制tile中的children是否渲染。

root.children 是一个定义子 Tile 的对象数组,每个Tile还会有其children,这样就形成了一种递归定义的树状结构。每个子 Tile 的内容完全由其父 Tile 的boundingVolume 包围,并且通常是其 geometricError 小于其父 Tile 的 geometricError,因为越接近叶子节点,模型越精细,与原模型的几何误差就越小。对于叶子节点的 Tile ,其数组的长度为零,或者是未定义 children 。

当然,为了创建树状结构,tile 的 content.uri 也可以指向外部的 tileset(另一个 tileset 的 JSON 文件)。这样做的一个好处就是,不同的tileset可以分开存储,例如我国的每个城市可单独存储成一个tileset,然后再定义一个包含所有 tileset 的全局 tileset。

Tiles—瓦片

瓦片包含用于确定是否渲染瓦片的元数据、对渲染内容的引用以及任何子瓦片的数组。切片实际上也是一个JSON对象,它由以下属性组成。

1)boundingVolumes(边界范围框)
定义了瓦片的最小边界范围,用于确定在运行时渲染哪个瓦片,有region、box、sphere三种形式。

2)geometricError(几何误差)
是一个非负数,以米为单位定义了不同瓦片层级的几何误差,通过几何误差来计算以像素为单位的屏幕误差(SSE),从而确定不同缩放级别下应该调用哪个层级的瓦片。简单来说,Tile的几何误差是用来确定瓦片切换层级的,即控制LOD的。

3)refine(细化方式)
确定瓦片从低级别(LOD)切换为高级别(LOD)的呈现过程,简单来说就是瓦片是如何切换的,其中包括替换(REPLACE)和添加(ADD)两种方式。替换就是直接把父级的瓦片替换掉,添加则是在父级瓦片的基础增加细节部分。

理论上来说,ADD方式是一种非常好的方式,是一种增量的LOD策略,能够减少数据的传输。这里强调一下,refine属性在根节点的Tile中是必须定义的,子节点中是可选的。如果子节点没有定义,则继承父节点的该属性。

4)content(内容)

content属性指定了瓦片实际渲染的内容。content.uri属性可以是一个指定二进制块(b3dm、i3dm、pnts、cmpt)的位置,也可以是指向另一个外部的tileset.json。
content.boundingVolume属性定义了类似 Tile属性boundingVolume的边界范围框,但是content.boundingVolume是一个紧密贴合的边界范围框,仅包含切片的内容。该属性可以用来做视锥体裁剪,只渲染视图范围内的内容,如果该属性没定义,系统也会自动计算。下图是关于Tile.boundingVolumes和content.boundingVolumes 的比较,红色是Tile的boundingVolumes,包围了Tileset的整个区域;蓝色是content的boundingVolumes,仅包围切片中的渲染模型。

5)children(孩子节点)
这个很容易理解,因为3D Tiles是分级别的,所以每个Tile还会有子Tile、子子Tile、子子子Tile …,分的越多,层级划分的越精细,和下面讲到的Tileset瓦片集root.children是同一个概念。

6)viewerRequestVolume(可选,观察者请求体)
定义了一个边界范围,使用与boundingVolumes相同的模式,只有当观察者处于其定义的范围内时,Tile才显示,从而精细控制了个别瓦片的显示与否。如下图所示,只有相机拉近到某一个距离时,才显示屋内的球。

7)transform(可选,位置变换矩阵)
定义了一个4x4的变换矩阵 ,通过此属性,Tile的坐标就可以是自己的局部坐标系内的坐标,最后通过自己的transform矩阵变换到父节点的坐标系中。它会对Tile的content、boudingVolume、viewerRequestVolume进行转换。详情可查看3D Tiles的规范文档。

Tile 数据格式

格式 用途
批量3D模型(b3dm) 大型异构3D模型,包括三维建筑物、地形等
实例3D模型(i3dm) 3D模型实例,如树、风力发电机等
点云(pnts) 点云
组合数据(cmpt) 以上不同格式的切片组合到一个切片中