右键环视:计算北朝上所需的 roll,消除倾斜时的附加旋转
This commit is contained in:
@@ -383,6 +383,10 @@ export class CesiumGlobe {
|
|||||||
enu: new Cesium.Matrix4(),
|
enu: new Cesium.Matrix4(),
|
||||||
invEnu: new Cesium.Matrix4(),
|
invEnu: new Cesium.Matrix4(),
|
||||||
localDir: new Cesium.Cartesian3(),
|
localDir: new Cesium.Cartesian3(),
|
||||||
|
enuUp: new Cesium.Cartesian3(),
|
||||||
|
u0: new Cesium.Cartesian3(),
|
||||||
|
un: new Cesium.Cartesian3(),
|
||||||
|
cross: new Cesium.Cartesian3(),
|
||||||
};
|
};
|
||||||
|
|
||||||
handler.setInputAction((movement) => {
|
handler.setInputAction((movement) => {
|
||||||
@@ -477,9 +481,37 @@ export class CesiumGlobe {
|
|||||||
Cesium.Matrix4.multiplyByPointAsVector(sc.invEnu, dir, sc.localDir);
|
Cesium.Matrix4.multiplyByPointAsVector(sc.invEnu, dir, sc.localDir);
|
||||||
const heading = Math.atan2(sc.localDir.x, sc.localDir.y);
|
const heading = Math.atan2(sc.localDir.x, sc.localDir.y);
|
||||||
const pitch = Math.asin(sc.localDir.z);
|
const pitch = Math.asin(sc.localDir.z);
|
||||||
|
|
||||||
|
// 计算“北朝上”所需的 roll:把 roll=0 的 up(水平线方向)滚转到“世界 Z 投影”的 up,
|
||||||
|
// 这样倾斜时 up 不随方向转动(否则会又倾斜又旋转)
|
||||||
|
const dz = dir.z;
|
||||||
|
sc.un.x = -dir.x * dz;
|
||||||
|
sc.un.y = -dir.y * dz;
|
||||||
|
sc.un.z = 1 - dz * dz;
|
||||||
|
if (Cesium.Cartesian3.magnitudeSquared(sc.un) < 1e-12) {
|
||||||
|
Cesium.Cartesian3.clone(s.up, sc.un);
|
||||||
|
} else {
|
||||||
|
Cesium.Cartesian3.normalize(sc.un, sc.un);
|
||||||
|
}
|
||||||
|
Cesium.Cartesian3.normalize(sc.newPos, sc.enuUp); // 径向 = newPos 处的“上”
|
||||||
|
const d0 = Cesium.Cartesian3.dot(sc.enuUp, dir);
|
||||||
|
sc.u0.x = sc.enuUp.x - d0 * dir.x;
|
||||||
|
sc.u0.y = sc.enuUp.y - d0 * dir.y;
|
||||||
|
sc.u0.z = sc.enuUp.z - d0 * dir.z;
|
||||||
|
let roll = 0;
|
||||||
|
if (Cesium.Cartesian3.magnitudeSquared(sc.u0) > 1e-12) {
|
||||||
|
Cesium.Cartesian3.normalize(sc.u0, sc.u0);
|
||||||
|
Cesium.Cartesian3.cross(sc.u0, sc.un, sc.cross);
|
||||||
|
const sin =
|
||||||
|
Cesium.Cartesian3.magnitude(sc.cross) *
|
||||||
|
Math.sign(Cesium.Cartesian3.dot(sc.cross, dir));
|
||||||
|
const cos = Cesium.Cartesian3.dot(sc.u0, sc.un);
|
||||||
|
roll = Math.atan2(sin, cos);
|
||||||
|
}
|
||||||
|
|
||||||
camera.setView({
|
camera.setView({
|
||||||
destination: Cesium.Cartesian3.clone(sc.newPos),
|
destination: Cesium.Cartesian3.clone(sc.newPos),
|
||||||
orientation: { heading, pitch, roll: 0 },
|
orientation: { heading, pitch, roll },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user