Cesium 实战教程 - 三种方式(CZML、nodeTransformations)修改模型节点组件属性(比例、旋转、移动等)
- 核心代码
- 完整代码
- 在线示例
关于 Cesium 设置模型组件的动作,之前是通过 CZML + articulations
来实现的,最近在官网发现一个示例,可以直接操作模型的 node
节点,来实现模型组件的动作。
本文介绍几种给模型组件设置动作的方法,包括 CZML articulations
、CZML nodeTransformations
以及代码(model.nodeTransformations
) 实现模型动作。
三种设置方式,效果是一致的,但是操作难度略有差别。
CZML articulations 需要先给模型添加自定义的关节动作,才可以通过代码来实现动作。
CZML nodeTransformations 相对比较方便,只需要知道节点(node)名称就可以实现动作,只是设置参数略有不同。
model.nodeTransformations 完全是由代码来实现的,比较自由,但是需要对相关代码比较熟悉。
三种方式各有优势,使用哪种,取决于项目需求。
本文包含核心代码、完整代码以及在线示例三部分。
核心代码
1. CZML articulations 关节动作
// 自定义动作,需要模型存在自定义关节属性
"articulations": {// 导弹组件向前移动// MoveZ 为 glTF 中自定义的关节名称"missiles MoveZ": {// 开始移动时刻"epoch": "2023-06-14T10:10:00Z",// 设置移动参数"number": [// 当前 epoch 时刻,第 0 秒的时,Z 轴移动的距离(米)0, 0,// 当前 epoch 时刻,第 300 秒的时,Z 轴移动的距离(米)// 与模型行进方向相反300, -60]},
}
详情请参考:Cesium 实战 - AGI_articulations 扩展:模型自定义关节动作
2. CZML nodeTransformations 实现节点动作
// 设置火焰显示隐藏
"nodeTransformations": {"SRB_Flame4": {// 旋转(按照模型设置的中心点)"scale": {"epoch": "2023-06-14T10:00:20Z",// 设置时刻与比例// 0 比例表示隐藏,1 比例表示显示"cartesian": [// 0 秒、x 比例、y 比例、z 比例0.0, 0, 0, 0,// 5 秒、x 比例、y 比例、z 比例5.0, 1.0, 1.0, 1.0,800.0, 1.0, 1.0, 1.0,1600.0, 1.0, 1.0, 1.0,],// nextTime: 500,},},
}
2. model.nodeTransformations 代码实现动作
// 获取模型实体const entity = dataSource.entities.getById("Vulcan");// 模型视角跟随viewer.trackedEntity = entity;console.log(entity.model.nodeTransformations);// 定义比例节点转换,用于显示隐藏const transformation = new Cesium.NodeTransformationProperty({scale: new Cesium.Cartesian3(1.0, 1.0, 1.0)});// 记录当前时间const current = viewer.clock.currentTime.secondsOfDay;// 模型实体添加节点控制entity.model.nodeTransformations.addProperty('SRB_Flame2', transformation);// 时间轴监听事件let onTickEvent;// 时间轴监听回调function adjust() {// 200 秒后隐藏 SRB_Flame2 组件if (viewer.clock.currentTime.secondsOfDay > current + 200) {const transformation = new Cesium.NodeTransformationProperty({scale: new Cesium.Cartesian3(0.0, 0.0, 0.0)});entity.model.nodeTransformations.SRB_Flame2 = transformation;onTickEvent();}}onTickEvent = viewer.clock.onTick.addEventListener(adjust);// 设置观察角度
entity.viewFrom = new Cesium.Cartesian3(-1000, 100,-1000);
完整代码
<style>@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar"><span><h2>请调整至合适视角!<h4/><br/>开始阶段:SRB_Flame2 (通过 model.nodeTransformations 控制)尾焰开启<br/><br/>和 BoosterFlames (通过 czml articulations控制)尾焰开启!<br/><br/>viewer时钟 100 秒之后,BoosterFlames 尾焰关闭,<br/><br/>SRB_Flame4 和 SRB_Flame6(通过 czml nodeTransformations 控制) 开启!<br/><br/></span>
</div>
// 火箭模拟发射数据
const czml = [{"id": "document","name": "SpaceX","version": "1.0","clock": {"interval": "2023-06-14T10:00:00Z/2023-06-14T10:17:33Z","currentTime": "2023-06-14T10:00:00Z","multiplier": 10,"range": "CLAMPED","step": "SYSTEM_CLOCK_MULTIPLIER"}},{"id": "Vulcan","availability": "2023-06-14T10:00:00Z/2023-06-14T10:17:33Z","name": "Vulcan","billboard": {"show": true,"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAjSURBVChTYyAa/EcDUGEIgIphAKg0XRSAAFQMDqDChAADAwDC13+BJ+0oDwAAAABJRU5ErkJgggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==","scale": 1,"pixelOffset": {"cartesian2": [0, 0]},"eyeOffset": {"cartesian": [0, 0, 0]},"horizontalOrigin": "CENTER","verticalOrigin": "CENTER","color": [{"interval": "2023-06-14T10:00:00Z/2023-06-14T10:10:00Z","rgba": [0, 255, 0, 255]},{"interval": "2023-06-14T10:10:00Z/2023-06-14T10:13:20Z","rgba": [255, 255, 0, 255]},{"interval": "2023-06-14T10:13:20Z/9999-12-31T23:59:59.9999999Z","rgba": [255, 0, 255, 255]}]},"label": {"show": false,"text": "Vulcan","font": "21pt Lucida Console","style": "FILL_AND_OUTLINE","scale": 0.5,"pixelOffset": {"cartesian2": [5, -4]},"horizontalOrigin": "LEFT","verticalOrigin": "CENTER","fillColor": [{"interval": "2023-06-14T10:00:00Z/2023-06-14T10:10:00Z","rgba": [0, 255, 0, 255]},{"interval": "2023-06-14T10:10:00Z/2023-06-14T10:13:20Z","rgba": [255, 255, 0, 255]},{"interval": "2023-06-14T10:13:20Z/9999-12-31T23:59:59.9999999Z","rgba": [255, 0, 255, 255]}],"outlineColor": {"rgba": [0, 0, 0, 255]},"outlineWidth": 2},"path": {"show": [{"interval": "2023-06-14T10:00:00Z/2023-06-14T10:17:33Z","boolean": true}],"width": 5,"resolution": 1,"leadTime": [{"interval": "2023-06-14T10:00:00Z/2023-06-14T10:17:33Z","epoch": "2023-06-14T10:00:00Z","number": [0, 1053,1053, 0]}],"trailTime": [{"interval": "2023-06-14T10:00:00Z/2023-06-14T10:17:33Z","epoch": "2023-06-14T10:00:00Z","number": [0, 0,1053, 1053]}],"material": {polylineGlow: {color: [{"interval": "2023-06-14T10:00:00Z/2023-06-14T10:10:00Z",rgba: [255, 0, 0, 255],},{"interval": "2023-06-14T10:10:00Z/2023-06-14T10:13:20Z",rgba: [0, 0, 255, 255],},{"interval": "2023-06-14T10:13:20Z/9999-12-31T23:59:59.9999999Z",rgba: [255, 0, 255, 255],}],glowPower: 0.25,// taperPower: 0.5,},},},"model": {"show": true,"gltf": [{"interval": "2023-06-14T10:00:00Z/9999-12-31T23:59:59.9999999Z","uri": "https://cesium.com/public/SandcastleSampleData/launchvehicle.glb"}],"minimumPixelSize": 512,"scale": 15,"runAnimations": false,// 自定义的关节动作设置火焰"articulations": {// 火箭中间火焰"BoosterFlames Size": {"epoch": "2023-06-14T10:00:00Z","number": [0, 1,49, 1,50, 0,9999, 0]},},// nodeTransformations 设置火焰显示隐藏"nodeTransformations": {// 第六个火焰节点名称"SRB_Flame6": {// 比例(按照模型设置的中心点)"scale": {"epoch": "2023-06-14T10:00:00Z","cartesian": [0.0, 0, 0, 0,120.0, 0, 0, 0,121.0, 1.0, 1.0, 1.0,200.0, 1.0, 1.0, 1.0,],},},// 第五个火焰节点名称"SRB_Flame4": {// 比例(按照模型设置的中心点)"scale": {"epoch": "2023-06-14T10:00:00Z","cartesian": [0.0, 0, 0, 0,150.0, 0, 0, 0,151.0, 1.0, 1.0, 1.0,200.0, 1.0, 1.0, 1.0,],},},},},"position": {"interpolationAlgorithm": "LAGRANGE","interpolationDegree": 2,"referenceFrame": "FIXED","epoch": "2023-06-14T10:00:00Z","cartesian": [0.000, -2174195.199042614, 4389988.019058515, 4070606.7900844226,250.000, -2828836.74243954, 4527941.384141082, 4322899.592600973,750.000, -3812052.7676919936, 3910960.7948377975, 4168079.0591541207,1053.000, -3929362.40133975, 3277792.786767426, 3795371.463871257,]},"orientation": {"velocityReference": "#position"},},
];const viewer = new Cesium.Viewer("cesiumContainer", {shouldAnimate: true,
});const dataSourcePromise = viewer.dataSources.add(Cesium.CzmlDataSource.load(czml)
);dataSourcePromise.then(function (dataSource) {// 获取模型实体const entity = dataSource.entities.getById("Vulcan");// 模型视角跟随viewer.trackedEntity = entity;console.log(entity.model.nodeTransformations);// 定义比例节点转换,用于显示隐藏const transformation = new Cesium.NodeTransformationProperty({scale: new Cesium.Cartesian3(1.0, 1.0, 1.0)});// 记录当前时间const current = viewer.clock.currentTime.secondsOfDay;// 模型实体添加节点控制entity.model.nodeTransformations.addProperty('SRB_Flame2', transformation);// 时间轴监听事件let onTickEvent;// 时间轴监听回调function adjust() {// 200 秒后隐藏 SRB_Flame2 组件if (viewer.clock.currentTime.secondsOfDay > current + 100) {console.log('SRB_Flame2 尾焰关闭!');// 重新定义火焰比例const transformation = new Cesium.NodeTransformationProperty({scale: new Cesium.Cartesian3(0.0, 0.0, 0.0)});entity.model.nodeTransformations.SRB_Flame2 = transformation;onTickEvent();}}onTickEvent = viewer.clock.onTick.addEventListener(adjust);// 设置观察角度entity.viewFrom = new Cesium.Cartesian3(-1000, 100,-1000);}).catch(function (error) {console.error(error);});
在线示例
三种方式(CZML、nodeTransformations)修改模型节点组件属性(修改比例、旋转、移动等)
参考博客:
[1]: 【Cesium】计算模型的朝向四元数,实现模型运动中调整朝向
[2]: czml api
[3]: CZML Model - Node Transformations.html
[4]: Transformations 代码设置节点旋转
[5]: cesium-CZML描述动态场景