大家好,我是日拱一卒的
攻城师不浪
,致力于前沿科技探索,摸索小而美工作室,这是2025年输出的第53/100篇原创文章。
效果预览
www.bilibili.com/video/BV1wf...
在三维领域,模型动画控制是提升交互体验和仿真效果的关键技术。今天我们来聊下Cesium
中如何实现对GLTF
模型的精确动画控制,以起重机模型为例,展示如何通过键盘交互实现模型各部件的旋转和伸缩动作,打造沉浸式的三维交互体验。
功能概述
主要是通过键盘按键对GLTF
模型的精确控制,包括:
-
通过
A/D
键控制起重机驾驶舱的水平旋转 -
通过
W/S
键控制起重臂的俯仰 -
通过
Q/E
键控制钩子的伸缩
应用场景
-
工业仿真与培训:通过精确控制工程机械模型,可以构建操作培训系统,帮助操作人员熟悉设备操作逻辑,降低实操风险。这在起重机、挖掘机、装载机等大型设备培训中尤为有价值。
-
智慧建筑与城市规划:在建筑设计和城市规划中,可以通过模型控制模拟建筑组件的活动,如电梯运行、门窗开合、机械设备操作等,为设计评审和方案汇报提供直观的交互式演示。
-
数字孪生应用:结合物联网数据,可以实现物理设备与数字模型的联动,构建数字孪生应用。例如,实时展示工厂设备的运行状态,或通过虚拟模型控制实际设备的操作。
-
教育与科普:在教育领域,可以通过交互式模型演示复杂机械的工作原理,帮助学生理解机械工程基本概念,增强学习兴趣和效果。
技术原理
核心是对GLTF
模型节点 的矩阵 进行操控,GLTF
模型一般都是由多个节点组成,每个节点对应模型的一个部件。

通过对特定节点应用变换矩阵,可以控制该部件的位置、旋转和缩放。
代码实现
节点获取
javascript
let gltfModel = null;
let node, node1, node2, node3, node0, node5;
const addGltf = async () => {
// 加载GLTF模型
gltfModel = await Cesium.Model.fromGltfAsync({
url: "/models/crane.glb",
minimumPixelSize: 80,
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(120.1536, 36.2875, 0)),
});
__viewer.scene.primitives.add(gltfModel);
// 模型加载完成后获取关键节点
gltfModel.readyEvent.addEventListener(() => {
// 定位到模型
const boundingSphere = gltfModel.boundingSphere;
__viewer.camera.flyToBoundingSphere(boundingSphere, {
duration: 1,
});
// 获取关键节点
node1 = gltfModel.getNode("node_Ctrl_Spin02_-1362"); // 驾驶舱水平旋转控制节点
node = gltfModel.getNode("node_Ctrl_Spin01_-1378"); // 起重臂控制节点
node2 = gltfModel.getNode("node_Dummy005_-1380"); // 臂部辅助节点
node3 = gltfModel.getNode("node_Dummy006_-1454"); // 臂部辅助节点
node0 = gltfModel.getNode("node_Bone006_-1438"); // 钩子节点
node5 = gltfModel.getNode("node_Bone007_-1434"); // 钩子伸缩节点
});
};
通过fromGltfAsync
方法异步加载GLTF
模型,并在模型加载完成后获取控制动画所需的关键节点。
这里可能会有人问:我怎么确定每个节点的名称?
这里给大家推荐一个查看gltf模型的网站 ONLINE 3D VIEWER
:3dviewer.bimant.com/ ,可以清晰的看到每个节点的属性名称以及父子节点之间的树状关系图。

计算世界坐标函数
javascript
/**
* 计算世界坐标
*/
const computeModelPosition = (name) => {
const node = gltfModel._nodesByName[name];
const m = Cesium.Matrix4.clone(Cesium.Matrix4.IDENTITY);
Cesium.Matrix4.multiply(node.matrix, node._runtimeNode.transformToRoot, m);
// 获取矩阵平移后的位置
const position = Cesium.Matrix4.getTranslation(m, new Cesium.Cartesian3());
return position;
};
这个函数用于计算模型节点在世界坐标系中的位置,是实现精确控制的关键。通过矩阵乘法将节点的局部变换与根节点的变换结合,得到节点在世界坐标系中的确切位置。
驾驶舱水平旋转
其实只要学会了一个节点的控制,其它的节点,我们只要确定好对应的中心轴,操作原理就是一样的。因此我们来看下驾驶舱水平旋转的操作动画控制。

javascript
const rotateZ = (angle) => {
if (!node1) {
throw new Error("node1 尚未初始化");
}
const modelMatrix = node1.matrix;
const rotation = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(angle));
node1.matrix = Cesium.Matrix4.multiplyByMatrix3(modelMatrix, rotation, modelMatrix);
}
吊钩伸缩动画

其次是起重机挂钩的上下伸缩的动画,这里我们应该使用模型的局部坐标系进行中心轴选择,这个是由建模的时候,模型师所设定的,所以我们不能用世界坐标系去判断,因此这里要注意一下。
我们使用Matrix4.multiplyByTranslation
平移变换到节点矩阵,在节点的局部坐标系中进行平移
js
let l = 0
function stretch(length) {
l += length;
if (l > 0) {
l = 0;
return;
}
node5.matrix = Cesium.Matrix4.multiplyByTranslation(
node5.matrix,
new Cesium.Cartesian3(length, 0, 0),
node5.matrix
);
}
stretch(-1) // 下移
stretch(1) // 上移
最后
希望通过今天的介绍,能为大家在Cesium
中实现模型动画控制提供一些思路和参考。
将来,我们还可以通过做一些优化和提升,例如:
-
结合物理引擎实现更逼真的模型动力学表现
-
通过VR/AR技术提供更沉浸式的交互体验
-
融合AI技术实现更智能的模型控制逻辑
想系统学习Cesium的小伙伴儿,可以了解下不浪的教程
《Cesium从入门到实战》
,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市
的完整项目,关注公众号:攻城师不浪,即可获取教程介绍,也可+作者:brown_7778(备注来意)。
有需要进可视化&Webgis交流群
可以加我:brown_7778(备注来意)。