【CesiumJS入门】(4)加载3D Tiles并获取tileset

前言

本次,我们将写一个函数来加载3D Tiles数据,

3D Tiles数据的文档:CesiumGS/3d-tiles: Specification for streaming massive heterogeneous 3D geospatial datasets (github.com)

同时我们将获取加载成功后的tileset数据集(有了tileset后续就可以方便得进行模型相关的操作了),下图为加载模型后的效果。
在这里插入图片描述

实现

写法一

该写法配合Promise,通过实例化一个Cesium3DTileset后通过readyPromise返回tileset,但是这种写法将在CesiumJS 1.107 版本后弃用!!

/**
 * @function addThreeDTiles
 * @param {String} url - 模型切瓦后的瓦片索引文件URL或者Cesium Resource
 * @param {Object} [option] - 选项对象(可选) https://cesium.com/learn/cesiumjs/ref-doc/Cesium3DTileset.html#.ConstructorOptions
 */
 
export function addThreeDTiles(url, option) {
    
    
  // 开启地形深度检测:
  // 控制在渲染场景时,相机是否进行深度测试以避免将被遮挡的物体绘制在前景
  // true: 相机会根据地形高度信息进行深度测试,避免将低于地面的物体绘制在地面之上
  viewer.scene.globe.depthTestAgainstTerrain = true

  // ! 写法一:将在 1.107 版本后不支持,options.url和Cesium3DTileset.readyPromise将被移除
  return new Promise(resolve => {
    
    
    const tileset = new Cesium.Cesium3DTileset({
    
    
      url // 模型切瓦后的瓦片索引文件地址或者Cesium Resource
    })
    tileset.readyPromise.then(() => {
    
    
      viewer.scene.primitives.add(tileset)
    })
    resolve(tileset) // 返回模型对象
  })
}

调用:

const modelPromise = addThreeDTiles('/model/Tileset/示例建筑/tileset.json')  // 模型切瓦后的瓦片索引文件URL
const modelPromise2 = addThreeDTiles(Cesium.IonResource.fromAssetId(75343)) // Cesium Ion Resource

modelPromise.then(tileset=> {
    
    
  console.log('tileset: ', tileset)
})

推荐:写法二:

配合 async/awaitCesium3DTileset.fromUrlfromIonAssetId来实现:

export async function addThreeDTiles(url, option) {
    
    

  viewer.scene.globe.depthTestAgainstTerrain = true
  
  // ! 写法二:
  let tileset = {
    
    }
  if (typeof url == 'number') {
    
    
    tileset = await Cesium.Cesium3DTileset.fromIonAssetId(url, option);
  } else {
    
    
    tileset = await Cesium.Cesium3DTileset.fromUrl(url, option);
  }
  
  viewer.scene.primitives.add(tileset);

  return tileset // 返回模型对象
}

调用方法类似:

const modelPromise = addThreeDTiles('/model/Tileset/示例建筑/tileset.json')  // 模型切瓦后的瓦片索引文件URL
const modelPromise2 = addThreeDTiles(69380) // Cesium Ion Resource

modelPromise.then(tileset=> {
    
    
  console.log('tileset: ', tileset)
})

Options

通过上述封装的函数在加载3D Tiles 瓦片集时,可以传入option,option则为初始化Cesium3DTileset时的配置项对象,参考中文文档: Cesium3DTileset - Cesium Documentation

移除tileset

viewer.scene.primitives.remove(tileset);

代码

代码提交参考:
feat: 新增添加3D Tiles · c3759ef · ReBeX/cesium-tyro-blog - Gitee.com
fix: 优化3D Tiles加载方法 · ff20c46 · ReBeX/cesium-tyro-blog - Gitee.com

/*
 * @Date: 2023-05-23 10:45:33
 * @LastEditors: ReBeX  [email protected]
 * @LastEditTime: 2023-06-14 23:24:54
 * @FilePath: \cesium-tyro-blog\src\utils\ThreeDTiles\loadTileset.js
 * @Description:  从给定 URL 加载 3D 模型,添加到场景中,并自动定位到模型所在位置
 * import { addThreeDTiles } from '@/utils/ThreeDTiles/loadTileset.js'
 * const modelPromise = addThreeDTiles('/model/Tileset/示例建筑/tileset.json')
 * const modelPromise = addThreeDTiles(69380)
 * modelPromise.then(model => {
 *   console.log('tileset: ', model)
 * })
 */
import {
    
     viewer } from '@/utils/createCesium.js' // 引入地图对象
import * as Cesium from 'cesium'

/**
 * @function addThreeDTiles
 * @param {String} url - 模型切瓦后的瓦片索引文件URL或者Cesium Resource
 * @param {Object} [option] - 选项对象(可选) https://cesium.com/learn/cesiumjs/ref-doc/Cesium3DTileset.html#.ConstructorOptions
 */
const tilesetOption = {
    
    
  skipLevelOfDetail: true,
  baseScreenSpaceError: 1024,
  skipScreenSpaceErrorFactor: 16,
  skipLevels: 1,
  immediatelyLoadDesiredLevelOfDetail: false,
  loadSiblings: false,
  cullWithChildrenBounds: true
}
export async function addThreeDTiles(url, option) {
    
    
  // 开启地形深度检测:
  // 控制在渲染场景时,相机是否进行深度测试以避免将被遮挡的物体绘制在前景
  // true: 相机会根据地形高度信息进行深度测试,避免将低于地面的物体绘制在地面之上
  viewer.scene.globe.depthTestAgainstTerrain = true

  /*
  // ! 写法一:将在 1.107 版本后不支持,options.url和Cesium3DTileset.readyPromise将被移除
  return new Promise(resolve => { // 返回 Promise 对象
    const tileset = new Cesium.Cesium3DTileset({
      url // 模型切瓦后的瓦片索引文件地址或者Cesium Resource: Cesium.IonResource.fromAssetId(75343)
    })
    tileset.readyPromise.then(() => {
      viewer.scene.primitives.add(tileset)
    })
    resolve(tileset) // 返回模型对象
  })
  */

  // ! 写法二:
  let tileset = {
    
    }
  if (typeof url == 'number') {
    
    
    tileset = await Cesium.Cesium3DTileset.fromIonAssetId(url, option);
  } else {
    
    
    tileset = await Cesium.Cesium3DTileset.fromUrl(url, option);
  }

  viewer.scene.primitives.add(tileset);
  // 定位到模型
  viewer.zoomTo(
    tileset,
    new Cesium.HeadingPitchRange(
      0.0,
      -0.5,
      tileset.boundingSphere.radius * 2.0 // 模型的包围球半径的2倍
    )
  )
  return tileset // 返回模型对象
}

猜你喜欢

转载自blog.csdn.net/ReBeX/article/details/131214220
今日推荐