笔者最近在研究Cesium中坐标系变换的问题,看到了Transform类中有rotationMatrixFromPositionVelocity方法,但是官方对于这个方法的解释不是很清晰,我在网上查找的资源中对于这个方法的使用也非常少,所以去看了一下源码搞清楚了这个方法的含义。
简单说就是根据给定的位置和向量建立一个旋转矩阵,这个旋转矩阵以给定位置Position为坐标系原点,给定向量Velocity为坐标轴X。这个旋转矩阵的含义是从地固坐标系转到模型坐标系
具体说就是根据当前位置和球体相切面的法线得到一个向量normal,再根据normal和velocity得到和这两个向量组成的平面垂直的向量right,同理根据right和velocity得到up,对up进行归一化处理,再用up和velocity得到right,求right向量的中心对称向量(x,y,z全取反),最后再对right进行归一化处理,得到right,up,velocity三个向量,再将其组成旋转矩阵,源码在下面,欢迎大家交流~
/**
* Transform a position and velocity to a rotation matrix.
*
* @param {Cartesian3} position The position to transform.
* @param {Cartesian3} velocity The velocity vector to transform.
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
* @param {Matrix3} [result] The object onto which to store the result.
* @returns {Matrix3} The modified result parameter or a new Matrix3 instance if none was provided.
*/
Transforms.rotationMatrixFromPositionVelocity = function (
position,
velocity,
ellipsoid,
result
) {
//>>includeStart('debug', pragmas.debug);
if (!defined(position)) {
throw new DeveloperError("position is required.");
}
if (!defined(velocity)) {
throw new DeveloperError("velocity is required.");
}
//>>includeEnd('debug');
//得到position这一点处和椭球相切面的法线
var normal = defaultValue(ellipsoid, Ellipsoid.WGS84).geodeticSurfaceNormal(
position,
normalScratch
);
// 计算两个向量的交叉(外)积,两个向量的外积与这两个向量组成的坐标平面垂直
var right = Cartesian3.cross(velocity, normal, rightScratch);
if (Cartesian3.equalsEpsilon(right, Cartesian3.ZERO, CesiumMath.EPSILON6)) {
right = Cartesian3.clone(Cartesian3.UNIT_X, right);
}
var up = Cartesian3.cross(right, velocity, upScratch);
Cartesian3.normalize(up, up);
Cartesian3.cross(velocity, up, right);
// 向量取反
Cartesian3.negate(right, right);
Cartesian3.normalize(right, right);
if (!defined(result)) {
result = new Matrix3();
}
result[0] = velocity.x;
result[1] = velocity.y;
result[2] = velocity.z;
result[3] = right.x;
result[4] = right.y;
result[5] = right.z;
result[6] = up.x;
result[7] = up.y;
result[8] = up.z;
return result;
};