Skip to content

Proposal for recenter issue with the daydream HMD #17

Open
@Tivoyagefeak

Description

@Tivoyagefeak

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:

  1. 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.
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions