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); // 更新渲染
        }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章