作为三维项目,以第一人称视角漫游是比较常见的需求,而 Cesium 默认是不带此功能,因此需要自己实现。
在网上几乎没有发现完整的实现示例,大多都是部分代码或者提供思路,经研究,终于实现功能,这里记录一下。
本文包括实现思路、核心代码以及在线示例三部分。
在最开始的时候,作者以为官方会有类似于 viewer.trackedEntity = entity;
的方法来实现第一人称视角,结果找半天并没有发现。
后来,想的是通过 viewer.camera.setView
和 viewer.camera.lookAtTransform
之类的方式实现,结果尝试很多次并没有成功。
viewer.camera.lookAtTransform
也可以实现固定视角,但是没找到如何改变仰角,效果不太好,因此放弃。
最后改变思路,尝试实时监听飞行状态,通过 viewer.camera.lookAt
动态修改视角,实现第一人称视角飞行。
在调整模型角度的时候,因网上的碎片代码,并没有完美设置模型的方向与姿态,稍微花了点时间调整。
完成第一视角跟随之后,还需要取消跟随,按照常规来说,有绑定就应该有解绑。
通过 onTickEvent = viewer.clock.onTick.addEventListener
绑定,作者认为是 viewer.clock.onTick.removeEventListener
,结果发现直接调用一次方法也可以,这样更省事:onTickEvent()
。
至此,第一视角跟随功能已可以完全实现!
这里贴上核心代码,具体解释详见注释信息。
// 获取当前模型方向和位置
// entityB2 为模型对象
const orientation = entityB2.orientation;
const position = entityB2.position;// 实时调整位置
function adjust() {if (viewer.clock.shouldAnimate === true) {// 获取偏向角let ori = orientation.getValue(viewer.clock.currentTime); // 获取位置let center = position.getValue(viewer.clock.currentTime);// 1、由四元数计算三维旋转矩阵var mtx3 = Cesium.Matrix3.fromQuaternion(ori);// 2、计算四维转换矩阵:var mtx4 = Cesium.Matrix4.fromRotationTranslation(mtx3, center);// 3、计算角度:var hpr = Cesium.Transforms.fixedFrameToHeadingPitchRoll(mtx4);// 获取角度(弧度)const headingTemp = hpr.heading;const pitchTemp = hpr.pitch;// 调整角度为第一人称,注意调整的角度const heading = Cesium.Math.toRadians(Cesium.Math.toDegrees(headingTemp) + 90);const pitch = Cesium.Math.toRadians(Cesium.Math.toDegrees(pitchTemp) - 12);// 视角高度,根据模型大小调整const range = 140.0;// 动态改变模型视角viewer.camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, range));}
}onTickEvent = viewer.clock.onTick.addEventListener(adjust);setTimeout(function (){alert('您现在可以拖动了!');// 关闭视角跟随onTickEvent && onTickEvent();
},10000);
示例中展示了, 三维地图第一人称飞行。
在线示例中,使用的官方模型,有需要 B2 轰炸机模型的可以 点击下载。
Cesium 沙盒测试
三维地图第一人称飞行
参考博客:
Cesium中的相机—setView&lookAtTransform
cesium飞行第一视角
Cesium 设置entity的姿态及获取entity的hpr(仰俯角、偏转角、翻滚角)
如何在Cesium中停用onTick方法