原帖:https://blog.csdn.net/zhishiqu/article/details/79077883
源码:cesium-threejs-experiment
这个帖子讲述了如何在在Cesium引入Three,总结一下原理就是
- HTML中设置两个容器分别用于容纳Cesium与Three,且Three容器在Cesium容器下面,这样才能让Three产生的场景覆盖在Cesium上,并且禁用Three容器的鼠标事件,通过Cesium同步Three。
- 初始化Ceiusm,初始化Three(渲染器设置背景为透明,达成叠加效果),初始化物体并分别添加到各自的场景中
- 获取指定位置的坐标,将Three场景的坐标设置为指定位置的坐标,并设置朝向与top方向
- 关掉Three相机的自动更行,复制Cesium相机的fov与matrix并赋值给Three相机,更新Three相机,Cesium+Three同步
注意点
一、原帖中采用的Three源码为r87版本,基于原版本可以正常运行,如果切换为r87后的版本则会发现没有报错但是Cesium正常显示但是Three模型显示不出的问题
解决方案:r87版本中的object3D函数的lookAt方法的形参是vector3,后续版本的lookAt方法的形参是将vector3拆分成三个参数传入,所以更换为后续版本需要把源码中的lookat方法的实参进行改变才能正确显示。
二、Cesium与Three正常加载后,Cesium地图闪烁
解决方案:这个问题可能是因为Ceiusm与Three刷新不同步导致的,在项目中更新Cesium版本后未发现有闪烁现象,所以推测可能更新Cesium版本可以解决。
核心代码
// 核心方法
function renderThreeObj() {
// register Three.js scene with Cesium
three.camera.fov = Cesium.Math.toDegrees(cesium.viewer.camera.frustum.fovy) // 获取cesium相机角度并赋值给Three
three.camera.updateProjectionMatrix();
// 笛卡尔转矢量
var cartToVec = function (cart) {
return new THREE.Vector3(cart.x, cart.y, cart.z);
};
// 物体位置调整
for (var id in _3Dobjects) {
minWGS84 = _3Dobjects[id].minWGS84;
maxWGS84 = _3Dobjects[id].maxWGS84;
// 物体中心点坐标
var center = Cesium.Cartesian3.fromDegrees((minWGS84[0] + maxWGS84[0]) / 2, (minWGS84[1] + maxWGS84[1]) / 2);
// 物体顶部朝向坐标
var centerHigh = Cesium.Cartesian3.fromDegrees((minWGS84[0] + maxWGS84[0]) / 2, (minWGS84[1] + maxWGS84[1]) / 2, 1);
// y轴朝向
var bottomLeft = cartToVec(Cesium.Cartesian3.fromDegrees(minWGS84[0], minWGS84[1])); // 指定平面左下角
var topLeft = cartToVec(Cesium.Cartesian3.fromDegrees(minWGS84[0], maxWGS84[1])); // 指定平面左上角
var latDir = new THREE.Vector3().subVectors(bottomLeft, topLeft).normalize(); // 指定平面左边向量
// 物体位置调整
_3Dobjects[id].threeMesh.position.copy(center); // 物体position更正
_3Dobjects[id].threeMesh.lookAt(centerHigh.x, centerHigh.y, centerHigh.z); // z轴方向,即上方向,lookAt改传三个参数
_3Dobjects[id].threeMesh.up.copy(latDir); //指定y轴的朝向与平面左边平行,即模型朝向与平面左边朝向相同
}
//关闭相机自动更新
three.camera.matrixAutoUpdate = false;
// cesium相机位置
var cvm = cesium.viewer.camera.viewMatrix;
var civm = cesium.viewer.camera.inverseViewMatrix;
// 同步Three相机位置设置
three.camera.matrixWorld.set(
civm[0], civm[4], civm[8], civm[12],
civm[1], civm[5], civm[9], civm[13],
civm[2], civm[6], civm[10], civm[14],
civm[3], civm[7], civm[11], civm[15]
);
three.camera.matrixWorldInverse.set(
cvm[0], cvm[4], cvm[8], cvm[12],
cvm[1], cvm[5], cvm[9], cvm[13],
cvm[2], cvm[6], cvm[10], cvm[14],
cvm[3], cvm[7], cvm[11], cvm[15]
);
// 相机设置参数
var width = ThreeContainer.clientWidth;
var height = ThreeContainer.clientHeight;
var aspect = width / height;
three.camera.aspect = aspect;
three.camera.updateProjectionMatrix(); // 相机参数更新
// 渲染尺寸
three.renderer.setSize(window.innerWidth, window.innerHeight);
three.renderer.render(three.scene, three.camera); // 更新渲染
}