From 7a99756fc6ae0b105378cbd22ca2105d3d28aec5 Mon Sep 17 00:00:00 2001 From: fukunee Date: Sat, 19 Sep 2026 14:58:04 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=B3=E9=94=AE=E7=8E=AF=E8=A7=86=EF=BC=9A?= =?UTF-8?q?=E5=B7=A6=E5=8F=B3=3D=E7=BA=AC=E5=BA=A6=E6=96=B9=E5=90=91?= =?UTF-8?q?=E5=80=BE=E5=80=92=EF=BC=8C=E4=B8=8A=E4=B8=8B=3D=E7=BB=8F?= =?UTF-8?q?=E5=BA=A6=E6=96=B9=E5=90=91=E5=80=BE=E5=80=92=EF=BC=8C=E5=BC=BA?= =?UTF-8?q?=E5=88=B6=E5=8C=97=E6=9C=9D=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/scene/CesiumGlobe.js | 43 +++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/scene/CesiumGlobe.js b/src/scene/CesiumGlobe.js index 6d7baee..a6003f5 100644 --- a/src/scene/CesiumGlobe.js +++ b/src/scene/CesiumGlobe.js @@ -372,6 +372,7 @@ export class CesiumGlobe { offset: new Cesium.Cartesian3(), upAxis: new Cesium.Cartesian3(), eastAxis: new Cesium.Cartesian3(), + northAxis: new Cesium.Cartesian3(), qAz: new Cesium.Quaternion(), qEl: new Cesium.Quaternion(), q: new Cesium.Quaternion(), @@ -379,7 +380,7 @@ export class CesiumGlobe { newOffset: new Cesium.Cartesian3(), newPos: new Cesium.Cartesian3(), dir: new Cesium.Cartesian3(), - upRot: new Cesium.Cartesian3(), + upProj: new Cesium.Cartesian3(), }; handler.setInputAction((movement) => { @@ -394,8 +395,8 @@ export class CesiumGlobe { if (!Cesium.defined(pivot)) return; const sc = this._orbitScratch; const offset = Cesium.Cartesian3.subtract(camera.position, pivot, sc.offset); - const upAxis = Cesium.Cartesian3.normalize(pivot, sc.upAxis); // 绕它转 = 左右旋转 - const eastAxis = Cesium.Cartesian3.cross(Cesium.Cartesian3.UNIT_Z, pivot, sc.eastAxis); // 绕它转 = 上下倾角 + const upAxis = Cesium.Cartesian3.normalize(pivot, sc.upAxis); + const eastAxis = Cesium.Cartesian3.cross(Cesium.Cartesian3.UNIT_Z, pivot, sc.eastAxis); // 绕它转 = 左右拖动(纬度方向倾倒) if (Cesium.Cartesian3.magnitudeSquared(eastAxis) < 1e-12) { eastAxis.x = 1; eastAxis.y = 0; @@ -403,11 +404,15 @@ export class CesiumGlobe { } else { Cesium.Cartesian3.normalize(eastAxis, eastAxis); } + const northAxis = Cesium.Cartesian3.normalize( + Cesium.Cartesian3.cross(upAxis, eastAxis, sc.northAxis), // 绕它转 = 上下拖动(经度方向倾倒) + sc.northAxis, + ); this._lookState = { pivot: Cesium.Cartesian3.clone(pivot), startOffset: Cesium.Cartesian3.clone(offset), - upAxis: Cesium.Cartesian3.clone(upAxis), eastAxis: Cesium.Cartesian3.clone(eastAxis), + northAxis: Cesium.Cartesian3.clone(northAxis), position: Cesium.Cartesian3.clone(camera.position), direction: Cesium.Cartesian3.clone(camera.direction), up: Cesium.Cartesian3.clone(camera.up), @@ -443,26 +448,36 @@ export class CesiumGlobe { this._lookHandler = handler; } - // 按累计角度(已限制)把相机绕点击点旋转;位置、朝向、up 一起做刚体旋转 + // 按累计角度(已限制)把相机绕点击点倾倒:左右 = 纬度方向(绕东西轴), + // 上下 = 经度方向(绕南北轴);up 始终强制北朝上。 _orbitCamera(s) { const camera = this.viewer.camera; const sc = this._orbitScratch; - Cesium.Quaternion.fromAxisAngle(s.upAxis, s.azimuth, sc.qAz); - Cesium.Quaternion.fromAxisAngle(s.eastAxis, s.elevation, sc.qEl); + Cesium.Quaternion.fromAxisAngle(s.eastAxis, s.azimuth, sc.qAz); + Cesium.Quaternion.fromAxisAngle(s.northAxis, s.elevation, sc.qEl); Cesium.Quaternion.multiply(sc.qEl, sc.qAz, sc.q); Cesium.Matrix3.fromQuaternion(sc.q, sc.rotMat); Cesium.Matrix3.multiplyByVector(sc.rotMat, s.startOffset, sc.newOffset); Cesium.Cartesian3.add(s.pivot, sc.newOffset, sc.newPos); - // up 不强制北朝上,与方向一起旋转(否则左右拽缺少 roll 分量,表现异常) - Cesium.Matrix3.multiplyByVector(sc.rotMat, s.direction, sc.dir); - Cesium.Cartesian3.normalize(sc.dir, sc.dir); - Cesium.Matrix3.multiplyByVector(sc.rotMat, s.up, sc.upRot); - Cesium.Cartesian3.normalize(sc.upRot, sc.upRot); + const dir = Cesium.Cartesian3.normalize( + Cesium.Cartesian3.subtract(s.pivot, sc.newPos, sc.dir), + sc.dir, + ); + // 强制北朝上:up = 世界 Z 投影到垂直于视线的方向 + const z = dir.z; + sc.upProj.x = -dir.x * z; + sc.upProj.y = -dir.y * z; + sc.upProj.z = 1 - z * z; + if (Cesium.Cartesian3.magnitudeSquared(sc.upProj) < 1e-12) { + Cesium.Cartesian3.clone(s.up, sc.upProj); // 垂直俯视时北朝上无定义,回退起始 up + } else { + Cesium.Cartesian3.normalize(sc.upProj, sc.upProj); + } camera.setView({ destination: Cesium.Cartesian3.clone(sc.newPos), orientation: { - direction: Cesium.Cartesian3.clone(sc.dir), - up: Cesium.Cartesian3.clone(sc.upRot), + direction: Cesium.Cartesian3.clone(dir), + up: Cesium.Cartesian3.clone(sc.upProj), }, }); }