# 使用 CesiumJS 创建优化的 3D Tileset 模型

在现代地理信息系统(GIS)应用中,3D Tiles 是一种高效的方式,用于处理和可视化大规模三维数据。本文将介绍如何使用 CesiumJS 创建一个具有优化设置的 3D Tileset 模型。我们将逐步解析代码,并解释每个部分的功能。

# 代码解析

以下是创建优化 Tileset 模型的核心代码:

createOptimizedTileSetModel(data, viewer) {
  // 创建具有优化设置的 tileset 选项
  const tileSetOptions = {
    id: data.id,
    url: data.url,
    skipLevelOfDetail: true,  // 跳过细节级别
    baseScreenSpaceError: 1024,  // 基本屏幕空间误差
    maximumScreenSpaceError: 4,  // 最大屏幕空间误差
    skipScreenSpaceErrorFactor: 16,  // 跳过屏幕空间误差因子
    skipLevels: 1,  // 跳过级别数
    immediatelyLoadDesiredLevelOfDetail: false,  // 立即加载所需级别的细节
    loadSiblings: true,  // 加载相邻的 tile
    cullWithChildrenBounds: true,  // 使用子 tile 边界进行剔除
    cullRequestsWhileMoving: true,  // 在移动时剔除请求
    cullRequestsWhileMovingMultiplier: 10,  // 移动时剔除请求的乘数
    preloadWhenHidden: true,  // 隐藏时预加载
    preferLeaves: true,  // 首选叶子节点
    maximumMemoryUsage: 512,  // 最大内存使用量
    progressiveResolutionHeightFraction: 0.5,  // 渐进式分辨率高度因子
    dynamicScreenSpaceErrorDensity: 1,  // 动态屏幕空间误差密度
    dynamicScreenSpaceErrorFactor: 1,  // 动态屏幕空间误差因子
    dynamicScreenSpaceError: true,  // 动态屏幕空间误差
    show: true,  // 显示 tileset
  };
  // 创建 tileset 模型实例
  const tileSetModel = new Cesium3DTileset(tileSetOptions);
  // 将 tileset 添加到场景
  viewer.scene.primitives.add(tileSetModel);
  tileSetModel.readyPromise.then((tileset) => {
    // 3D tile 模型的边界球体
    var boundingSphere = tileset.boundingSphere;
    // 迪卡尔空间直角坐标 => 地理坐标(弧度制)
    var cartographic_original = Cesium.Cartographic.fromCartesian(boundingSphere.center);
    // 地理坐标(弧度制) => 迪卡尔空间直角坐标
    var Cartesian3_original = Cesium.Cartesian3.fromRadians(
      cartographic_original.longitude,
      cartographic_original.latitude,
      cartographic_original.height
    );
    var Cartesian3_offset = Cesium.Cartesian3.fromRadians(
      cartographic_original.longitude,
      cartographic_original.latitude,
      1
    );
    // 获得地面和 offset 的转换
    var translation = Cesium.Cartesian3.subtract(Cartesian3_offset, Cartesian3_original, new Cesium.Cartesian3());
    // 修改模型矩阵
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
    viewer.zoomTo(
      tileset,
      new Cesium.HeadingPitchRange(
        0.5,
        -0.2,
        tileset.boundingSphere.radius * 1.0
      )
    );
  });
}

# 代码详解

# 1. Tileset 选项配置

在函数开始,我们定义了 tileSetOptions 对象,其中包含多种优化参数:

  • skipLevelOfDetail: 允许跳过细节级别,以提高渲染效率。
  • baseScreenSpaceErrormaximumScreenSpaceError: 控制渲染的精度和性能。
  • cullRequestsWhileMoving: 在相机移动时剔除不必要的请求,进一步提升性能。

# 2. 创建 Tileset 实例

使用 Cesium3DTileset 创建一个 tileset 实例,并将其添加到视图器的场景中:

const tileSetModel = new Cesium3DTileset(tileSetOptions);
viewer.scene.primitives.add(tileSetModel);

# 3. 加载后的处理

当 tileset 准备就绪后,我们计算其边界球体,并进行坐标转换,以确保模型在场景中的正确定位。此部分代码负责调整模型的位置矩阵并缩放视图器视角:

tileSetModel.readyPromise.then((tileset) => {
  // 计算边界球体和调整模型矩阵
});

# 总结

通过以上步骤,我们能够在 CesiumJS 中创建一个优化的 3D Tileset 模型。这种方法不仅提高了渲染效率,还确保了较高的视觉质量,适用于大规模地理数据的可视化。