GoogleVR for Unity--CardBoard视图过小的解决方案

问题

google vr 的sdk现在还不能适配所有的机型。有一些特别的机型就会出现视图过小的问题。如图。视图都缩小在了屏幕的下方,小小的一个。(github上的图)

比如这样

原因

设备没有反馈一个正确的dpi值给sdk。没有正确的值,sdk自然不能绘制出一个合适的视图了。

简练的解决方案

在unity中,找到BaseDevice脚本,有UpdateProfile()方法。里面就是定义了屏幕的各种属性。其中,screen.width和screen.height就是屏幕的宽和高了(单位:米)。可以根据不同的屏幕做自定义。
当然啦,这个方法里面还给很多其他的属性赋值了,我们都可以在这里对这些属性做操作。

 private void UpdateProfile()
    {
       GetProfile(profileData);
       GvrProfile.Viewer device = new GvrProfile.Viewer();
       GvrProfile.Screen screen = new GvrProfile.Screen();
       device.maxFOV.outer = profileData[0];
       device.maxFOV.upper = profileData[1];
       device.maxFOV.inner = profileData[2];
       device.maxFOV.lower = profileData[3];
       
       //重点在此。通过改这里的值,就可以修改视图的大小了。注意。这里的单位是:米。
        screen.width = 0.133f;
        screen.height = 0.074f;
       
        screen.border = profileData[6];
        device.lenses.separation = profileData[7];
        device.lenses.offset = profileData[8];
        device.lenses.screenDistance = profileData[9];
        device.lenses.alignment = (int)profileData[10];
        device.distortion.Coef = new [] { profileData[11], profileData[12] };
        Profile.screen = screen;
        Profile.viewer = device;

        float[] rect = new float[4];
        Profile.GetLeftEyeNoLensTanAngles(rect);
        float maxRadius = GvrProfile.GetMaxRadius(rect);
        Profile.viewer.inverse = GvrProfile.ApproximateInverse(
        Profile.viewer.distortion, maxRadius);
    }

好,简练的解决方案到此为止,如果只是想解决问题的同学看到这里就够了,可以直接滑到底部点个赞啦下面是我解决这个问题过程中的一些经历和收获。


过程和收获

在GvrViewerMain中,可以看到有一个Unity Editor Emulation Settings。这就unity的模拟设置。



年少无知英文不好的我,看到有手机型号设置,就直接点进去GvrViewer脚本中看了。

在脚本中,很轻易地发现,是GvrProfile这个类在控制着这些手机型号的设置。继续点进去看咯。


GvrProfile

GvrProfile这个类中,定义了所有关于屏幕的信息。所有的长度单位都是米。这会决定视图放在手机上的哪个位置和方向。

我们看下源码,看下到底有哪些屏幕信息

/// Information about the screen.  All distances are in meters, measured relative to how
/// the phone is expected to be seated in the viewer, i.e. landscape orientation.
[System.Serializable]
public struct Screen {

  public float width;   // The long edge of the phone.手机的宽
  public float height;  // The short edge of the phone.手机的高
  public float border;  // Distance from bottom of the phone to the bottom edge of screen.
}

ps:视图会尽量保持正方形,所以width和height相差太大,视图会设配数值小的那个属性,让视图显得很小。

关于透镜在视图中如何放置的信息。也是以米为单位的。

/// Information about the lens placement in the viewer.  All distances are in meters.
[System.Serializable]
public struct Lenses {
  public float separation;     // Center to center.左右两眼的视图的中心点之间的距离
  public float offset;         // Offset of lens center from top or bottom of viewer.视图中心点与底部的距离
  public float screenDistance; // Distance from lens center to the phone screen.视图边缘到视图中心点的距离。说到底就是视图的大小

  public int alignment;  // Determines whether lenses are placed relative to top, bottom or
                         // center.  It is actually a signum (-1, 0, +1) relating the scale of
                         // the offset's coordinates to the device coordinates.
                         //视图的align。。靠中,靠上,靠下咯,就是下面定义的三个变量。

  public const int AlignTop = -1;    // Offset is measured down from top of device.
  public const int AlignCenter = 0;  // Center alignment ignores offset, hence scale is zero.
  public const int AlignBottom = 1;  // Offset is measured up from bottom of device.
}

嗯,,还有还有,关于透镜的属性没认真看这部分的代码,所有就不翻译了。

 /// Information about the viewing angles through the lenses.  All angles in degrees, measured

