3D Tiles介绍
3D Tiles 是在glTF的基础上,加入了分层LOD的概念(可以把3D Tiles简单地理解为带有 LOD 的 glTF ),专门为流式传输和渲染海量 3D 地理空间数据而设计的,例如倾斜摄影、3D 建筑、BIM/CAD、实例化要素集和点云。它定义了一种数据分层结构和一组切片格式,用于渲染数据内容。
主要优点
- 高效性能:通过使用层次化的瓦片数据结构,可以快速加载和渲染大规模地理数据,提供流畅的用户体验。
- 可扩展性:3D Tiles支持数据的分层和分块存储,可以处理非常大的地理数据集,并支持动态加载和渲染。
- 可互操作性:3D Tiles是一个开放的标准,被广泛支持和采用。它可以与不同的地理数据工具和平台进行交互,实现数据的共享和集成。
格式描述
在 3D Tiles 中,一个瓦片集(Tileset)是由一组瓦片(Tile)按照空间数据结构(树状结构)组织而成的,它至少包含一个用于描述瓦片集的 JSON 文件(包含瓦片集的元数据和瓦片对象),其中每一个瓦片对象可以引用下面的其中一种格式,用于渲染瓦片内容:
格式 | 用途 |
---|---|
批处理3D模型 b3dm | 异构3D模型。例如带纹理的地形和表面,3D建筑外部和内部 |
实例化3D模型 i3dm | 3D模型实例。例如树木,风车 |
点云 pnts | 大量的点 |
复合 cmpt | 以上不同格式的切片组合到一个切片中 |
Tilset瓦片集
- asset:描述瓦片集的基本信息,包括版本号、生成工具、生成日期等。
- georeferenced:指示瓦片集是否具有地理参考信息,用于指定坐标系和投影方式。
- properties:自定义的属性,可以用于存储瓦片集的额外信息。
- root:描述瓦片集的根节点,包括其位置、边界框和变换矩阵等信息。
- geometricError:描述瓦片集的几何误差,用于控制瓦片的细节层次和显示精度。
- refine:指示瓦片集的细分策略,可以是"ADD"、"REPLACE"或"FIXED"。
- boundingVolume:描述瓦片集的边界体积,可以是包围盒或球体。
- content:描述瓦片集的内容,包括瓦片的URL、包围盒、材质和属性等信息。
- extensions:扩展属性,用于支持特定的功能或格式扩展。
加载3D Tiles
加载3D Tiles
js
var viewer = new Cesium.Viewer("cesiumContainer");
// 添加3D Tiles
var tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: "./data/Cesium3DTiles/Tilesets/Tileset/tileset.json",
// maximumScreenSpaceError: 2, //最大的屏幕空间误差
// maximumNumberOfLoadedTiles: 1000, //最大加载瓦片个数
})
);
var viewer = new Cesium.Viewer("cesiumContainer");
// 添加3D Tiles
var tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: "./data/Cesium3DTiles/Tilesets/Tileset/tileset.json",
// maximumScreenSpaceError: 2, //最大的屏幕空间误差
// maximumNumberOfLoadedTiles: 1000, //最大加载瓦片个数
})
);
设置样式
js
var properties = tileset.properties;
if (Cesium.defined(properties) && Cesium.defined(properties.Height)) {
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${Height} >= 83", "color('purple', 0.5)"],
["${Height} >= 80", "color('red')"],
["${Height} >= 70", "color('orange')"],
["${Height} >= 12", "color('yellow')"],
["${Height} >= 7", "color('lime')"],
["${Height} >= 1", "color('cyan')"],
["true", "color('blue')"],
],
},
});
}
var properties = tileset.properties;
if (Cesium.defined(properties) && Cesium.defined(properties.Height)) {
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${Height} >= 83", "color('purple', 0.5)"],
["${Height} >= 80", "color('red')"],
["${Height} >= 70", "color('orange')"],
["${Height} >= 12", "color('yellow')"],
["${Height} >= 7", "color('lime')"],
["${Height} >= 1", "color('cyan')"],
["true", "color('blue')"],
],
},
});
}
位置调整
js
var cartographic = Cesium.Cartographic.fromCartesian(
tileset.boundingSphere.center
);
var surface = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
0.0
);
var offset = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
height
);
var translation = Cesium.Cartesian3.subtract(
offset,
surface,
new Cesium.Cartesian3()
);
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
})
.otherwise(function (error) {
console.log(error);
});
var cartographic = Cesium.Cartographic.fromCartesian(
tileset.boundingSphere.center
);
var surface = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
0.0
);
var offset = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
height
);
var translation = Cesium.Cartesian3.subtract(
offset,
surface,
new Cesium.Cartesian3()
);
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
})
.otherwise(function (error) {
console.log(error);
});
拾取要素
js
var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(function (movement) {
var feature = viewer.scene.pick(movement.position);
if (Cesium.defined(feature) && feature instanceof Cesium.Cesium3DTileFeature) {
var propertyNames = feature.getPropertyNames();
var length = propertyNames.length;
for (var i = 0; i < length; ++i) {
var propertyName = propertyNames[i];
console.log(propertyName + ": " + feature.getProperty(propertyName));
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(function (movement) {
var feature = viewer.scene.pick(movement.position);
if (Cesium.defined(feature) && feature instanceof Cesium.Cesium3DTileFeature) {
var propertyNames = feature.getPropertyNames();
var length = propertyNames.length;
for (var i = 0; i < length; ++i) {
var propertyName = propertyNames[i];
console.log(propertyName + ": " + feature.getProperty(propertyName));
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);