欢迎转载,转载需带着文章出处链接~~,希望我的经验能帮到你,有问题可以点我头像加我微信
本文章仅对遇到的问题提供一个解决思路,对于迫切想要实现功能效果的人来说,希望能稍微沉下心观看,或者直接观看思路部分,或者直接观看完整代码
本文章的代码并不能直接拿来使用,完整代码只是本篇文章解决的问题需要用到的代码,如果直接使用可能会有报错,只要修改一下代码既可使用~~~
Cesiumjs+Threejs开发,解决模型在地球背面显示的问题
模型在地球背面时,本应该隐藏的模型,此时正在显示。
-参考-
CesiumJs+ThreeJs实测 cesium与three.js,解决three.js 高版本模型出不来的问题 CesiumJs获取中心坐标
-说明-
为什么出现了问题?
① Cesiumjs和Threejs集成的原理,通过定位两个DOM节点,使两个DOM重叠,将Threejs放到Cesiumjs上。
② 局部查看,Threejs的Mesh显示在对应的位置上。
③ 转动视角后,在地球背面本应该消失的模型,因为没有物体遮挡,所以模型还存在,出现了BUG。
-主要版本-
three.js r123,不仅限于这个版本 cesium.js 1.76,不仅限于这个版本
-思路-
1、查找代码相关位置 2、将Pointer替换为Mouse 3、event.pointerType无法获取,故直接跳过这步,将里边的方法拿出来
-过程-
1、Cesium和Three集成
官方给出的cesium和threejs结合的方案,在这里将对loop代码进行规整,代码如下所示。
function loop() {
requestAnimationFrame(loop); //loop
renderCesium(); //渲染cesium
renderThree(); //渲染three
renderCamera(); // 视角调整
}
2、获取中心点坐标
在renderCamera视角调整代码处,修改增加获取当前视角下中心坐标点的代码,这里代码写成2部分,方便代码观看,callback回调在步骤3。
// 处理三维模型显示隐藏问题
function getCenterPosition(callback) {
var viewer = cesium.viewer;
var result = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas
.clientHeight / 2));
var curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(result);
var lon = curPosition.longitude * 180 / Math.PI;
var lat = curPosition.latitude * 180 / Math.PI;
var height = getHeight(); // 获取高度
var now = getCurrentExtent(); // 获取当前视角下的经纬度的范围
callback(lon,lat,height,now);
return {
lon: lon,
lat: lat,
height: height
};
}
3、动态修改Threejs模型显隐
在renderCamera视角调整代码处,调用该方法,对模型进行显示隐藏处理
getCenterPosition((lon, lat, height, now) => {
let hei = now.height;
// 地球背面模型隐藏
for (let k in modelDict) {
let item = modelDict[k];
var pos = item.getPosition();
let lon1 = pos.lon;
let lat1 = pos.lat;
let hei1 = pos.hei;
if (Math.abs(lon1 - lon) > 300) {
if (lon1 < 0) {
lon1 += 360
} else {
lon += 360
}
}
if (Math.abs(lon1 - lon) > 90 + hei1 / 100000 || Math.abs(lat1 - lat) > 60) {
item.setVisible(false);
} else {
item.setVisible(true);
}
// 优化显示
if (hei - hei1 < 2000000 && Math.abs(lon - lon1) < 6 && Math.abs(lat - lat1) < 6) {
item.setVisible(true);
} else {
item.setVisible(false);
}
}
});
-完整代码-
function loop() {
requestAnimationFrame(loop);
renderCesium(); //渲染cesium
renderThree(); //渲染three
renderCamera();
// nowDate += 1000 * 60
// var utc=Cesium.JulianDate.fromDate(new Date(nowDate)); // 获取当前时间
// cesium.viewer.clockViewModel.currentTime = Cesium.JulianDate.addHours(utc,0,new Cesium.JulianDate()); // 设置时间,第二个是时差
}
function renderCesium() {
cesium.viewer.render();
}
function renderThree() {
var width = ThreeContainer.clientWidth;
var height = ThreeContainer.clientHeight;
three.renderer.setSize(width, height);
three.renderer.render(three.scene, three.camera);
}
function renderCamera() {
// register Three.js scene with Cesium
three.camera.fov = Cesium.Math.toDegrees(cesium.viewer.camera.frustum.fovy) // ThreeJS FOV is vertical
three.camera.updateProjectionMatrix();
// Clone Cesium Camera projection position so the
// Three.js Object will appear to be at the same place as above the Cesium Globe
three.camera.matrixAutoUpdate = false;
var cvm = cesium.viewer.camera.viewMatrix;
var civm = cesium.viewer.camera.inverseViewMatrix;
three.camera.lookAt(new THREE.Vector3(0, 0, 0));
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();
getCenterPosition((lon, lat, height, now) => {
let hei = now.height;
// 地球背面模型隐藏
for (let k in modelDict) {
let item = modelDict[k];
var pos = item.getPosition();
let lon1 = pos.lon;
let lat1 = pos.lat;
let hei1 = pos.hei;
if (Math.abs(lon1 - lon) > 300) {
if (lon1 < 0) {
lon1 += 360
} else {
lon += 360
}
}
if (Math.abs(lon1 - lon) > 90 + hei1 / 100000 || Math.abs(lat1 - lat) > 60) {
item.setVisible(false);
} else {
item.setVisible(true);
}
// 优化显示
if (hei - hei1 < 2000000 && Math.abs(lon - lon1) < 6 && Math.abs(lat - lat1) < 6) {
item.setVisible(true);
} else {
item.setVisible(false);
}
}
});
}
// 处理三维模型显示隐藏问题
function getCenterPosition(callback) {
var viewer = cesium.viewer;
var result = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas
.clientHeight / 2));
var curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(result);
var lon = curPosition.longitude * 180 / Math.PI;
var lat = curPosition.latitude * 180 / Math.PI;
var height = getHeight();
var now = getCurrentExtent();
callback(lon,lat,height,now);
return {
lon: lon,
lat: lat,
height: height
};
}
/* 获取camera高度 */
function getHeight() {
var viewer = cesium.viewer;
if (viewer) {
var scene = viewer.scene;
var ellipsoid = scene.globe.ellipsoid;
var height = ellipsoid.cartesianToCartographic(viewer.camera.position).height;
return height;
}
}
function getCurrentExtent() {
// 范围对象
var extent = {};
// 得到当前三维场景
var viewer = cesium.viewer;
var scene = viewer.scene;
// 得到当前三维场景的椭球体
var ellipsoid = scene.globe.ellipsoid;
var canvas = scene.canvas;
// canvas左上角
var car3_lt = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, 0), ellipsoid);
// canvas右下角
var car3_rb = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(canvas.width, canvas.height), ellipsoid);
// 当canvas左上角和右下角全部在椭球体上
if (car3_lt && car3_rb) {
var carto_lt = ellipsoid.cartesianToCartographic(car3_lt);
var carto_rb = ellipsoid.cartesianToCartographic(car3_rb);
extent.xmin = Cesium.Math.toDegrees(carto_lt.longitude);
extent.ymax = Cesium.Math.toDegrees(carto_lt.latitude);
extent.xmax = Cesium.Math.toDegrees(carto_rb.longitude);
extent.ymin = Cesium.Math.toDegrees(carto_rb.latitude);
}
// 当canvas左上角不在但右下角在椭球体上
else if (!car3_lt && car3_rb) {
var car3_lt2 = null;
var yIndex = 0;
do {
// 这里每次10像素递加,一是10像素相差不大,二是为了提高程序运行效率
yIndex <= canvas.height ? yIndex += 10 : canvas.height;
car3_lt2 = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, yIndex), ellipsoid);
} while (!car3_lt2);
var carto_lt2 = ellipsoid.cartesianToCartographic(car3_lt2);
var carto_rb2 = ellipsoid.cartesianToCartographic(car3_rb);
extent.xmin = Cesium.Math.toDegrees(carto_lt2.longitude);
extent.ymax = Cesium.Math.toDegrees(carto_lt2.latitude);
extent.xmax = Cesium.Math.toDegrees(carto_rb2.longitude);
extent.ymin = Cesium.Math.toDegrees(carto_rb2.latitude);
}
// 获取高度
extent.height = Math.ceil(viewer.camera.positionCartographic.height);
return extent;
}