本节主讲相机的Heading\Pitch和Roll。
Cesium的相机主要是通过局部坐标的偏航角、俯仰角和翻滚角确定相机姿态的。
上一节我们知道,Cesium在获取这三个角度的时候,会将以地球球心为原点的地心地固坐标ECEF转为ENU东北天坐标系,ENU坐标系中,X轴指向正东,Y轴指向正北,Z轴指向天顶。
所谓的偏航角、俯仰角和翻滚角,我们可以想象一个正在飞行的飞机,机头的朝向称为偏航角Heading,用于决定此时飞行的方向,如果飞机要转向,实际上是在与大地平行的一个平面上进行转向,因此,Heading的旋转轴是负Z轴。
飞机的俯仰角Pitch可以考虑为机头是朝向地面还是朝向天空,从而决定此时是上行还是下降。Pitch的旋转轴是负Y轴。
飞机的翻滚角Roll是飞机开始玩花样飞翔,以机身为旋转轴开始翻滚。Roll的旋转轴是X轴。
由此我们可以分析Heading、Pitch和Roll的计算方式。
我们将机头的朝向定义为direction,机翼方向为right,机身正身朝上的方向为up,构建右手坐标系。
获取Heading的方法
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);
}
可以看到,由于Heading的旋转轴是Z轴,因此,Heading实际上是一个在XY平面上与X轴的夹角。首先要将direction和up投影到XY平面上。如果此时相机朝向Z轴,即飞机机头像火箭一样垂直向上,则direction在XY轴的垂线在原点上,此时我们使用up来计算。此时的up一定是在XY平面上的。或者可以这么理解,当你站立在地上,你的眼睛直视前方,此时你的眼睛朝向的方向就是direction方向,你的右手方向就是right方向,你的头顶就是up方向。当你躺在地上,面朝天空的时候,你的面向方向如何确定的呢?当你站起来时,你面朝的方向一定是是你的脚的方向,因此,此时的方向也设为你的脚的朝向,同时,也是你的头顶方向up加减180度的方向。所以,此时要使用up来计算heading值。
heading方向的确定是你所面朝的方向direction与正北(Y轴)方向的夹角,并以顺时针,0-2PI的方式取值。
当direction平行于Z轴的时候,使用up来计算,head方向为up方向在XY轴上的投影的负向与正北(Y轴)方向的夹角。
即,当你站在地面上的时候,不管你的头是如何上下抬动的,heading方向始终是你的身体的朝向与正北之间的夹角,顺时针计算。
pitch的计算比较简单
function getPitch(direction) {
return CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(direction.z);
}
就是你抬头或者低头的较低,与你面朝的方向无关。计算你抬头的角度和天空之间(Z轴)的夹角即可。
而roll则是你歪头的角度。
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主要取决于right和up。由于roll的旋转轴是X轴,因此我们将right、up、direction投影到YZ平面上。如果direction的z朝向正上(Z轴),则right和up在YZ平面的投影都是共线的,都落在Y轴上,此时我们记roll为0.
如果direction的z不是朝上的就要求一个up方向在ZY平面上的投影与Z轴的夹角,表示你头歪了多少(同样,direction朝向上方的时候,不管怎么歪头,角度都是90度)。同样,在YZ平面上,顺时针为正。最终结果都为正值。