Open
Description
Hi, first of all thank you for your great work. Im not sure if I overthought the following problem, but I had an issue with the build in recenter Action from DayDream. The behaviour of the ARCam in relation to the VR Camera really confused me and I couldnt find a solution anywhere. So If anyone stumbles across the same issue this is how I tackled it:
- The problem:
Everytime you recenter in a different orientation than the starting orientation of the app, the VR Camera gets aligned correctly but the ARCore Camera is not affected (which is quite obvious). But it had no affect either, when I tried to rotate the ARCore Camera to the new orientation. And I tried a lot of approaches to fix the rotation issue. - My solution:
In the end I watched the last X rotations of the VR camera and listened to the GvrControllerInput.Recentered event to get noticed when the event started. You have to listen to the last rotations because it might take one or two more frames till the recenter actually takes place. Then you can spot the desired value. This angle is used to rotate the position vectors in the followARCoreCamera so you still walk straight on.
public class RecenterCorrection : MonoBehaviour {
public static float ANGLETHRESHOLD = 2f;
public static int ROTATIONQUEUESIZE = 10;
//camera for rotation values
public Transform gearCamera;
//AR Core Camera for real world position values
public Transform arcoreCamera;
//class which "followy" the arcore cam position with the daydream camera
followARCoreCamera arcorecam;
//stores rotation each frame from daydream camera
Queue<Vector3> rotations;
//flag which indicates that recentered got triggered
bool watchRotation;
// Use this for initialization
void Start () {
arcorecam = GameObject.FindObjectOfType<followARCoreCamera>();
watchRotation = false;
rotations = new Queue<Vector3>();
}
// Update is called once per frame
void Update () {
//only watch last ROTATIONQUEUESIZE rotations. The rotation recenter can last some frames, so we have to track more rotation values to spot the action and the angle
if (rotations.Count > ROTATIONQUEUESIZE)
{
//if queue is full kick out the oldest element
rotations.Dequeue();
}
//enque the newest rotation value of daydream cam
rotations.Enqueue(gearCamera.rotation.eulerAngles);
//recentered got pressed might be executing soon / executed
if (GvrControllerInput.Recentered)
{
Debug.Log("[IO] Recentering Done");
//watch the Queue with stored rotations to spot the angle difference
watchRotation = true;
}
if (watchRotation)
{
//get current y angle of daydream camera
float yAngle = gearCamera.rotation.eulerAngles.y;
//check if its inside our "recetered" anglethreshhold
if ((yAngle > 360f - ANGLETHRESHOLD && yAngle <= 360) ||
(yAngle >= 0f && yAngle < ANGLETHRESHOLD)){
//get the odlest y angle of queue
yAngle = rotations.Dequeue().y;
//remeber the angle before yAngle
float angleBeforeRecenter = 0f;
//as long ad the yAngle is not in range, dequeue the rotations
while (!((yAngle > 360f - ANGLETHRESHOLD && yAngle <= 360) || (yAngle >= 0f && yAngle < ANGLETHRESHOLD)))
{
angleBeforeRecenter = yAngle;
yAngle = rotations.Dequeue().y;
}
//now angleBeforeRecenter has the angle before the recenterd rotation of (almost) 0
Debug.Log("[IO] Recenter finished, y Angle almost 0f");
//tell arcore cam the angle, so the delta Vectors can be rotated accordingly
//we have to substract the old vector, cause this vector is always the new origin rotation
arcorecam.mirrorAngle = (arcorecam.mirrorAngle - angleBeforeRecenter)%360;
Debug.Log("[IO] ARCore mirrorAngle = " + arcorecam.mirrorAngle);
//stop watching the rotations
watchRotation = false;
}
//if not, keep on recording the rotations of daydream cam
rotations.Enqueue(gearCamera.rotation.eulerAngles);
}
}
}
If you have a more convinient solution or if i missed sth please share your thoughts. I just wanted to share this so if another person has similiar issues he can start with my approach.
Greetings
Micha