右键环视:左右=纬度方向倾倒,上下=经度方向倾倒,强制北朝上

This commit is contained in:
2026-09-19 14:58:04 +08:00
parent 0357bb0fb1
commit 7a99756fc6
+29 -14
View File
@@ -372,6 +372,7 @@ export class CesiumGlobe {
offset: new Cesium.Cartesian3(), offset: new Cesium.Cartesian3(),
upAxis: new Cesium.Cartesian3(), upAxis: new Cesium.Cartesian3(),
eastAxis: new Cesium.Cartesian3(), eastAxis: new Cesium.Cartesian3(),
northAxis: new Cesium.Cartesian3(),
qAz: new Cesium.Quaternion(), qAz: new Cesium.Quaternion(),
qEl: new Cesium.Quaternion(), qEl: new Cesium.Quaternion(),
q: new Cesium.Quaternion(), q: new Cesium.Quaternion(),
@@ -379,7 +380,7 @@ export class CesiumGlobe {
newOffset: new Cesium.Cartesian3(), newOffset: new Cesium.Cartesian3(),
newPos: new Cesium.Cartesian3(), newPos: new Cesium.Cartesian3(),
dir: new Cesium.Cartesian3(), dir: new Cesium.Cartesian3(),
upRot: new Cesium.Cartesian3(), upProj: new Cesium.Cartesian3(),
}; };
handler.setInputAction((movement) => { handler.setInputAction((movement) => {
@@ -394,8 +395,8 @@ export class CesiumGlobe {
if (!Cesium.defined(pivot)) return; if (!Cesium.defined(pivot)) return;
const sc = this._orbitScratch; const sc = this._orbitScratch;
const offset = Cesium.Cartesian3.subtract(camera.position, pivot, sc.offset); const offset = Cesium.Cartesian3.subtract(camera.position, pivot, sc.offset);
const upAxis = Cesium.Cartesian3.normalize(pivot, sc.upAxis); // 绕它转 = 左右旋转 const upAxis = Cesium.Cartesian3.normalize(pivot, sc.upAxis);
const eastAxis = Cesium.Cartesian3.cross(Cesium.Cartesian3.UNIT_Z, pivot, sc.eastAxis); // 绕它转 = 上下倾角 const eastAxis = Cesium.Cartesian3.cross(Cesium.Cartesian3.UNIT_Z, pivot, sc.eastAxis); // 绕它转 = 左右拖动(纬度方向倾倒)
if (Cesium.Cartesian3.magnitudeSquared(eastAxis) < 1e-12) { if (Cesium.Cartesian3.magnitudeSquared(eastAxis) < 1e-12) {
eastAxis.x = 1; eastAxis.x = 1;
eastAxis.y = 0; eastAxis.y = 0;
@@ -403,11 +404,15 @@ export class CesiumGlobe {
} else { } else {
Cesium.Cartesian3.normalize(eastAxis, eastAxis); Cesium.Cartesian3.normalize(eastAxis, eastAxis);
} }
const northAxis = Cesium.Cartesian3.normalize(
Cesium.Cartesian3.cross(upAxis, eastAxis, sc.northAxis), // 绕它转 = 上下拖动(经度方向倾倒)
sc.northAxis,
);
this._lookState = { this._lookState = {
pivot: Cesium.Cartesian3.clone(pivot), pivot: Cesium.Cartesian3.clone(pivot),
startOffset: Cesium.Cartesian3.clone(offset), startOffset: Cesium.Cartesian3.clone(offset),
upAxis: Cesium.Cartesian3.clone(upAxis),
eastAxis: Cesium.Cartesian3.clone(eastAxis), eastAxis: Cesium.Cartesian3.clone(eastAxis),
northAxis: Cesium.Cartesian3.clone(northAxis),
position: Cesium.Cartesian3.clone(camera.position), position: Cesium.Cartesian3.clone(camera.position),
direction: Cesium.Cartesian3.clone(camera.direction), direction: Cesium.Cartesian3.clone(camera.direction),
up: Cesium.Cartesian3.clone(camera.up), up: Cesium.Cartesian3.clone(camera.up),
@@ -443,26 +448,36 @@ export class CesiumGlobe {
this._lookHandler = handler; this._lookHandler = handler;
} }
// 按累计角度(已限制)把相机绕点击点旋转;位置、朝向、up 一起做刚体旋转 // 按累计角度(已限制)把相机绕点击点倾倒:左右 = 纬度方向(绕东西轴),
// 上下 = 经度方向(绕南北轴);up 始终强制北朝上。
_orbitCamera(s) { _orbitCamera(s) {
const camera = this.viewer.camera; const camera = this.viewer.camera;
const sc = this._orbitScratch; const sc = this._orbitScratch;
Cesium.Quaternion.fromAxisAngle(s.upAxis, s.azimuth, sc.qAz); Cesium.Quaternion.fromAxisAngle(s.eastAxis, s.azimuth, sc.qAz);
Cesium.Quaternion.fromAxisAngle(s.eastAxis, s.elevation, sc.qEl); Cesium.Quaternion.fromAxisAngle(s.northAxis, s.elevation, sc.qEl);
Cesium.Quaternion.multiply(sc.qEl, sc.qAz, sc.q); Cesium.Quaternion.multiply(sc.qEl, sc.qAz, sc.q);
Cesium.Matrix3.fromQuaternion(sc.q, sc.rotMat); Cesium.Matrix3.fromQuaternion(sc.q, sc.rotMat);
Cesium.Matrix3.multiplyByVector(sc.rotMat, s.startOffset, sc.newOffset); Cesium.Matrix3.multiplyByVector(sc.rotMat, s.startOffset, sc.newOffset);
Cesium.Cartesian3.add(s.pivot, sc.newOffset, sc.newPos); Cesium.Cartesian3.add(s.pivot, sc.newOffset, sc.newPos);
// up 不强制北朝上,与方向一起旋转(否则左右拽缺少 roll 分量,表现异常) const dir = Cesium.Cartesian3.normalize(
Cesium.Matrix3.multiplyByVector(sc.rotMat, s.direction, sc.dir); Cesium.Cartesian3.subtract(s.pivot, sc.newPos, sc.dir),
Cesium.Cartesian3.normalize(sc.dir, sc.dir); sc.dir,
Cesium.Matrix3.multiplyByVector(sc.rotMat, s.up, sc.upRot); );
Cesium.Cartesian3.normalize(sc.upRot, sc.upRot); // 强制北朝上: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({ camera.setView({
destination: Cesium.Cartesian3.clone(sc.newPos), destination: Cesium.Cartesian3.clone(sc.newPos),
orientation: { orientation: {
direction: Cesium.Cartesian3.clone(sc.dir), direction: Cesium.Cartesian3.clone(dir),
up: Cesium.Cartesian3.clone(sc.upRot), up: Cesium.Cartesian3.clone(sc.upProj),
}, },
}); });
} }