Skip to content

3D Tiles介绍

3D Tiles 是在glTF的基础上,加入了分层LOD的概念(可以把3D Tiles简单地理解为带有 LOD 的 glTF ),专门为流式传输和渲染海量 3D 地理空间数据而设计的,例如倾斜摄影、3D 建筑、BIM/CAD、实例化要素集和点云。它定义了一种数据分层结构和一组切片格式,用于渲染数据内容。

主要优点

  1. 高效性能:通过使用层次化的瓦片数据结构,可以快速加载和渲染大规模地理数据,提供流畅的用户体验。
  2. 可扩展性:3D Tiles支持数据的分层和分块存储,可以处理非常大的地理数据集,并支持动态加载和渲染。
  3. 可互操作性:3D Tiles是一个开放的标准,被广泛支持和采用。它可以与不同的地理数据工具和平台进行交互,实现数据的共享和集成。

格式描述

在 3D Tiles 中,一个瓦片集(Tileset)是由一组瓦片(Tile)按照空间数据结构(树状结构)组织而成的,它至少包含一个用于描述瓦片集的 JSON 文件(包含瓦片集的元数据和瓦片对象),其中每一个瓦片对象可以引用下面的其中一种格式,用于渲染瓦片内容:

格式用途
批处理3D模型 b3dm异构3D模型。例如带纹理的地形和表面,3D建筑外部和内部
实例化3D模型 i3dm3D模型实例。例如树木,风车
点云 pnts大量的点
复合 cmpt以上不同格式的切片组合到一个切片中

Tilset瓦片集

  1. asset:描述瓦片集的基本信息,包括版本号、生成工具、生成日期等。
  2. georeferenced:指示瓦片集是否具有地理参考信息,用于指定坐标系和投影方式。
  3. properties:自定义的属性,可以用于存储瓦片集的额外信息。
  4. root:描述瓦片集的根节点,包括其位置、边界框和变换矩阵等信息。
  5. geometricError:描述瓦片集的几何误差,用于控制瓦片的细节层次和显示精度。
  6. refine:指示瓦片集的细分策略,可以是"ADD"、"REPLACE"或"FIXED"。
  7. boundingVolume:描述瓦片集的边界体积,可以是包围盒或球体。
  8. content:描述瓦片集的内容,包括瓦片的URL、包围盒、材质和属性等信息。
  9. 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);