Cesium实战系列文章总目录
:
传送门
1. 介绍
英文原文链接:传送门
英文好的可以直接看原文哈,本文加入了自己的一点理解,若有出错的地方,请大家批评指正。
3D Tiles
是Cesium
于2016年3月定义的一种三维模型瓦片数据格式,目前已经是OGC
标准之一,3D Tiles将海量三维数据以分块分层的形式组织起来,大大减轻了浏览器和GPU的负担。从结构关系上看,3D Tiles归属于Primitive
,有很高的数据加载效率。
3D Tiles
专为流式传输和渲染3D地理数据而设计的,如倾斜摄影测量、BIM、点云、建筑数据等。特点有:
(1)开放且灵活。3D Tiles作为开放数据规范,其切片方案灵活可变,三维模型的切片大小和覆盖范围可以人为设置。此外,3D Tiles还可以适配三维空间中多种空间分区方案,如四叉树、八叉树、KD树等。
(2)异质性支持。通过一组已定义的文件格式,将多种三维地理空间要素(如倾斜摄影测量、BIM、点云、建筑数据、实例化要素等)转换为三维形式的单个数据集,同时又允许多种不同格式标准的模型显示在同一场景中。
(3)专为三维可视化设计。3D Tiles建立在gltf格式之上,并引入了三维图形学技术,以树状的层级细节模型(HLOD
)进行组织,降低海量数据可视化过程中的浏览器负担,减少WebGL绘制请求的数量。
(4)可交互。3D Tiles支持交互旋转和样式的设置。如单击高亮,修改单个模型的材质,根据属性信息设置不同的显示效果等。
在3D Tiles中一组数据由tileset
(瓦片数据集)进行组织,每一个tileset
至少有一个JSON
文件描述,该文件包含tileset
元数据和一个tile对象树,每个tile
对象可以引用以下各自之一的可渲染内容:
格式 | 用途 |
---|---|
Batched 3D Model (*.b3dm) | 异构3三维模型。如地形、建筑等 |
Instanced 3D Model (*.i3dm) | 实例化三维模型。如树木、风车等 |
Point Cloud (*.pnts) | 点云数据 |
Composite | 将不同格式的瓦片连接到一个瓦片中 |
Vector Data (*.vctr) | 矢量数据(尚未发布) |
每个tile
的content
是瓦片的实例,是包含Feature Table
和Batch Table
特定组件的二进制blob
。
content
引用了一组要素集,例如代表建筑、树木、点云的三维模型。每个要素的位置(position
)和外观属性(appearance
)存储在瓦片的Feature Table
中,和存储在Batch Table
中的特定于应用的属性。客户端可以在运行时选择要素属性以可视化和分析。
批量3D模型和实例3D模型格式建立在GLTF之上,这是一种为高效传输3D内容而设计的开放格式规范。瓦片的content
的二进制文件内嵌入了gltf,其中包含了模型几何和纹理信息,点云格式不嵌入gltf。
瓦片以树形结构进行组织,使用了层次细节模型(HLOD),以优化空间数据的渲染。每个瓦片都有bounding volume
属性,和定义其包围的控件范围的对象content
。索引树具有空间连续性,子瓦片的完全在父瓦片的外包盒内。
瓦片集(tileset
)可以使用二维栅格和矢量的瓦片方案(如Web地图瓦片服务WMTS
或者XYZ
方案),它们以多个细节级别提供预定义的瓦片。由于瓦片集的内容通常是不均匀的,不易在二维中进行组织,因此树是具有空间一致性的空间数据结构
,包括k-d树,四叉树,八叉树和网格。
可以选择将3D Tiles Style
或者style
应用到瓦片集中,样式定义了每个要素的表现形式。
2. 文件扩展和MIME类型
3D Tiles使用以下文件扩展和MIME类型。
(1)瓦片集文件使用.json
扩展和application/json
的MIME类型
(2)瓦片内容使用文件类型和瓦片格式规范的MIME类型
(3)瓦片集样式文件使用.json
扩展和application/json
的MIME类型
显式文件扩展名是可选的,有效的实现可能会忽略它并通过瓦片内容中标题的magic
字段进行识别。
3. JSON编码
3D Tiles对JSON格式和编码有以下限制
(1)JSON必须使用没有BOM的UTF-8编码
(2)本规范中的所有字符串(属性名称、枚举)等仅使用ASCII字符集,并以纯文本的形式编写
(3)JSON对象中的键值对中的键是唯一的,即不允许重复键。
4. URIs
3D Tiles使用URI来引用瓦片内容,这些URI可能指向外部引用(RFC3986
),或者在JSON中嵌入资源数据的URI。嵌入式资源使用数据URI方案(RFC2397
)。
当URI是相对时,它基于瓦片集的JSON文件。
客户端实现需要支持相关的外部引用和嵌入式资源,可以支持其他方案(如http://
),所有的URI都必须有效且可解析。
5. 单位
所有线段
距离单位都是米
。
所有角度
都是弧度
制。
6. 概念
6.1 坐标参考系
3D Tiles使用右手笛卡尔坐标系,即x和y叉积产生z。3D Tiles将z轴定义为局部笛卡尔坐标系的向上。瓦片集的全球坐标系常使用WGS84
(EPSG 4978)地心坐标参考系。但没有地理空间上下文的建模工具生产的模型则不是以此为坐标参考系。
可以使用额外的瓦片变换,将瓦片的局部坐标参考系转换为其父瓦片的坐标参考系。
区域边界使用地理坐标系(经度、纬度和高度)指定。
6.2 瓦片
瓦片由用于判断是否渲染瓦片的元数据、对可渲染内容的引用和所有子瓦片的数组组成。
6.2.1 几何误差
瓦片使用层级细节模型的树形结构进行组织,因此在客户端运行时,需要确定瓦片是否足够详细以进行渲染,以及瓦片的内容是否应该由更高分辨率的子瓦片细化。在实现过程中需要考虑最大屏幕空间误差(Screen-Space Error,SSE
),误差使用像素值进行度量。
瓦片的几何误差定义了该瓦片的选择度量。其值是一个非负数,单位是米,用于指定瓦片的几何图形简化的误差。在根节点瓦片中具有最大的几何图形简化误差。其连续的子瓦片具有比其父级更低的几何误差,叶子瓦片的几何误差接近于0。
在客户端实现过程中,几何误差和其他屏幕空间度量一起使用,如瓦片到相机的距离,屏幕带下和分辨率——当瓦片渲染,但其子瓦片未渲染时计算屏幕空间误差,如果屏幕空间误差超过了设置的最大值,则对瓦片进行细化,渲染其子瓦片。
几何误差是基于点密度、以米为单位的瓦片和瓦片集的其他因素等制定的。一般来说,较高的几何误差意味着更积极地细化瓦片,并且更快地加载和渲染子瓦片。
6.2.2 细化
细化是指低分辨率父瓦片渲染中选择高分辨率的子瓦片进行渲染的过程。
允许细化的类型是替换(replace
)和添加(add
),替换是指细化过程中只渲染子瓦片而不渲染父瓦片,添加是在渲染父瓦片的基础上渲染子瓦片。
一个瓦片集可以专门使用只替换、只添加或者两者进行组合的细化策略。
瓦片集的根瓦片需要设置细化类型,对于其他瓦片,细化类型可选。当省略时,瓦片将继承其父类的细化类型。
6.2.2.1 替换
当瓦片使用替换的细化类型,使用其子瓦片渲染代替其自己。
父瓦片 | 细化 |
---|---|
6.2.2.2 添加
若瓦片使用添加细化类型,则会同时渲染父瓦片和子瓦片。
父瓦片 | 细化 |
---|---|
6.2.3 外包区域
外包体定义了瓦片的空间范围。为了支持各种数据集的紧密拟合体积,例如规则划分的地形、位于经纬度线对齐的城市和点云等,外包区域类型包括外包盒、外包球和外包边界。
外包盒 | 外包球 | 外包边界 |
---|---|---|
6.2.3.1 外包盒
由12个数字组成数组,前三个元素定义了中心点坐标(x,y,z),其次的三个元素(索引3,4,5)定义了x轴方向半长,然后的三个元素(索引6,7,8)定义了y轴方向和半长,最后的三个元素(索引9,10,11)定义了z轴方向和半长。
"boundingVolume": {
"box": [
0, 0, 10,
100, 0, 0,
0, 100, 0,
0, 0, 10
]
}
6.2.3.2 外包球
外包球由四个数字组成的数组定义,前三个元素定义了球体中心的x,y,z坐标,最后一个元素定义了球体的半径。
"boundingVolume": {
"sphere": [
0,
0,
10,
141.4214
]
}
6.2.3.3 外包边界
由六个数字组成的数组进行定义。分别为[西,南,东,北,最小高度,最大高度],经纬度是WGS84
基准下的弧度制
单位,高度的单位为米。
"boundingVolume": {
"region": [
-1.3197004795898053,
0.6988582109,
-1.3196595204101946,
0.6988897891,
0,
20
]
}
6.2.4 可视请求域
瓦片的viewerRequestVolume
用于组成异构数据集,可与外部瓦片组合。
下面的例子有一个b3m
的建筑瓦片及其内部的pnts
点云瓦片。点云瓦片的外包区域是半径为1.5的球体,它有一个半径更大的球体viewerRequestVolume
。由于几何误差是0,当可视范围在点云瓦片的可视请求域内部时,该点云瓦片将会被一直渲染。
{
"children": [{
"transform": [
4.843178171884396, 1.2424271388626869, 0, 0,
-0.7993325488216595, 3.1159251367235608, 3.8278032889280675, 0,
0.9511533376784163, -3.7077466670407433, 3.2168186118075526, 0,
1215001.7612985559, -4736269.697480114, 4081650.708604793, 1
],
"boundingVolume": {
"box": [
0, 0, 6.701,
3.738, 0, 0,
0, 3.72, 0,
0, 0, 13.402
]
},
"geometricError": 32,
"content": {
"uri": "building.b3dm"
}
}, {
"transform": [
0.968635634376879, 0.24848542777253732, 0, 0,
-0.15986650990768783, 0.6231850279035362, 0.7655606573007809, 0,
0.19023066741520941, -0.7415493329385225, 0.6433637229384295, 0,
1215002.0371330238, -4736270.772726648, 4081651.6414821907, 1
],
"viewerRequestVolume": {
"sphere": [0, 0, 0, 15]
},
"boundingVolume": {
"sphere": [0, 0, 0, 1.25]
},
"geometricError": 0,
"content": {
"uri": "points.pnts"
}
}]
}
6.2.5 变换
6.2.5.1 瓦片变换
为了支持局部坐标系,例如,城市瓦片集中的建筑瓦片集可以在其内部坐标系中定义,建筑瓦片集内的点云瓦片也可以在其内部坐标系定义,每个瓦片都有一个可选的变换(transform
)属性。
transform
属性是一个4*4的仿射变化矩阵,以列主序的形式存储。将瓦片的局部坐标系转换为父瓦片的坐标系或者转换为瓦片集中根节点瓦片的坐标系。
该transform
变换属性适用于:
①tile.content
瓦片内容
a.每个要素的位置
b.当使用比例变换时,每个要素的法线都应通过左上角的三维矩形进行逆变换,以实现正确的变换
c.content.boundingVolume
,除非在EPSG:4979
中明确定义了content.boundingVolume.region
②tile.boundingVolume
除非tile.boundingVolume.region
在EPSG:4979
中明确定义了
③tile.viewerRequestVolume
除非tile.viewerRequestVolume.region
在EPSG:4979
中明确定义了
该transform
属性按照最大比例缩放几何误差。
当transform
未定义时,默认为单位矩阵:
[
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
]
从每个瓦片的局部坐标系到瓦片集的全局坐标系的转换是通过瓦片集的自上而下的遍历以及通过子级的transform
与父级的transform
进行计算,就像计算机图形中的传统场景图或者节点层次结构一样。
6.2.5.2 glTF变换
批量和实例化三维模型瓦片中嵌入了glTF
,它定义了自己的节点层次结构并使用y轴向上的坐标系,在使用瓦片变换后,才能对这些特定格式和属性进行变换。
首先,需要根据glTF
的规范应用glTF
的节点层次结构。
其次,为了与3D Tiles
的z轴向上保持一致,需要将glTF
从y轴向上转换为z轴向上,通过绕x轴渲染π/2来实现,即以下矩阵变换:
[
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
]
更通用地说,即转换的顺序是:
①glTF节点层次结构转换
②glTFy轴向上到z轴向上转换
③所有瓦片格式的特定变换
批量三维模型要素表可以定义RTC_CENTER
,用于转换模型顶点。
实例三维模型要素表定义了每个实例的位置、法线和比例,这些将应用于每个实例创建四维变换矩阵
④瓦片变换
**具体实施说明:**当处理固有的z向上的源数据时,如WGS84坐标系或局部
z轴向上的坐标系时,常用的工作流程是:
网格数据,包括位置和法线,不会被修改,保持z轴向上。
根节点矩阵指定列从z轴向上转换为y轴向上,将源数据转换为glTF所需的y轴向上坐标系。
在运行时,glTF使用上面的矩阵从y轴向上转换为z轴向上,实际上将变换抵消了。
示例glTF根节点:
"nodes": [
{
"matrix": [1,0,0,0,0,0,-1,0,0,1,0,0,0,0,0,1],
"mesh": 0,
"name": "rootNode"
}
]
对于瓦片集的转换示例(transformToRoot
在上面的代码中):
每块瓦片的计算转换为:
TO:[T0]
T1:[T0][T1]
T2:[T0][T2]
T3:[T0][T1][T3]
T4:[T0][T1][T4]
瓦片内容中的位置和法线也可以在瓦片变换之前应用特定的变换,例子如下:
b3dm
和i3dm
瓦片嵌入了glTF
,它定义了自己的节点层次结构和坐标系,tile.transform
在这些转换之后应用i3dm
的要素表定义了每个实例的位置、法线和比例。这些用于用于创建每个实例的4维变换矩阵,在tile.transform
之前应用- 压缩属性,如i3dm和pnts的要素表中的
POSITION_QUANTIZED
,pnts
中的NORMAL_OCT16P
,应该在其他转换之前解压缩
因此上述示例的完整计算转换为:
TO: [T0]
T1: [T0][T1]
T2: [T0][T2][pnts-specific transform, including RTC_CENTER (if defined)]
T3: [T0][T1][T3][b3dm-specific transform, including RTC_CENTER (if defined), coordinate system transform, and glTF node hierarchy]
T4: [T0][T1][T4][i3dm-specific transform, including per-instance transform, coordinate system transform, and glTF node hierarchy]
下面的代码展示了如何使用Cesium中的Matrix4和Matrix3
来进行计算:
function computeTransforms(tileset) {
var t = tileset.root;
var transformToRoot = defined(t.transform) ? Matrix4.fromArray(t.transform) : Matrix4.IDENTITY;
computeTransform(t, transformToRoot);
}
function computeTransform(tile, transformToRoot) {
// Apply 4x4 transformToRoot to this tile's positions and bounding volumes
var inverseTransform = Matrix4.inverse(transformToRoot, new Matrix4());
var normalTransform = Matrix4.getRotation(inverseTransform, new Matrix3());
normalTransform = Matrix3.transpose(normalTransform, normalTransform);
// Apply 3x3 normalTransform to this tile's normals
var children = tile.children;
var length = children.length;
for (var i = 0; i < length; ++i) {
var child = children[i];
var childToRoot = defined(child.transform) ? Matrix4.fromArray(child.transform) : Matrix4.clone(Matrix4.IDENTITY);
childToRoot = Matrix4.multiplyTransformation(transformToRoot, childToRoot, childToRoot);
computeTransform(child, childToRoot);
}
}
6.2.6 瓦片 JSON
瓦片JSON对象包含了以下属性:
以下代码展示了非叶子节点瓦片:
{
"boundingVolume": {
"region": [
-1.2419052957251926,
0.7395016240301894,
-1.2415404171917719,
0.7396563300150859,
0,
20.4
]
},
"geometricError": 43.88464075650763,
"refine" : "ADD",
"content": {
"boundingVolume": {
"region": [
-1.2418882438584018,
0.7395016240301894,
-1.2415422846940714,
0.7396461198389616,
0,
19.4
]
},
"uri": "2/0/0.b3dm"
},
"children": [...]
}
boundingVolume
定义了瓦片的外包体积,用于确定渲染过程中需要的瓦片。上述示例中给出了一个外包边界,也可以使用外包盒和外包球等类型。
可选的viewerRequestVolume
属性(上面未显示)定义了一个体积,与boundingVolume
的使用方式相同,它必须在基于几何误差的瓦片请求之前位于瓦片内容中。
refine
属性是一个字符串,包括"REPLACE
"和"ADD
",瓦片集的根瓦片需要它,对于非根瓦片,它是可选的。瓦片集内可以使用添加和替换的任意组合。当refine
属性被省略时,它将从父瓦片继承。
content
属性是一个包含瓦片可渲染内容元数据的对象。content.uri
是一个uri
,它指向瓦片的二进制文件,或者使用另一个瓦片集JSON
文件来创建。
当文件扩展中没有content.uri
时,内容的瓦片格式可以通过其标题的magic
字段来标识,或者从外部瓦片集的JSON
中获取。
content.boundingVolume
属性定义了一个类似于顶层外包区属性的可选外包区域,与之不同的是,content.boudingVolume
是一个进包含瓦片内容的紧密贴合外包体。boundingVolume
提供空间连续性,而content.boundingVolume
启用了视锥体剔除,剔除不在潜在可视范围内的所有内容。当它没有被定义时,瓦片的外包区域将被用于剔除。
下面的截图显示了根瓦片的外包区域,包含了瓦片集的整个区域,以红色显示。content.boundingVolume
仅包含根瓦片中的四个模型要素,以蓝色展示。
可选的transform
属性(上述未显示)定义了四维仿射变换矩阵,用于瓦片的content
、boundingVolume
和viewerRequestVolume
的变换,如上文瓦片变换所述。
children
属性定义了子瓦片数组的对象,每个子瓦片的内容都完全被其父瓦片的boundingVolume
包围,通常其几何误差要小于父瓦片的几何误差,对于其叶子瓦片,数组的长度为0,孩子瓦片可能未定义。
有关瓦片JSON文件架构的参考,请查看属性参考,完整的JSON结构可以在tile.schema.json
中查看。
6.3 瓦片集
3D Tiles使用一个主瓦片集的JSON文件定义瓦片集的入口。入口和特定的瓦片集JSON文件都不需要遵循特定的命名约定。
这是上文的瓦片集的JSON文件的一个子集:
{
"asset" : {
"version": "1.0",
"tilesetVersion": "e575c6f1-a45b-420a-b172-6449fa6e0a59",
},
"properties": {
"Height": {
"minimum": 1,
"maximum": 241.6
}
},
"geometricError": 494.50961650991815,
"root": {
"boundingVolume": {
"region": [
-0.0005682966577418737,
0.8987233516605286,
0.00011646582098558159,
0.8990603398325034,
0,
241.6
]
},
"geometricError": 268.37878244706053,
"refine": "ADD",
"content": {
"uri": "0/0/0.b3dm",
"boundingVolume": {
"region": [
-0.0004001690908972599,
0.8988700116775743,
0.00010096729722787196,
0.8989625664878067,
0,
241.6
]
}
},
"children": [..]
}
}
瓦片集JSON有四个顶级属性:asset
、properties
、geometricError
和root
。
asset
是一个包含整个瓦片集元数据的对象。asset.version
属性字符串定义了3D TIles的版本,它指定了瓦片集的JSON结构和基本瓦片规范。tilesetVersion
属性是一个可选的字符串,定义了特定应用版本的瓦片集,如当现有的瓦片集更新时。实现说明:tileVersion
可在请求内容时用作查询参数,以避免使用缓存中的过时内容。
properties
是一个包含瓦片集内所有要素属性的对象。上述瓦片集的JSON文件是用于3D建筑物的,每块瓦片中都包含了建筑模型,每个模型都具有height
高度属性。properties
中的每个对象与要素属性一一匹配,其值定义了非常有效的最大maximun
和最小minimum
数值,例如创建渐变颜色等。
geometricError
是一个非负数,它确定了瓦片集的渲染误差,单位为米。在运行时,几何误差将用于计算屏幕空间误差,如果屏幕空间误差没有超过要求的最小值,则不渲染该瓦片集即其中的任何瓦片。
root
是使用瓦片JSON定义根瓦片的对象。root.geometricError
与瓦片集的顶级geometricError
不同,瓦片集的geometricError
在渲染运行时用于确定瓦片集根瓦片的屏幕空间误差,而root.geometriError
用于确定子瓦片渲染过程中的屏幕空间误差。
6.3.1 外部瓦片集
要创建一棵树,一个瓦片的content.uri
可以指向一个外包瓦片集(另一个瓦片集的JSON文件),例如,将每个城市存储到瓦片集中,然后将拥有该瓦片集的一个全局瓦片集合。
当一个瓦片指向外部瓦片集时,这个瓦片:
- 不能有任何孩子瓦片,
tile.children
必须为undefined
或者空数组 - 不能用于创建循环,例如,通过指向该包含该瓦片的同一个数据集或者指向另一块瓦片集,然后再指向包含该瓦片的初始文件
- 将瓦片的
transform
和根瓦片的transform
都进行变换。例如,在引用外部瓦片集的以下瓦片中,T3的计算变换为:[T0][T1][T2][T3]
如果外部瓦片集定义了asset.tilesetVersion
,它将覆盖父瓦片集的值。如果外部瓦片集未定义asset.tilesetVersion
,该值将会从父瓦片(已定义)中继承。
6.3.2 外包区域空间相关性
如上所述,树具有空间相关性,每个瓦片都具有一个完全包含其内容的外包区,子瓦片的内容完全在父瓦片的外包区内,但这并不意味子外包区完全在父外包区内。
例如:地形瓦片外包球:
四个子瓦片的外包球,子瓦片的内容完全在父瓦片内,但子外包区域不完全在父外包体内,因为它们并不是紧密贴合的。
6.3.3 空间数据结构
3D Tiles使用了层次细节模型(HLOD
),以优化空间数据的渲染。瓦片集根节点由树形结构进行组织,其子瓦片可以通过不同的空间数据结构进行组织。
实时渲染引擎在瓦片集中的任何树的渲染是通用的,可以使用瓦片格式和细化方法的组合,从而灵活地支持异构数据集。
瓦片集可以使用类似于2D空间栅格和矢量瓦片方案(如Web地图瓦片服务WMTS
或XYZ
方案),它们以多个细节级别(或缩放层级)提供预定义瓦片。然而,由于瓦片集的内容通常是不均匀的,不容易直接使用二维的方式进行组织,因此可以优化其他空间数据结构。
下面简要介绍了3D Tiles的各种空间数据结构。
6.3.3.1 四叉树
四叉树(Quadtrees
):类似典型的2D空间瓦片方案,创建四叉树时,将瓦片均匀划分的四个子瓦片(例如,使用中心点经纬度)。空的子瓦片是可以省略的。经典四叉树划分如下图所示:
3D Tiles支持四叉树的变化版本,如非均匀划分和紧密边界体积划分(与边界相反,例如,对于稀疏的数据集是浪费的,如只占父瓦片的25%区域)。每个子瓦片都具有紧密的边界体积的四叉树如下图:
例如,这里是根瓦片和子瓦片。注意左下角,外包区域不包括左小角没有建筑出现的水。
3D Tiles还支持四叉树变体,如松散四叉树,其子瓦片发生了重叠,但仍保留空间连贯性,如下图所示。即父瓦片完全包含所有子瓦片。此方法可用于避免跨瓦片的要素拆分,如三维模型。
如下图,绿色建筑位于左子瓦片,而紫色建筑位于右子瓦片上。因为瓦片会重叠,因此中心的绿色建筑和紫色建筑并没有分开。
6.3.3.2 K-D树
当每个瓦片由一个平行于x、y或z轴(或经度、纬度、高度)的平面分割为两个子级时,就会创建一个k-d
树。分割轴通常会随着树的级别增加而循环旋转,并且可以使用中值分割、表面积约束或其他区方式进行分割。
非均匀
划分的KD树,如下图所示。
k-d树不像典型的二维地理空间切片方案那样具有统一的细分,因此可以为稀疏和非均匀分布的数据集创建更平衡的树。
3D Tiles支持k-d树的变化版本,如多路k-d树,在树的每个叶子上,沿轴进行了多次拆分。每块瓦片并不是只有2个孩子瓦片,而是有n个孩子。
6.3.3.3 八叉树
八叉树(Octrees
)通过使用三个正交的分割平面来扩展四叉树,将一个瓦片划分为八个子级。与四叉树一样,3D Tiles允许是对八叉树进行变化,例如非均匀细分、紧密边界体积和重叠子级等。
传统八叉树划分如下图:
使用添加细化方式的非均匀八叉树的点云分割如下图所示。
6.3.3.4 网格
3D Tiles支持任意数量子瓦片的均匀、非均匀和重叠的网格(grid
),如下图,非均匀网格。
3D Tiles利用具有边界区域但没有实际内容的空瓦片。由于瓦片的content
属性不需要定义,因此可以使用空的非叶子瓦片通过分层剔除的方式来加速非均匀网络。这实质上创建了一个没有层次细节模型(HLOD)的四叉树或八叉树。
6.4 指定扩展和应用附加功能
3D Tiles定义了扩展以允许基本规范具有新要素的可扩展性,以特定程序和元数据的附加属性。
6.4.1 扩展
扩展允许使用新要素扩展基本规范。可选extensions
属性可以添加到任何3D Tiles JSON
对象中,其中包含了扩展名和扩展特定对象。以下示例显示了瓦片对象增加了一个扩展,指定了一个特定的冲突区域。
{
"transform": [
4.843178171884396, 1.2424271388626869, 0, 0,
-0.7993325488216595, 3.1159251367235608, 3.8278032889280675, 0,
0.9511533376784163, -3.7077466670407433, 3.2168186118075526, 0,
1215001.7612985559, -4736269.697480114, 4081650.708604793, 1
],
"boundingVolume": {
"box": [
0, 0, 6.701,
3.738, 0, 0,
0, 3.72, 0,
0, 0, 13.402
]
},
"geometricError": 32,
"content": {
"uri": "building.b3dm"
},
"extensions": {
"VENDOR_collision_volume": {
"box": [
0, 0, 6.8,
3.8, 0, 0,
0, 3.8, 0,
0, 0, 13.5
]
}
}
}
瓦片集或任何外部瓦片集中所使用的扩展都必须在顶级的extensionsUsed
数组属性在瓦片集的JSON文件中,例如:
{
"extensionsUsed": [
"VENDOR_collision_volume"
]
}
瓦片集的加载和渲染,或任何外部瓦片集所需的所有扩展也必须在顶级JSON文件中的extensionsRequired
数组属性中列出,例如extensionsUsed
的一个子集extensionsRequired
,extensionsRequired
的所有值必须在extensionUsed
中列出。
6.4.2 附加功能
extras
属性运行将应用程序特定的元数据添加到3D Tiles的JSON对象中,一下示例显示了具有附加应用特定名称属性的瓦片对象。
{
"transform": [
4.843178171884396, 1.2424271388626869, 0, 0,
-0.7993325488216595, 3.1159251367235608, 3.8278032889280675, 0,
0.9511533376784163, -3.7077466670407433, 3.2168186118075526, 0,
1215001.7612985559, -4736269.697480114, 4081650.708604793, 1
],
"boundingVolume": {
"box": [
0, 0, 6.701,
3.738, 0, 0,
0, 3.72, 0,
0, 0, 13.402
]
},
"geometricError": 32,
"content": {
"uri": "building.b3dm"
},
"extras": {
"name": "Empire State Building"
}
}
7. 瓦片格式规范
每个瓦片的content.uri
属性可以是二进制blob
的uri
,包含了三维内容的渲染信息,这个内容是下表中列出的格式之一的实例。
格式 | 用途 |
---|---|
批量三维模型 Batched 3D Model(b3dm) | 异构三维模型,例如带纹理的地形和表面、三维建筑外部和内部、大型模型等 |
实例三维模型 Instanced 3D Model(i3dm) | 三维模型实例,例如树木、风车、螺栓 |
点云 Point Cloud(pnts) | 海量点云 |
复合 Composite(cmpt) | 将不同格式的瓦片组成到一个瓦片中 |
瓦片集可以包含瓦片格式的任意组合。3D Tiles也可以使用复合瓦片和支持同一个瓦片中的不同格式。
8. 声明样式规范
3D Tiles包括用JSON定义的简明声明样式,以及用一小部分JavaScript编写的表达式,增强了样式。
样式定义了要素的显示方式,如show
和color
(RGB
和透明)用于要素属性的表达。
以下示例将高度高于90的要素显示为红色,其余则为白色。
{
"color" : "(${Height} > 90) ? color('red') : color('white')"
}
9. 属性参考
瓦片集的属性如下:
Tileset
Asset
Bounding Volume
Extension
Extras
Properties
Tile
Content
具体属性列表:
名称 | 类型 | 描述 | 是否必须 |
---|---|---|---|
asset | object | 整个瓦片集的元数据 | 是 |
properties | any | 每个要素属性的元数据字典对象 | 否 |
geometricError | number | 几何误差,以米为单位 | 是 |
root | object | 瓦片集的根瓦片 | 是 |
rextensionUsed | string[1-*] | 瓦片特定应用场景下的扩展名 | 否 |
extensionRequired | string[1-*] | 正确加载此瓦片集所需要的扩展 | 否 |
extensions | object | 特定应用对象的字典对象 | 否 |
extras | any | 特定于应用程序的数据 | 否 |
9.1 Asset
关于整个瓦片集的元数据
名称 | 类型 | 描述 | 是否必须 |
---|---|---|---|
version | string | 3D Tiles版本 | 是 |
tilesetVersion | string | 特定应用版本的瓦片集 | 否 |
extensions | object | 特定扩展对象的字典对象 | 否 |
extras | any | 特定应用的数据 | 否 |
9.2 Bounding Volume
包围瓦片或者其内容的外包区域。必须指定一种外包体属性,可能是box
、region
或者sphere
。扩展可以定义额外的外包体类型,如果指定了多个外包体,客户可以根据用例和性能要求选择最为合适的选项。
名称 | 类型 | 描述 | 是否必须 |
---|---|---|---|
box | number[12] | 外包盒 | 否 |
region | number[6] | 外包区域 | 否 |
sphere | number[4] | 外包球 | 否 |
extensions | object | 扩展特定对象的字典对象 | 否 |
extras | any | 特定应用的数据 | 否 |
9.3 Extension
具有扩展特定对象的字典对象,运行附加类型。
9.4 Extras
特定于应用的数据。
9.5 Properties
每个要素属性的元数据字典对象
名称 | 类型 | 描述 | 是否必须 |
---|---|---|---|
maximum | number | 属性的最大值 | 是 |
manimum | number | 属性的最小值 | 是 |
extensions | object | 扩展特定对象的字典对象 | 否 |
extras | any | 特定应用的数据 | 否 |
9.6 Tile
3D Tiles瓦片集中的瓦片。
名称 | 类型 | 描述 | 是否必须 |
---|---|---|---|
boundingVolume | object | 瓦片及其内容的外包体 | 是 |
viewerRequestVolume | object | 查看请求的区域 | 否 |
geometricError | number | 几何误差 | 是 |
refine | string | 瓦片细化方式 | 否 |
transform | number[16] | 四维变换矩阵 | 否,默认为单位矩阵 |
content | object | 瓦片内容的元数据和内容链接 | 否 |
children | array[] | 子瓦片数组 | 否 |
extensions | object | 扩展特定对象的字典对象 | 否 |
extras | any | 特定应用的数据 | 否 |
9.7 Content
关于瓦片内容的元数据和内容链接
名称 | 类型 | 描述 | 是否必须 |
---|---|---|---|
boundingVolume | object | 瓦片及其内容的外包体 | 否 |
uri | string | 指向瓦片内容的链接 | 是 |
extensions | object | 扩展特定对象的字典对象 | 否 |
extras | any | 特定应用的数据 | 否 |