Use device orientation sensor alpha, beta and gamma to rotate camera

Hi everyone,

I am trying to control my Unity camera with the data received from an android mobile device sensor sent through websockets.

I am using SensorServer to receive data from my android device. I can receive separate magnetometer, accelerometer and gyroscope raw data, but I was trying to adapt the code from Device Orientation Controls from a deprecated example of Three.js (here) which uses the orientation sensor.

On my script I receive three values: x, y and z which are actually alpha, beta and gamma (in degrees) as the following:

· The DeviceOrientationEvent.alpha value
represents the motion of the device
around the z axis, represented in
degrees with values ranging from 0
(inclusive) to 360 (exclusive).


· The DeviceOrientationEvent.beta value
represents the motion of the device
around the x axis, represented in
degrees with values ranging from -180
(inclusive) to 180 (exclusive). This
represents a front to back motion of
the device.


· The DeviceOrientationEvent.gamma value
represents the motion of the device
around the y axis, represented in
degrees with values ranging from -90
(inclusive) to 90 (exclusive). This
represents a left to right motion of
the device.

I have been trying to adapt the code from three.js to c# but I get lost in the quaternion math, specially because of the abstraction of the euler class which does not exist in Unity and the axis change of the euler multiplication:

// SET UP
const _euler = new Euler();
const _q0 = new Quaternion();
const _q1 = new Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
const _zee = new Vector3(0, 0, 1);
const orient = window.orientation // its only possible values are -90, 0, 90, and 180, then they are converted to radians.

// UPDATE FUNCTION

_euler.set(beta, alpha, -gamma, "YXZ"); // 'ZXY' for the device, but 'YXZ' for us. All values are converted to radians

// Quaternion is the camera transform.rotation

quaternion.setFromEuler(_euler); // orient the device
    
quaternion.multiply(_q1); // camera looks out the back of the device, not the top
    
quaternion.multiply(_q0.setFromAxisAngle(_zee, -orient));

Basically what I would like to do is take alpha, beta and gamma and use these values to change my camera rotation as if I was looking through the phone with it, like a vr viewer.

Hope someone can help me with this since I have been trying without success.

Thank you so much in advance

@cristobalbahe - (I was writing my answer as a comment but it became a bit long so I have to place it as an swer, although I am unsure if it will fix your issue) Let’s break this down into smaller steps. First, you’ll need to convert the alpha, beta, and gamma values from degrees to radians because Unity uses radians for rotations. After that, you’ll have to adjust the coordinate systems and then use Quaternion.Euler to create a new quaternion.

Let’s start by creating a function to convert degrees to radians. It’s a simple mathematical conversion where one radian equals 180/PI degrees. So, the conversion function would look like this:

private float DegToRad(float angleInDegrees)
{
    return angleInDegrees * Mathf.PI / 180;
}

Now, you should convert alpha, beta, and gamma to radians before using them. As you mentioned, alpha represents rotation around the z-axis, beta around the x-axis, and gamma around the y-axis. But, Unity’s coordinate system is left-handed, whereas the device’s is right-handed. Therefore, some adjustments are needed:

For Unity, the y-axis is up/down, so alpha (rotation around the z-axis) will be y in Unity.
Beta is a rotation around the x-axis, which matches with Unity’s x-axis.
Gamma is rotation around the y-axis, but since Unity’s y is up/down, we’ll use gamma for Unity’s z.

Now, you can use Quaternion.Euler to create a new quaternion:

float alphaRad = DegToRad(alpha);
float betaRad = DegToRad(beta);
float gammaRad = DegToRad(gamma);

Quaternion deviceRotation = Quaternion.Euler(betaRad, alphaRad, -gammaRad);

Here, the rotations are applied in the order of x (beta), y (alpha), and then z (gamma), which corresponds to the “YXZ” order in your original JavaScript code. Note the negative sign before gammaRad because Unity uses a left-handed coordinate system.

Finally, you can apply this rotation to your camera. If your camera’s initial rotation is stored in initialRotation, you can apply deviceRotation relative to initialRotation like this:

Quaternion finalRotation = initialRotation * deviceRotation;
camera.transform.rotation = finalRotation;

I hope this helps! Im unsure if it will work, but it should in the very least get you closer to an answer wwhat with the conversions and all.