Cesium引入Three同步相机

原帖:https://blog.csdn.net/zhishiqu/article/details/79077883

源码:cesium-threejs-experiment

这个帖子讲述了如何在在Cesium引入Three,总结一下原理就是

  1. HTML中设置两个容器分别用于容纳Cesium与Three,且Three容器在Cesium容器下面,这样才能让Three产生的场景覆盖在Cesium上,并且禁用Three容器的鼠标事件,通过Cesium同步Three。
  2. 初始化Ceiusm,初始化Three(渲染器设置背景为透明,达成叠加效果),初始化物体并分别添加到各自的场景中
  3. 获取指定位置的坐标,将Three场景的坐标设置为指定位置的坐标,并设置朝向与top方向
  4. 关掉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); // 更新渲染
        }

猜你喜欢

转载自blog.csdn.net/oneKnow/article/details/100118580