'Javascript Full 360 rotation from deviceorientation event beta angle when device is horizontal

I'm developing a WebGL game where the user would use the orientation of the device to control the camera ie look around. From the three rotations of deviceorientation event, I converted them to Quaternions.

THe problem starts here: I need to have the user to hold the device horizontally. In this position, the beta angle will be used to turn around the vertical axis y from the user's perspective.

enter image description here

However, the beta angle only goes from -180 to 180, any number outside will cause the other axes to change, to get a valid rotation. Due to how my WebGL camera is handled (I'm using Unity Engine), I need to separate the axes to remap them to the Camera coordinate accordingly, and to offset the angles from the horizontal pose (adding 90 degrees to the Y axis for example, because the device is rolled back). I have to convert the quaternion back to 3 euler angles and control each camera axis through those.

Is there a way to solve this?

Here's what I use to get the device orientation from the web:

var degtorad = Math.PI / 180; // Degree-to-Radian conversion

function getQuaternion(alpha, beta, gamma) {
  var _x = beta ? beta * degtorad : 0; // beta value
  var _y = gamma ? gamma * degtorad : 0; // gamma value
  var _z = alpha ? alpha * degtorad : 0; // alpha value

  var cX = Math.cos(_x / 2);
  var cY = Math.cos(_y / 2);
  var cZ = Math.cos(_z / 2);
  var sX = Math.sin(_x / 2);
  var sY = Math.sin(_y / 2);
  var sZ = Math.sin(_z / 2);

  //
  // ZXY quaternion construction.
  //

  var w = cX * cY * cZ - sX * sY * sZ;
  var x = sX * cY * cZ - cX * sY * sZ;
  var y = cX * sY * cZ + sX * cY * sZ;
  var z = cX * cY * sZ + sX * sY * cZ;

  return [w, x, y, z];
}

function GyroEvent(e) {
  var quat = getQuaternion(e.alpha, e.beta, e.gamma + 90);
  // w
  unityInstance.SendMessage("Main Camera", "GetGyroW", quat[0]);
  // x
  unityInstance.SendMessage("Main Camera", "GetGyroX", quat[1]);
  // y
  unityInstance.SendMessage("Main Camera", "GetGyroY", quat[2]);
  // z
  unityInstance.SendMessage("Main Camera", "GetGyroZ", quat[3]);
}

window.addEventListener("deviceorientation", GyroEvent);


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source