const scratchToHPRDirection = new Cartesian3();
const scratchToHPRUp = new Cartesian3();
const scratchToHPRRight = new Cartesian3();
function directionUpToHeadingPitchRoll(camera, position, orientation, result) {
const direction = Cartesian3.clone(
orientation.direction,
scratchToHPRDirection
);
const up = Cartesian3.clone(orientation.up, scratchToHPRUp);
if (camera._scene.mode === SceneMode.SCENE3D) {
const ellipsoid = camera._projection.ellipsoid;
const transform = Transforms.eastNorthUpToFixedFrame(
position,
ellipsoid,
scratchHPRMatrix1
);
const invTransform = Matrix4.inverseTransformation(
transform,
scratchHPRMatrix2
);
Matrix4.multiplyByPointAsVector(invTransform, direction, direction);
Matrix4.multiplyByPointAsVector(invTransform, up, up);
}
const right = Cartesian3.cross(direction, up, scratchToHPRRight);
result.heading = getHeading(direction, up);
result.pitch = getPitch(direction);
result.roll = getRoll(direction, up, right);
return result;
}
function getHeading(direction, up) {
let heading;
if (
!CesiumMath.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath.EPSILON3)
) {
heading = Math.atan2(direction.y, direction.x) - CesiumMath.PI_OVER_TWO;
} else {
heading = Math.atan2(up.y, up.x) - CesiumMath.PI_OVER_TWO;
}
return CesiumMath.TWO_PI - CesiumMath.zeroToTwoPi(heading);
}
function getPitch(direction) {
return CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(direction.z);
}
function getRoll(direction, up, right) {
let roll = 0.0;
if (
!CesiumMath.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath.EPSILON3)
) {
roll = Math.atan2(-right.z, up.z);
roll = CesiumMath.zeroToTwoPi(roll + CesiumMath.TWO_PI);
}
return roll;
}
- roll是围绕x轴旋转
- pitch是围绕Y轴旋转
- heding 是为找z手旋转,图中的yaw
这段代码实现的是将摄像机的方向向量和上方向量转换为欧拉角(heading、pitch、roll)。以下是代码的解读:
-
首先将摄像机的方向向量和上方向量分别存储到
direction
和up
变量中。 -
如果当前场景是3D场景,那么需要对
direction
和up
进行转换,使它们相对于场景的东北天坐标系(east-north-up)。具体做法是:先根据当前摄像机位置和地球椭球体,计算出将东北天坐标系转换为固定坐标系(fixed)的变换矩阵
transform
;然后再根据transform
的逆矩阵invTransform
,将direction
和up
从固定坐标系转换回东北天坐标系。这样做的目的是为了确保欧拉角的计算是相对于场景的东北天坐标系的。 -
接着计算右方向向量
right
,这个向量是通过direction
和up
的叉积计算得到的。 -
最后调用
getHeading
、getPitch
和getRoll
三个工具方法,分别计算欧拉角的yaw、pitch和roll值。这三个方法的具体实现逻辑不在这段代码中,但它们的功能分别是:
-
getHeading
:计算yaw;
计算yaw值(偏航角,也叫航向角)。这个方法需要传入视图中的方向向量direction
和上方向向量up
。根据方向向量和上方向量的值,计算出绕Z轴旋转的角度,即yaw值。具体做法是:如果方向向量的z分量不等于1,那么yaw值可以通过方向向量在x-y平面上的反正切值来计算;否则yaw值通过上方向量在x-y平面上的反正切值来计算。计算出的yaw值需要进行一系列的角度转换和规范化,以确保它处于0到2π之间。
getPitch
:计算pitch值,即绕右方向向量旋转的角度;
计算pitch值(俯仰角)。这个方法也需要传入视图中的方向向量direction
。根据方向向量的z值,计算出绕右方向向量旋转的角度,即pitch值。具体做法是:先计算出方向向量与Z轴的夹角,然后将这个夹角减去π/2,即为pitch的值。
getRoll
:计算roll值,即绕方向向量旋转的角度。
这个方法需要传入视图中的方向向量direction
、上方向量up
和右方向量right
。根据这三个向量的值,计算出绕方向向量旋转的角度,即roll值。具体做法是:如果方向向量的z分量不等于1,那么roll值可以通过右方向量在up向量上的反正切值来计算;否则roll值为0。计算出的roll值需要进行一系列的角度转换和规范化,以确保它处于0到2π之间。
这些工具方法可以用于将视图中的方向向量和上方向向量转换为欧拉角的值,以便于对摄像机进行控制。
最后将计算出的yaw、pitch和roll值存储到result
对象中,并返回result
对象。