Rotation of an object in the tangent space of a globe

Viewed 204

Given the two following inputs:

  • a point on a sphere (like an observer on Earth);
  • and the world matrix of an object in space (the position and attitude of a satellite),

how to get the azimuth and elevation of the object in the tangent space of the point on the sphere (the elevation and azimuth of where the observer should look at)? In particular, when the object is exactly at the zenith, the yaw rotation (rotation around the vertical axis) should account for the azimuth (so that, though the observer is looking straight up, his shoulders would be facing the same azimuth as the object).

The math I've tried so far is:

  1. to put the satellite in tangent space (multiplying its world matrix with the inverse of the matrix of the tangent space on the globe). Or the same with quaternions. An euler rotation is then deduced from the resulting matrix (or the resulting quaternion), with a "ZXY" priority, and the Z and X are interpreted as azimuth and elevation. But this gives incorrect numbers, as part of the rotation seems often interpreted as roll (Y axis rotation) which I want to be zero.
  2. an intuitive approach also is to compute the angle between the vector of the observer to the object's position, with the vertical axis, to deduce the elevation; whereas the azimuth is given by the angle between the tangent north and the projected position of the object on the "tangent ground" (plus some more math to hone this particular deduction). But this approach does not work for the case of the object at the zenith.

Resources exist online but not with these specific inputs and the necessity of supporting the zenith case.


Incidentally the program is in typescript for three.js, and so the code goes as follows for the first solution described above:

function getRotationAtPoint(
    object: THREE.Object3D,
    point: THREE.Vector3
): { azimuth: number, elevation: number } {
    // 1. Get the matrix of the tangent space of the observer.
    const tangentSpaceMatrix = new THREE.Matrix4();
    const baseTangentSpaceAxes = getBaseTangentAxesOnSphere(point);
    tangentSpaceMatrix.makeBasis(...baseTangentSpaceAxes);

    // 2. Tranform the object's matrix in tangent space of observer.
    const inverseMatrix = new THREE.Matrix4().getInverse(tangentSpaceMatrix);
    const objectMatrix = object.matrixWorld.clone().multiply(inverseMatrix);

    // 3. Get the angles.
    const euler = new THREE.Euler().setFromRotationMatrix(objectMatrix);
    return {
        azimuth: euler.z,
        elevation: euler.x
    };
}

Also, Three.js offers references to the up axis of THREE.Object3D instances, however the program I deal with computes everything directly into the objects' matrices and the up axis can't be trusted.

0 Answers
Related