1. 前言
3D Tiles 常用于城市规划、建筑设计和基础设施管理,可以直观地展示城市的三维模型。通过加载和渲染大规模三维场景,支持VR和AR应用的开发。在GIS中,3D Tiles可用于展示地形和其他地理数据,增强空间分析和可视化能力。
先看下官网给出的案例效果图,能更直观的了解3D Tile的作用。
2. 使用Cesium3DTileset
在Cesium ion的Asset Depot中找到纽约3D Tile,添加到My Assets中。
在项目中添加代码。
const tileset = viewer.scene.primitives.add(
await Cesium.Cesium3DTileset.fromIonAssetId(75343),
);
由于是纽约的建筑效果原型,则需要定位到纽约去观察效果。
viewer.zoomTo(tileset);
该方法用于将相机平滑地移动到指定的 3D Tiles 数据集(tileset
)的边界,使其完全可见。这是一个非常方便的功能,可以帮助用户快速聚焦于特定的 3D 模型或场景。
我们来看下效果:
嗯,不咋地,与期望的第一个图的视角有偏差。这里八青妹给出自己的视角值,仅供参考:
let initialPosition = Cesium.Cartesian3.fromDegrees(
-74.01881302800248,
40.69114333714821,
1200
);
viewer.camera.setView({
destination: initialPosition,
orientation: {
// 水平方向的角度,以弧度表示
heading: Cesium.Math.toRadians(20.0),
// 垂直方向的角度,以弧度表示
pitch: Cesium.Math.toRadians(-30.0),
},
});
3. 定义3D Tiles数据集的样式
通过Cesium.Cesium3DTileStyle(style)
来设置样式,通过样式折纸来修改颜色、透明度、可见性等。主要可设置的属性:
- color:用于设置单个模型或多个模型的颜色,可以使用表达式。
- show:控制模型的可见性。
示例:
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${Height} >= 100", 'color("purple", 0.5)'],
["${Height} >= 50", 'color("red")'],
["true", 'color("blue")'],
],
},
show: "${Height} > 10",
});
这里颜色显示的条件是,建筑物高度大于等于100的时候,显示透明度0.5的紫色;高度在大于等于50并小于100的时候显示红色,其他情况下显示蓝色;建筑物高度大于10的才显示。
这里给出最上面示例图的颜色参考值,颜色按照此配置,就可以得到接近效果图的颜色。
color: {
conditions: [
["${Height} >= 300", "rgba(45, 0, 75, 0.5)"],
["${Height} >= 200", "rgb(102, 71, 151)"],
["${Height} >= 100", "rgb(170, 162, 204)"],
["${Height} >= 50", "rgb(224, 226, 238)"],
["${Height} >= 25", "rgb(252, 230, 200)"],
["${Height} >= 10", "rgb(248, 176, 87)"],
["${Height} >= 5", "rgb(198, 106, 11)"],
["true", "rgb(127, 59, 8)"],
],
},
当然,在控制是否显示的属性当中,也可以用表达式去写,例如:
show: {
conditions: [
["${Height} >= 200", "true"],
["${Height} >= 25", "false"],
["true", "true"],
],
},
通过该表达式,可以显示的建筑为高度小于25的和高度大于200。
4. 调整偏移高度
建筑物没有正确的定位在地平面上,看起来有偏差,例如下图所示的柯林顿城堡,没有贴合上。
😖处女座忍不了一点。但是这题是有解的,我们可以通过修改模型矩阵modelMatrix来调整tileset的位置。
const heightOffset = 30;
await tileset.readyPromise;
// Position tileset
const boundingSphere = tileset.boundingSphere;
const cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
const surface = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
0.0
);
const offset = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
heightOffset
);
const translation = Cesium.Cartesian3.subtract(
offset,
surface,
new Cesium.Cartesian3()
);
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
八青妹这里设置的偏移量是30,依据不同的3D Tile可调试设置。这里的效果如下:
嗯,舒服了。