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