Search code examples
three.jsgeometryquaternionswebvr

THREE.js - Quaternion to lat, lon


I am trying to convert vrDisplays rotation (comes in quaternions) to latitude and longitude, since an API I use needs the current rotation of the head mounted display in lat and lon values.

lordofducts answer in unity3D forums (https://forum.unity3d.com/threads/quaternions-and-euler-angles-to-longitude-latitude.154392/ )

gave me good hope that this is actually possible, but I am kind of stuck, as THREE.Quaternion doesn't seem to have ToAxisAngle() method and I am not that good with 3D geometry.

so does anybody have an idea how I can achieve this so I can do sth like that?

var quat = THREE.Quaternion();

quat.fromArray(vrDisplay.getPose().orientation);

var lat = //do sth with quat
var lon = //do seth with quat

api.rotateCamera({
    lat: lat, 
    lon: lon
});

// I noticed that in my code I already have a conversion from Euler angles to lat lon. So I might be just converting the Quaternion to Euler angles and then convert it to lat lon values. Still, there has to be a more sophisticated method...


Solution

  • var look = new THREE.Vector3();
    
    quatToSpherical = function(quat){
      look.set(0,0,1);
      look.applyQuaternion(quat);
      look.normalize();
      if(Math.abs(look.x) < 0.001) look.x = 0.001;
    
      var angles = {};
      var radius = 1;
    
      angles.lat = Math.acos(look.z/r);
      angles.lon = Math.atan2(look.y , look.x);
    
      return angles;
    }
    

    The solution applies only to a standard cartesian coordinate system.

    a right handed coordinate system with XY ground plane like I used in my setup needs offsets:

    angles.lat = Math.acos(look.z/r) - Math.PI/2;
    angles.lon = Math.atan2(look.y , look.x) - Math.PI;
    

    https://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates