一、背景簡介
Welcome to VR at Google
進入Google VR主頁,發現官方給我們提供了兩套解決觀看VR視訊的方式:
給我們提供了三個平臺的API,分別是:Unity 3D 、Android、IOS;
下面看一下官方給這兩種方式的描述(
Daydream
Daydream is a platform for high quality, mobile virtual reality.
白日夢是高質量,移動虛擬現實的平臺。在主頁上方官方也描述它為:低延遲,身臨其境的,互動的移動VR的新平臺
Cardboard
Cardboard lets you experience virtual reality in a simple, fun, and affordable way.
紙板可以讓你在負擔得起的情況下,體驗一個簡單,有趣的虛擬現實。在主頁上方官方也描述它為:是世界上最流行的和方便的移動VR平臺(可能是經濟成本低吧)
-
2014年:Google在當年的Google I/O大會上宣佈,其將開發紙盒版的HMD(頭盔式顯示器),年底該裝置銷量達到了50萬。
-
2015年:Cardboard被大公司所接受,Google將那些刻上了品牌商標的Cardboard分發給了各大合作商,消費者繼續購買主題化的HMD。此時,Cardboard的發展又到了另一個高度:銷量達到100萬。
-
2016年:在今年的Google I/O大會上,Google宣佈Cardboard銷量已達到500萬部,但與此同時,Google推出了Daydream——一個更高階的移動VR HMD,並將於今年11月進入市場。如今市場上已經產生了成千上萬的Cardboard應用,Google Play store上的Cardboard app安裝量達到50萬至100萬次。
Daydream is a much higher end VR experience. I have Cardboard, and it's neat, but in some ways, it feels like a tech demo. (白日夢是一個更高的終端虛擬現實體驗。紙板,它很簡潔,但在某些方面,感覺技術演示。)
那麼就此看來,應該是這樣的情況:Cardboard是Google先推出的簡陋版/測試版/經濟適用版,現在佔用了很大市場;Daydream 是今年新推出的豪華版/完善版/高階玩家版,會衝擊Cardboard的市場。也就是說Cardboard短期不會死 ,Daydream還在發展中。
介紹
官方在這裡介紹了VR view 、支援平臺等。我挑幾個相對重要的介紹一下:
1、影像規格
VR檢視影像可以儲存為PNG,JPEG或GIF。Google建議使用JPEG改進壓縮。 為了獲得最大的相容性和效能,影像尺寸應該是2的倍數(例如,2048或4096)。單個影像應為2:1縱橫比(例如4096×2048)。 立體影像應為1:1縱橫比(例如4096×4096)。
如圖:
案列
首先下載Demo,
https://github.com/googlevr/gvr-android-sdk
專案(gvr-android-sdk )中有幾個主要目錄可以留意一下:
-
libraries
-
ndk-beta
-
samples
-
samples目錄中有四個Demo,分別是:
-
SDK-controllerclient(Daydream的控制端)
-
SDK-simplepanowidget(全景圖)
-
SDK-simplevideowidget(全景視訊 也就是VR視訊)
-
SDK-treasurehunt(尋寶專案)
注意:執行環境必須是api19以上的手機,也就是Android4.4及以上
VrPanoramaView(VR全景檢視)的實現
1、新增依賴
compile 'com.google.vr:sdk-panowidget:1.40.0'
2、許可權
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3、佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.zx.vrview.MainActivity">
<com.google.vr.sdk.widgets.pano.VrPanoramaView
android:id="@+id/vrPanoramaView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:scrollbars="none"/>
</LinearLayout>
4、activity
/**
* VR全景檢視(圖片檢視器)
*/
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private VrPanoramaView paNormalView;
private VrPanoramaView.Options paNormalOptions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initVrPaNormalView();
}
@Override
protected void onPause() {
super.onPause();
paNormalView.pauseRendering();
}
@Override
protected void onResume() {
super.onResume();
paNormalView.resumeRendering();
}
@Override
protected void onDestroy() {
// Destroy the widget and free memory.
super.onDestroy();
paNormalView.shutdown();
}
//初始化VR圖片
private void initVrPaNormalView() {
paNormalView = (VrPanoramaView) findViewById(R.id.vrPanoramaView);
paNormalOptions = new VrPanoramaView.Options();
paNormalOptions.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;
// paNormalView.setFullscreenButtonEnabled (false); //隱藏全屏模式按鈕
paNormalView.setInfoButtonEnabled(false); //設定隱藏最左邊資訊的按鈕
paNormalView.setStereoModeButtonEnabled(false); //設定隱藏立體模型的按鈕
paNormalView.setEventListener(new ActivityEventListener()); //設定監聽
//載入本地的圖片源
paNormalView.loadImageFromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.andes), paNormalOptions);
//設定網路圖片源
// panoWidgetView.loadImageFromByteArray();
}
private class ActivityEventListener extends VrPanoramaEventListener {
@Override
public void onLoadSuccess() {//圖片載入成功
Log.i(TAG, "onLoadSuccess------------>");
}
@Override
public void onLoadError(String errorMessage) {//圖片載入失敗
Log.i(TAG, "Error loading pano:------------> " + errorMessage);
}
@Override
public void onClick() {//當我們點選了VrPanoramaView 時候出發
super.onClick();
Log.i(TAG, "onClick------------>");
}
@Override
public void onDisplayModeChanged(int newDisplayMode) {
//改變顯示模式時候出發(全屏模式和紙板模式)
super.onDisplayModeChanged(newDisplayMode);
Log.i(TAG, "onDisplayModeChanged------------>" + newDisplayMode);
}
}
}
程式碼分析
這個栗子中需要注意幾個知識點:
VrPanoramaView //Google提供給我們現實全景圖片的View
Options //VrPanoramaView 所需的設定
VrPanoramaEventListener//為 VrPanoramaView 設定監聽
loadImageFromBitmap//載入圖片的主要方法
Options
接下來看看剛剛的VrPanoramaView.Options吧,上文中 是這麼設定的
panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;
那麼為什麼要這樣設定呢?先看官方對Options中標籤的介紹:
-
public static final int TYPE_MONO = 1;
影像被預期以覆蓋沿著其水平軸360度,而垂直範圍是根據影像的寬高比來計算。例如,如果一個1000x250畫素的影像,給出所述全景將覆蓋360x90度與垂直範圍是-45至+45度。 -
public static final int TYPE_STEREO_OVER_UNDER = 2;
包含兩個大小相等的投影 全景圖垂直疊加。頂部影像被顯示給左眼、底部影像被顯示給右眼。//看下圖你就懂了
影像將覆蓋沿水平軸360度,而垂直範圍是根據影像的寬高比來計算。例如,如果一個1000x500畫素的影像中
這裡寫圖片描述
我要顯示的圖片是下圖這樣的,所以就要設定為 'TYPE_STEREO_OVER_UNDER'
這裡寫圖片描述
那麼什麼樣的圖片設定為 'TYPE_MONO' 呢?請看:
這裡寫圖片描述
不知道有沒有眼神好的同學發現這個問題:TYPE_STEREO_OVER_UNDER型別的圖片每次切換模式時候 圖片中間都會有一條垂直於水平線的分割線(很淺 很淺 然後逐漸消失),
總結
總結下如何在Android裝置上用Google的SDK做一款全景圖的顯示器(播放器?檢視器?... 不知道叫什麼合適):
-
匯入google的庫
-
在相應的佈局檔案中引入控制元件com.google.vr.sdk.widgets.pano.VrPanoramaView
-
初始化控制元件
-
為VrPanoramaView設定options
-
找到圖片的Bitmap
-
呼叫VrPanoramaView的loadImageFromBitmap方法
-
在onPause、onResume、onDestroy中做出相應處理
最後給大家分享一份非常系統和全面的Android進階技術大綱及進階資料,及面試題集
想學習更多Android知識,請加入Android技術開發企鵝交流 7520 16839
進群與大牛們一起討論,還可獲取Android高階架構資料、原始碼、筆記、視訊
包括 高階UI、Gradle、RxJava、小程式、Hybrid、移動架構、React Native、效能優化等全面的Android高階實踐技術講解效能優化架構思維導圖,和BATJ面試題及答案!
群裡免費分享給有需要的朋友,希望能夠幫助一些在這個行業發展迷茫的,或者想系統深入提升以及困於瓶頸的朋友,在網上部落格論壇等地方少花些時間找資料,把有限的時間,真正花在學習上,所以我在這免費分享一些架構資料及給大家。希望在這些資料中都有你需要的內容。