/// away from the optical axis, i.e. angles are all positive.  It is assumed that left and right

/// eye FOVs are mirror images, so that both have the same inner and outer angles.  Angles do not

/// need to account for the limits due to screen size.
[System.Serializable]
public struct MaxFOV {
  public float outer;  // Towards the side of the screen.
  public float inner;  // Towards the center line of the screen.
  public float upper;  // Towards the top of the screen.
  public float lower;  // Towards the bottom of the screen.
}

/// Information on how the lens distorts light rays.  Also used for the (approximate) inverse
/// distortion.  Assumes a radially symmetric pincushion/barrel distortion model.
[System.Serializable]
public struct Distortion {
  private float[] coef;
  public float[] Coef {
    get {
      return coef;
    }
    set {
      if (value != null) {
        coef = (float[])value.Clone();
      } else {
        coef = null;
      }
    }
  }

  public float distort(float r) {
    float r2 = r * r;
    float ret = 0;
    for (int j=coef.Length-1; j>=0; j--) {
      ret = r2 * (ret + coef[j]);
    }
    return (ret + 1) * r;
  }

  public float distortInv(float radius) {
    // Secant method.
    float r0 = 0;
    float r1 = 1;
    float dr0 = radius - distort(r0);
    while (Mathf.Abs(r1 - r0) > 0.0001f) {
      float dr1 = radius - distort(r1);
      float r2 = r1 - dr1 * ((r1 - r0) / (dr1 - dr0));
      r0 = r1;
      r1 = r2;
      dr0 = dr1;
    }
    return r1;
  }
}

看完这里,大家就会觉得好面熟喔,是的,这些属性就是我们在解决方案中,在androiddevice中修改的属性。不过,在直接在这里改的话,就这可以在unity编辑器中模拟运行的时候看到效果。实际运行的时候并不会有什么作用的。

所以我们回归到GvrViewer。发现了如下代码

用来提供数据的vr设备
 // The VR device that will be providing input data.
private static BaseVRDevice device;

我们发现这个BaseVRDevice中也自己存放着一个GvrProfile,估计他就是正主了。

在GvrViewer脚本中,我们发现他是通过

  device = BaseVRDevice.GetDevice();

来得到一个BaseVRDevice的实例的。GetDevice()方法具体的代码如下。所以,想知道你的设备具体是使用哪个BaseVRDevice的实例?打个log看看呗。

  public static BaseVRDevice GetDevice() {
    if (device == null) {
#if UNITY_EDITOR
      device = new EditorDevice();
#elif ANDROID_DEVICE
  #if UNITY_HAS_GOOGLEVR
      device = new UnityVRDevice();
  #else
      device = new AndroidDevice();
  #endif  // UNITY_HAS_GOOGLEVR
#elif IPHONE_DEVICE
      device = new iOSDevice();
#else
      throw new InvalidOperationException("Unsupported device.");
#endif  // UNITY_EDITOR
    }
    return device;
  }

在下的设备使用的是AndroidDevices。发现这个类里面,没做屏幕适配的方法喔。找他的父类GvrDevice。bingo,找到了UpdateProfile()方法。

  private void UpdateProfile() {
      //profileDate是一个底层的方法。我们通过调用这个方法,得到手机屏幕的数据,然后再像自己的profile赋值,根据这个值来绘制视图。
      GetProfile(profileData);
      
      GvrProfile.Viewer device = new GvrProfile.Viewer();
      GvrProfile.Screen screen = new GvrProfile.Screen();
      device.maxFOV.outer = profileData[0];
      device.maxFOV.upper = profileData[1];
      device.maxFOV.inner = profileData[2];
      device.maxFOV.lower = profileData[3];
      screen.width = profileData[4];
      screen.height = profileData[5];
      screen.border = profileData[6];
      device.lenses.separation = profileData[7];
      device.lenses.offset = profileData[8];
      device.lenses.screenDistance = profileData[9];
      device.lenses.alignment = (int)profileData[10];
      device.distortion.Coef = new [] { profileData[11], profileData[12] };
      Profile.screen = screen;
      Profile.viewer = device;

      float[] rect = new float[4];
      Profile.GetLeftEyeNoLensTanAngles(rect);
      float maxRadius = GvrProfile.GetMaxRadius(rect);
      Profile.viewer.inverse = GvrProfile.ApproximateInverse(
          Profile.viewer.distortion, maxRadius);
    }

然后怎么适配具体的屏幕,交给大家自由发挥了。

我的unity,googleVR学习总结目录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容