2016年,Cesium 团队借鉴传统2DGIS的地图规范:WMTS,借鉴图形学中的层次细节模型,打造出大规模的三维数据标准:3d-Tiles,中文译名:三维瓦片。
它在模型上利用了 gltf 渲染快的特点,对大规模的三维数据进行组织,包括层次细节模型、模型的属性数据、模型的层级数据等。
3D Tiles 是在glTF的基础上,加入了分层LOD的概念(可以把3D Tiles简单地理解为带有 LOD 的 glTF ),专门为流式传输和渲染海量 3D 地理空间数据而设计的,例如倾斜摄影、3D 建筑、BIM/CAD、实例化要素集和点云。它定义了一种数据分层结构和一组切片格式,用于渲染数据内容。3D Tiles 没有为数据的可视化定义明确的规则,客户可以按照自己合适的方式来可视化 3D 空间数据。同时,3D Tiles 也是 OGC 标准规范成员之一,可用于在台式机、Web端和移动应用程序中实现与海量异构3D地理空间数据的共享、可视化、融合以及交互功能。
数据处理相关的,可以参看:各类三维模型转为3DTiles格式
首先,我从一个简单的3D Tiles数据示例说起,请看下面目录:
上图是一份 3dTiles数据集在文件夹内的样子,层层打开可得以下特点:
tileset.json
*.json
文件*.b3dm、*.i3dm
等格式对这些数据的结构和详细介绍,我们下一节再详细解说,第一步,我们先学会怎么加载使用这个模型。
平台内加载3dtiles是使用 TilesetLayer类 。
3dTiles至少有一个 tileset.json
文件,作为整个数据集的入口,在代码层面,我们拿到这个主瓦片集JSON 文件(tileset.json)的url地址即可使用加载三维模型了。 如: http://data.mars3d.cn/3dtiles/qx-dyt/tileset.json
当我们拿到这个模型服务地址后:
(3)可以勾选深度检测来方便测试和调试模型高度
(4)如果是人工模型,可以勾选“鼠标拖拽编辑”来手动拖拽模型的位置与地图上匹配。
(5)在该页面调整好所有参数后,单击“保存参数”按钮,保存的参数json,会自动下载一个json文件。
(6) 如果模型是初始化就加载的,可以打开项目的config.json
文件,拷贝刚下载的json到config.json文件的layers参数中即可。
layers:[
{
"name": "模型名称",
"type": "3dtiles",
"url": "http://data.mars3d.cn/3dtiles/qx-dyt/tileset.json",
"maximumScreenSpaceError": 1,
"maximumMemoryUsage": 1024,
"position": {"alt": 452.9 },
"center": { "lat": 34.216894, "lng": 108.959834, "alt": 591, "heading": 4,"pitch": -37 },
"show": true
}
]
var tiles3dLayer = new mars3d.layer.TilesetLayer({
url: 'http://data.mars3d.cn/3dtiles/qx-simiao/tileset.json',
maximumScreenSpaceError: 16,
maximumMemoryUsage: 1024,
position: { alt: 452.9 },
center: { lat: 34.216894, lng: 108.959834, alt: 591, heading: 4,pitch: -37 },
flyTo: true,
})
map.addLayer(tiles3dLayer)
3dTiles 是一种规范(要区分规范和实现的概念),在规范的指导下,各种资源文件可以是独立存在于硬盘中的目录、文件,也可以以二进制形式写入数据库中。
3dTiles还有一个特点:那就是不记录模型数据(指三维模型的顶点、贴图材质、法线、颜色等信息),只记录各级“Tile”的逻辑关系(指LOD是如何组织的),以及“Tile”自己的属性信息(如房子的名称、建设年限、面积等)。
这些数据的原始格式都需要转换为3dtiles格式后,才能在平台加载使用。
通过上面介绍,3dTiles数据的入口文件是一个名叫tileset.json
的文件,在这个json文件中root属性下通过children属性来关联子级节点*.json
,这样一层层关联到叶子节点(如*.b3dm
等格式)。
树结构对于三维空间数据的组织有很大的优势。3dTiles在空间上允许数据集使用如下几种树结构:
八叉树
瓦片对象会引用一个二进制的瓦片数据文件,目前这些文件有以下类型:
文件后缀名 | 名称 | 英文名称 | 对应实际数据 |
---|---|---|---|
b3dm | 批量三维模型 | Batch 3D Model | 传统三维建模数据、BIM数据、倾斜摄影数据 |
i3dm | 实例三维模型 | Instance 3D Model | 一个模型多次渲染的数据,灯塔、树木、椅子等 |
pnts | 点云 | PointCloud | 点云数据 |
cmpt | 复合模型 | Component | 前三种数据的复合(允许一个cmpt文件内嵌多个其他类型的瓦片) |
上面表格中的b3dm 和 i3dm 格式是基于 glTF(一种专为高效传输 3D 内容而设计的开放性规范)构建的,它们的瓦片内容在二进制体中嵌入了 glTF 资源,包含模型的几何和纹理信息,而 pnts 格式却没有嵌入 glTF 资源。
在3dTiles中,模型数据是以glb的形式嵌入在瓦片文件中的(点云直接就写xyz和颜色信息了),模糊了二维中“要素”的概念,而且gltf规范看起来并没有所谓的“要素”的概念,仅仅是对GPU友好的vertex、normal、texture等信息。
瓦片引用的二进制文件有4种,即:b3dm、i3dm、pnts、cmpt。 除去cmpt这个复合类型不谈,前三种的瓦片二进制数据文件的大致字节布局结构见下图:
每一种瓦片二进制数据文件都有一个记录该瓦片的文件头信息,文件头包括若干个因瓦片不同而不太一致的数据信息,紧随其后的是两大数据表:FeatureTable(我翻译其为:要素表)、BatchTable(我翻译其为:批量表)。
这两个表既然是二进制的数据,尽管它名字里带“表”,但是却不是二维表格,它更多的是一些 键值 信息。
#(1)FeatureTable 要素表: 记录渲染相关的数据
在 b3dm 瓦片中,要素表记录这个批量模型瓦片中模型的个数,这个模型单体在人类逻辑上不可再分。
(在房屋级别来看,房子并不是单体,构造它的门、门把、窗户、屋顶、墙等才是模型单体;但是在模型壳子的普通表面建模数据中,房子就是一个简单的模型)
要素表还可以记录当前瓦片的中心坐标,以便gltf使用相对坐标,压缩顶点坐标数字的数据量。
在一个瓦片中,一个三维要素(GIS中的通常叫法)= 一个模型(图形学、工业建模叫法) = 一个BATCH(3dtiles叫法)
要素表的结构:JSON描述信息+要素表数据体
#(2)BatchTable 批量表: 记录属性数据
批量表就是所谓的模型属性表,批量表中每个属性数组的个数,就等于模型的个数,因为有多少个模型就对应多少个属性嘛!如果把批量表删除,那么3dTiles数据还能正常渲染。
批量表的结构:JSON描述信息+批量表数据本体,与 要素表 很像,批量表也是由: 二进制的JSON文本头 + 二进制的数据体 构成的。如下图所示:
#(3)四类类型对应的具体结构
b3dm:
i3dm:与 b3dm 一致,文件头多了个gltfFormat属性。
pnts不存在gltf模型,故结构如下:
cmpt:这是前三种的一种更灵活的组织,允许一个瓦片使用 cmpt 形式,组合多种瓦片,cmpt瓦片可以内嵌任意个、任意类型的瓦片,b3dm、i3dm、pnts均可。
#(4)代码中如何查询瓦片的批量表
我们通常在平台中使用 点击 事件,来获取一个 BATCH,即三维要素。在API中,这个被叫做:Cesium3DTileFeature。那么,这个 Cesium3DTileFeature 就能访问到它自己的批量表中的属性数据:
map.on(mars3d.EventType.click, function(event) {
let feature = event.pickedObject;
//下面只是演示解释底层实现,在平台中直接通过event.graphic.attr可以获取属性
if (feature instanceof Cesium.Cesium3DTileFeature) {
let propertyNames = feature.getPropertyNames();
let length = propertyNames.length;
for (var i = 0; i < length; ++i) {
let propertyName = propertyNames[i];
console.log(propertyName + ': ' + feature.getProperty(propertyName));
}
}
});
用到了 Cesium3DTileFeature.getPropertyNames() 方法获取批量表中所有属性名,用了 Cesium3DTileFeature.getProperty(string Name) 来获取对应属性名的属性值。更多 API 见官方文档。
获取更多关于3D Tiles 的格式信息可访问:
官方github 官方格式说明