cesium实现键盘控制模型姿态变化效果


Cesium实战系列文章总目录传送门

1.实现效果

在这里插入图片描述

2.实现方法

参考官方沙盒示例:传送门

2.1实现思路

(1)加载模型
使用modelfromGltf方法加载模型,API:传送门
在这里插入图片描述

(2)设置变换矩阵
使用Tranforms类的headingPitchRollToFixedFrame方法设置模型的变化矩阵modelMatrix,API:传送门

姿态和位置变化后的模型转换到WGS84椭球的位置上。
在这里插入图片描述

(3)监听键盘事件
通过监听键盘事件来更改模型的姿态,键盘事件如下:

键盘事件
抬头
低头
左转
右转
0顺时针转
.逆时针转
+加速
-减速

(4)渲染更新前监听
监听scenepreUpdate事件,API:传送门

当事件发生时,更新模型的姿态和位置。
在这里插入图片描述

2.2具体代码

具体实现代码如下:

// 初始化viewer
const viewer = new Cesium.Viewer("cesiumContainer", {
    // 允许动画
    shouldAnimate: true,
});


// 设置相机初始位置
viewer.camera.setView({
    destination: {
        x: -2769293.799109788,
        y: 4796599.883886506,
        z: 3171113.878101777
    },
    orientation: {
        heading: 6.283185307179586,
        pitch: -0.7854060155492881,
        roll: 6.283185307179586
    }
})

let headingPitchRoll = new Cesium.HeadingPitchRoll();
// 模型初始位置
let position = new Cesium.Cartesian3.fromDegrees(120, 30, 5000);
// 局部变换坐标系
let fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator("north", "west");

// 每次操作姿态变化为5°
let deltaRadians = Cesium.Math.toRadians(5.0);


// 使用primitive方式加载模型
let airplaneModel = viewer.scene.primitives.add(
    Cesium.Model.fromGltf({
        url: '../.././icons/hz/model/airplane.glb',
        scale: 100.0,
        modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(
            position,
            headingPitchRoll,
            Cesium.Ellipsoid.WGS84,
            fixedFrameTransform
        ),
        minimumPixelSize: 256,
    }))


// 添加键盘监听事件
document.addEventListener('keydown', function(e) {
    switch (e.keyCode) {
        // 抬头
        case 38:
            headingPitchRoll.pitch += deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.pitch > Cesium.Math.TWO_PI) {
                headingPitchRoll.pitch -= Cesium.Math.TWO_PI;
            }
            console.log("抬头:pitch+");
            break;

        // 低头
        case 40:
            headingPitchRoll.pitch -= deltaRadians;
            if (headingPitchRoll.pitch < -Cesium.Math.TWO_PI) {
                headingPitchRoll.pitch += Cesium.Math.TWO_PI;
            }
            console.log("低头:pitch-");

            break;
            
        // 左转
        case 37:
            headingPitchRoll.heading -= deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.heading < -Cesium.Math.TWO_PI) {
                headingPitchRoll.heading += Cesium.Math.TWO_PI;
            }
            console.log("左转:heading+");
            break;
            
        // 右转
        case 39:
            headingPitchRoll.heading += deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.heading > Cesium.Math.TWO_PI) {
                headingPitchRoll.heading -= Cesium.Math.TWO_PI;
            }
            console.log("右转:heading-");
            break;
            
        // 顺时针
        case 96:
            headingPitchRoll.roll += deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.roll > Cesium.Math.TWO_PI) {
                headingPitchRoll.roll -= Cesium.Math.TWO_PI;
            }
            console.log("顺时针翻滚:roll+");
            break;
            
        // 逆时针
        case 110:
            headingPitchRoll.roll -= deltaRadians;
            // 判断是否超过2π范围
            if (headingPitchRoll.roll < -Cesium.Math.TWO_PI) {
                headingPitchRoll.roll += Cesium.Math.TWO_PI;
            }
            console.log("逆时针翻滚:roll-");
            break;
            
        // 加速
        case 107:
            speed += 10
            speed = Math.min(speed, 10000);
            console.log("加速:" + speed);
            break;
        // 减速
        case 109:
            speed -= 10;
            speed = Math.max(speed, 100);
            console.log("减速:" + speed);
            break;

        default:
            break;
    }
})

// 速度
let speed = 100;
// 速度向量
let speedVector = new Cesium.Cartesian3();

// 飞行路径
const pathPosition = new Cesium.SampledPositionProperty();
const entityPath = viewer.entities.add({
    position: pathPosition,
    name: "飞行路径",
    path: {
        show: true,
        leadTime: 0,
        trailTime: 60,
        width: 20,
        resolution: 1,
        material: new Cesium.PolylineGlowMaterialProperty({
            glowPower: 0.3,
            taperPower: 0.3,
            color: Cesium.Color.PALEGOLDENROD,
        }),
    },
});

// 渲染更新前阶段添加监听
viewer.scene.preUpdate.addEventListener(() => {
    speedVector = Cesium.Cartesian3.multiplyByScalar(
        Cesium.Cartesian3.UNIT_X,
        speed / 10,
        speedVector
    );
    position = Cesium.Matrix4.multiplyByPoint(
        airplaneModel.modelMatrix,
        speedVector,
        position
    );
    // 将点添加到路径中
    pathPosition.addSample(Cesium.JulianDate.now(), position);

	  // 更新模型姿态与位置
    Cesium.Transforms.headingPitchRollToFixedFrame(
        position,
        headingPitchRoll,
        Cesium.Ellipsoid.WGS84,
        fixedFrameTransform,
        airplaneModel.modelMatrix
    )
})
  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

右弦GISer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值