Unity Cardboard Orientation Landscape Right Upside Down

可紊 提交于 2019-12-01 20:26:30

It appears the native code that the SDK uses to read the gyro is hardcoded for Landscape Left orientation only. This can be worked around by editing BaseCardboardDevice.cs and replacing the definition of UpdateState() with the following code:

private Quaternion fixOrientation;

public override void UpdateState() {
  GetHeadPose(headData, Time.smoothDeltaTime);
  ExtractMatrix(ref headView, headData);
  headPose.SetRightHanded(headView.inverse);

  // Fix head pose based on device orientation (since native code assumes Landscape Left).
  switch (Input.deviceOrientation) {
    case DeviceOrientation.LandscapeLeft:
      fixOrientation = Quaternion.identity;
      return;
    case DeviceOrientation.LandscapeRight:
      fixOrientation = Quaternion.Euler(0, 0, 180);
      break;
  }
  headPose.Set(headPose.Position, headPose.Orientation * fixOrientation);
}

I suggest turning off the Neck Model Scale (set it to 0) in the Cardboard settings too, since it won't come out right with this code.

I’ve solved this issue, here’s the solution (valid for Cardboard v0.5.2)

First, as suggested by smd, you need to apply orientation adjust in BaseCardboardDevice / UpdateState(). However, you should check ScreenOrientation rather than DeviceOrientation. Code is as follows:

public override void UpdateState() {

    ProcessEvents();
    GetHeadPose(headData);
    ExtractMatrix(ref headView, headData);
    headPose.SetRightHanded(headView.inverse);

    if (Screen.orientation == ScreenOrientation.LandscapeRight) {
        headPose.Set(headPose.Position, headPose.Orientation * Quaternion.Euler(0, 0, 180));                           // Workaround
}

This will fix the orientation, but that’s not enough, because you will be facing wrong direction after Cardboard Recenter(). To workaround this, you also need to apply the rotation in CardboardHead / UpdateHead() method, the code is like this:

private void UpdateHead() {

    if (updated) {  // Only one update per frame, please.
      return;
    }
    updated = true;
    Cardboard.SDK.UpdateState();

    if (trackRotation) {
      var rot = Cardboard.SDK.HeadPose.Orientation;

      if (Screen.orientation == ScreenOrientation.LandscapeRight) {
        rot = Quaternion.Euler(0, 180, 0) * rot; //           << Workaround
      }

      if (target == null) {
        transform.localRotation = rot;
      } else {
        transform.rotation = target.rotation * rot;
      }
    }

    if (trackPosition) {
      Vector3 pos = Cardboard.SDK.HeadPose.Position;
      if (target == null) {
        transform.localPosition = pos;
      } else {
        transform.position = target.position + target.rotation * pos;
      }
    }

    if (OnHeadUpdated != null) {
      OnHeadUpdated(gameObject);
    }
  }

You can just add:

headPose.Set(headPose.Position, headPose.Orientation * Quaternion.Euler(0,0,180));

at the and of UpdateState() of BaseCardboardDevice class. It fixed this problem for me regardless of how I turned the devices I tried it on. Unity 5 cardboard SDK v0.5.1

        var fixOrientation = Quaternion.identity;
        // Fix head pose based on device orientation (since native code assumes Landscape Left).
        switch (Input.deviceOrientation) {
        case DeviceOrientation.LandscapeLeft:
            fixOrientation = Quaternion.identity;
            break;
        case DeviceOrientation.LandscapeRight:
            fixOrientation = Quaternion.Euler(0, 0, 180);
            break;
        default:
            Debug.Log ("Error No Orientation" + Input.deviceOrientation.ToString ());
            break;
        }
        headPose.Set(headPose.Position, headPose.Orientation * fixOrientation);

Now, Cardboard SDK became GoogleVR, so I wrote like this at GvrDevice.cs

One way to let your app appear in both LandscapeLeft and LandscapeRight, without getting fixed to only one, is in the Start method to enable the screen settings in this sequence:

void Start () {
     Screen.orientation = ScreenOrientation.Landscape;
     Screen.orientation = ScreenOrientation.AutoRotation;
     Screen.autorotateToPortrait = false;
     Screen.autorotateToPortraitUpsideDown = false;
}

Basically you force one side, then enable automatic rotation, and then prevent the rotation from being Portrait.

Note that this way your application can work on both Landscapes, so you only need to rotate the screen left or right.

-

Note also that this also works for one VR applications with Cardboard as any other.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!