《圖說VR入門》——googleVR 他山之玉


本文章由cartzhang編寫,轉載請註明出處。 全部權利保留。
文章連接:http://blog.csdn.net/cartzhang/article/details/53125482
做者:cartzhang
git

《圖說VR入門》——googleVR 他山之玉


以前分析了一些GoogleVR的代碼,畫了一些圖。
常言:他山之石,能夠攻玉。我的以爲googleVR這不能說是石頭了吧,入寶山空手而歸,豈是程序的風格。咱們但願能夠拿着googleVR的玉,最起碼刻個玉璽吧。哈哈!!

這篇記錄一下,google VR 在Unity中代碼寫的漂亮代碼。
只是比較不錯的代碼,固然都是一人之間見。
github

1、 補上googleVR實現過程

googleVR 以前仍舊以爲對它的實現過程沒有說的很明白,上篇重點在於它的代碼的運行過程。
如今補上一張總體實現過程,但願對有須要的人有幫助:
markdown

這裏寫圖片描述
圖1
要說的是,它這個寫的仍是很不錯的,贊一個。
由於不像其餘各類插件,你須要導入到unity工程中後,須要各類配置預製體,這個只須要把一個預製體拽到場景中,而且位置隨意,真是智能的很。
再看看人家的實現流程,不吝讚美之詞。因此,要看看他的代碼。若對我來講,須要說的是,就是我這大括號對齊的毛病。哎呀,代碼風格,兼容幷包吧。
編輯器

2、gvrViewer的值得借鑑的代碼

1. 類的單例模式

/// The singleton instance of the GvrViewer class.
  public static GvrViewer Instance {
    get {
#if UNITY_EDITOR
      if (instance == null && !Application.isPlaying) {
        instance = UnityEngine.Object.FindObjectOfType<GvrViewer>();
      }
#endif
      if (instance == null) {
        Debug.LogError("No GvrViewer instance found. Ensure one exists in the scene, or call "
            + "GvrViewer.Create() at startup to generate one.\n"
            + "If one does exist but hasn't called Awake() yet, "
            + "then this error is due to order-of-initialization.\n"
            + "In that case, consider moving "
            + "your first reference to GvrViewer.Instance to a later point in time.\n"
            + "If exiting the scene, this indicates that the GvrViewer object has already "
            + "been destroyed.");
      }
      return instance;
    }
  }

   private static GvrViewer instance = null;


首字母小寫的instance爲私有變量,首字母大寫的爲共有靜態變量,來實現單例模式。

在編輯器模式下,就直接找到GvrViewer的對象爲單例。可是這個是配合它Awake的代碼來寫的,本身要這麼寫也要看本身的須要。
ide

2. 靜態對象變量

類的Controller,是一個只有get屬性的變量。this

public static StereoController Controller {
    get {
#if !UNITY_HAS_GOOGLEVR || UNITY_EDITOR
      Camera camera = Camera.main;
      // Cache for performance, if possible.
      if (camera != currentMainCamera || currentController == null) {
        currentMainCamera = camera;
        currentController = camera.GetComponent<StereoController>();
      }
      return currentController;
#else
      return null;
#endif // !UNITY_HAS_GOOGLEVR || UNITY_EDITOR
    }
  }
  private static StereoController currentController;
  private static Camera currentMainCamera;

首先,咱們看到整個googleVR中都有宏定義google

#if !UNITY_HAS_GOOGLEVR || UNITY_EDITOR

#else

#endif // !UNITY_HAS_GOOGLEVR || UNITY_EDITOR

代碼功能是找到主相機,而後把組件StereoController給添加到主相機上。實現的功能就是分屏的控制,左右眼設置等操做。

主要在於看這個代碼形式。
spa

3.帶get和set屬性的變量

public RenderTexture StereoScreen {
    get {
      // Don't need it except for distortion correction.
      if (!distortionCorrectionEnabled || !VRModeEnabled) {
        return null;
      }
      if (stereoScreen == null) {
        // Create on demand.
        StereoScreen = device.CreateStereoScreen();  // Note: uses set{}
      }
      return stereoScreen;
    }
    set {
      if (value == stereoScreen) {
        return;
      }
      if (stereoScreen != null) {
        stereoScreen.Release();
      }
      stereoScreen = value;
      if (OnStereoScreenChanged != null) {
        OnStereoScreenChanged(stereoScreen);
      }
    }
  }


