Sensor data coming in from [GAME_]ROTATION_VECTOR is a quaternion with the following axes:
- +X is Y dot Z (along the short axis for a rectangular phone, pointing right)
- +Y tangential to the device's screen, pointing upwards (along the long axis for a rectangular phone)
- +Z perpendicular to the device's screen, pointing outwards (towards the viewer when looking at a phone screen)
When the phone is held in "VR" orientation:
- it is rotated 90 degrees around the Z axis (to get it to landscape mode)
- it is rotated 90 degrees around the Y axis (to flip it upwards to be held directly in front of the eyes instead of flat)
The coordinate space that's desired when the phone is held in the VR orientation:
- +X points right (rightwards along the long axis of the phone; the former -Y direction)
- +Y points up (upwards along the short axis of the phone; the former +X direction)
- +Z points perpendicular to the device's screen, pointing outward (towards the viewer)
- this basically means that the former +X axis becomes +Y, and the former +Y axis becomes -X
This should lead to the following pseudocode:
Quaternion baseRotation(rv[1], rv[2], rv[3], rv[0]); // pull rotation vector sensor data into quaternion
baseRotation.normalize();
// remap coordinate system; this is what the Android SensorManager.remapCoordinateSystem function does
Matrix remap(0, 1, 0, 0,
-1, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
// make the new coordinate system be what we want
Matrix rotationMatrix = Matrix(baseRotation) * remap;
// but I need to adjust for the 90-degree landscape and flip-up orientations