前言
本次,我们将写一个函数来加载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/await
用Cesium3DTileset.fromUrl
或fromIonAssetId
来实现:
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 420659880@qq.com
* @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 // 返回模型对象
}