這與咱們經常使用的int a;這樣變量的區別在於它的get屬性和set屬性。這個是渲染紋理(RenderTexture)類。
Set的過程,先須要把以前的渲染紋理給Release釋放掉,而後在set還添加了OnStereoScreenChanged的委託事件。
.net

3、GvrProfile可鑑代碼


這個是枚舉值
插件

/// Some known screen profiles.
  public enum ScreenSizes {
    Nexus5,
    Nexus6,
    GalaxyS6,
    GalaxyNote4,
    LGG3,
    iPhone4,
    iPhone5,
    iPhone6,
    iPhone6p,
  };


這個是Screen類的對象:

/// Parameters for a Nexus 5 device.
  public static readonly Screen Nexus5 = new Screen {
    width = 0.110f,
    height = 0.062f,
    border = 0.004f
  };

  /// Parameters for a Nexus 6 device.
  public static readonly Screen Nexus6 = new Screen {
    width = 0.133f,
    height = 0.074f,
    border = 0.004f
  };

  // 不所有列舉了
  // .. .


發現奧祕了麼?
看圖
這裏寫圖片描述
圖2

紅框內的在vs中代碼顏色都同樣。我辨認都混淆了。

看到ScreenSizes這個是個枚舉類。他裏面的枚舉值Nexus5 等,都是枚舉值類型,隱形繼承的是int。
可是在同文件內,就還有一個Nexus5的變量,其類型爲Screen類。

這個作的很神奇啊。一開始在其餘地方使用的時候,我還覺得是寫錯了呢,結果編譯器也不吭氣,表示抗議。看來gogole寫的還真是有玄機。

那兩個不相關的東西怎麼對應和關聯的呢?

/// Returns a profile with the given parameters.
  public static GvrProfile GetKnownProfile(ScreenSizes screenSize, ViewerTypes deviceType) {
    Screen screen;
    switch (screenSize) {
      case ScreenSizes.Nexus6:
        screen = Nexus6;
        break;
      case ScreenSizes.GalaxyS6:
        screen = GalaxyS6;
        break;
      case ScreenSizes.GalaxyNote4:
        screen = GalaxyNote4;
        break;
      case ScreenSizes.LGG3:
        screen = LGG3;
        break;
      case ScreenSizes.iPhone4:
        screen = iPhone4;
        break;
      case ScreenSizes.iPhone5:
        screen = iPhone5;
        break;
      case ScreenSizes.iPhone6:
        screen = iPhone6;
        break;
      case ScreenSizes.iPhone6p:
        screen = iPhone6p;
        break;
      default:
        screen = Nexus5;
        break;
    }
    Viewer device;
    switch (deviceType) {
      case ViewerTypes.CardboardMay2015:
        device = CardboardMay2015;
        break;
      case ViewerTypes.GoggleTechC1Glass:
        device = GoggleTechC1Glass;
        break;
      default:
        device = CardboardJun2014;
        break;
    }
    return new GvrProfile { screen = screen, viewer = device };
  }

這樣就看明白了吧!!
就是這樣switch就作了關聯。其在EditorDevice.cs中的UpdateScreenData中調用。

4、 告一段


老生長談,路漫漫其修遠兮。

googleVR就代碼還有UI部分代碼及其controller的代碼都沒有具體涉及到。

還有一些就是在宏做用下,暫時在Unity或googlVR模式下,被屏蔽的代碼。
可是仍是但願這些東西對須要的人,有所幫助。

5、參考

[1] https://blogs.unity3d.com/2016/09/22/daydream-technical-preview-available-now/

[2] https://github.com/googlevr/gvr-unity-sdk/tree/master/GoogleVR

———————THE—————END————————
如有問題,請隨時聯繫!! 很是感謝!!

相關文章
相關標籤/搜索