Github
VR
虛擬現(xiàn)實(shí)(Virtual Reality)技術(shù)是一種可以創(chuàng)建和體驗(yàn)虛擬世界的計(jì)算機(jī)仿真系統(tǒng)轴合,它利用計(jì)算機(jī)生成一種模擬環(huán)境沃但,是一種多源信息融合的挖炬、交互式的三維動(dòng)態(tài)視景和實(shí)體行為的系統(tǒng)仿真, 使用戶(hù)沉浸到該環(huán)境中。
VR產(chǎn)品
Google VR for Android#
Google VR for Android支持DayDream和Cardboard。
SDK下載
使用git命名下載或者直接在github上下載壓縮包
git clone https://github.com/googlevr/gvr-android-sdk.git
官方Sample運(yùn)行
導(dǎo)入gvr-android-sdk到Android Studio, 同步的過(guò)程中需要下載很多庫(kù)所以會(huì)比較耗時(shí)剧蚣,另外可能出現(xiàn)build失敗的情況,這時(shí)可以嘗試使用本地的gradle來(lái)編譯旋廷。
gradle版本最好為最新版本鸠按。
simplepanowidget
simplepanowidget展示了印加文明遺跡馬丘比丘的全景圖(Panorama)
在真機(jī)上運(yùn)行時(shí),會(huì)有一個(gè)Cardboard選項(xiàng)饶碘。
點(diǎn)擊上圖紅色框中的按鈕即可進(jìn)入Cardboard模式目尖。
Demo代碼的主要邏輯就是加載一張全景圖放入VrPanoramaView中。
panoOptions = new Options();
panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;//圖像類(lèi)型為立體圖像
istr = assetManager.open("andes.jpg");//加載assets目錄下的全景圖
panoWidgetView.loadImageFromBitmap(BitmapFactory.decodeStream(istr), panoOptions);
全景圖片andes是由兩張圖片組成扎运,上面一張是給左眼看瑟曲,下面一張是給右眼看。
圖片類(lèi)型
simeplevideowidget
simeplevideowidget展示了剛果雨林中大猩猩的360視頻豪治。
Demo的核心代碼是加載assets目錄下的congo.mp4視頻到VrVideoView中
videoWidgetView.loadVideoFromAsset("congo.mp4", options);
congo.mp4的視頻內(nèi)容也是分為上下部分洞拨,上面給左眼看,下面給右眼看负拟。
treasurehunt
treasurehunt展示了一個(gè)簡(jiǎn)單到離譜的尋寶游戲扣甲,當(dāng)vr世界中矩形變成金黃色時(shí),點(diǎn)擊手機(jī)屏幕或者使用Daydream的控制器,即可完成尋寶琉挖。游戲還伴有音效启泣。
controllerclient
接收DayDream控制器輸入示例
videoplayer
使用Asynchronous Reprojection播放視頻示例
全景圖(PanoramaActivity)
1. 配置build.gradle
//修改minSDK為19
minSdkVersion 19
//添加依賴(lài)
compile 'com.google.vr:sdk-panowidget:1.20.0'
2. 配置AndroidManifest.xml
由于全景圖占內(nèi)存較大,當(dāng)加載多張全景圖時(shí)可能存在內(nèi)存溢出的情況示辈,所以這里開(kāi)啟largeHeap寥茫。
<application
android:largeHeap="true">
</application>
3. 加載全景圖
private class LoadPanoramaImageTask extends AsyncTask<Void, Void, Bitmap> {
@Override
protected Bitmap doInBackground(Void... params) {
try {
//加載assets目錄下的全景圖片
AssetManager assetManager = getAssets();
InputStream open = assetManager.open("andes.jpg");
return BitmapFactory.decodeStream(open);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
VrPanoramaView.Options options = new VrPanoramaView.Options();
//圖片類(lèi)型為立體圖像
options.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;
mVrPanoramaView.loadImageFromBitmap(bitmap, options);
}
}
4. 繩命周期管理
@Override
protected void onPause() {
mVrPanoramaView.pauseRendering();
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
mVrPanoramaView.resumeRendering();
}
@Override
protected void onDestroy() {
// Destroy the widget and free memory.
mVrPanoramaView.shutdown();
// The background task has a 5 second timeout so it can potentially stay alive for 5 seconds
// after the activity is destroyed unless it is explicitly cancelled.
if (mLoadPanoramaImageTask != null) {
mLoadPanoramaImageTask.cancel(true);
}
super.onDestroy();
}
5. 事件監(jiān)聽(tīng)
mVrPanoramaView.setEventListener(mVrPanoramaEventListener);
private VrPanoramaEventListener mVrPanoramaEventListener = new VrPanoramaEventListener() {
/**
* 點(diǎn)擊回調(diào)
*/
@Override
public void onClick() {
super.onClick();
}
/**
* 加載數(shù)據(jù)成功回調(diào)
*/
@Override
public void onLoadSuccess() {
super.onLoadSuccess();
}
/**
* 加載數(shù)據(jù)失敗回調(diào)
*/
@Override
public void onLoadError(String errorMessage) {
super.onLoadError(errorMessage);
}
};
360 視頻
1. 配置build.gradle
//添加依賴(lài)
//minSdkVersion 19//已經(jīng)配置則忽略
compile 'com.google.vr:sdk-videowidget:1.20.0'
2. 配置AndroidManifest.xml (已經(jīng)配置則忽略)##
<application
android:largeHeap="true">
</application>
3. 加載視頻
VrVideoView.Options options = new VrVideoView.Options();
//視頻類(lèi)型為立體視頻
options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER;
try {
mVrVideoView.loadVideoFromAsset("congo.mp4", options);
} catch (IOException e) {
e.printStackTrace();
}
4. 繩命周期管理
@Override
protected void onPause() {
super.onPause();
// Prevent the view from rendering continuously when in the background.
mVrVideoView.pauseRendering();
// If the video is playing when onPause() is called, the default behavior will be to pause
// the video and keep it paused when onResume() is called.
isPaused = true;
}
@Override
protected void onResume() {
super.onResume();
mVrVideoView.resumeRendering();
}
@Override
protected void onDestroy() {
// Destroy the widget and free memory.
mVrVideoView.shutdown();
super.onDestroy();
}
5. 事件監(jiān)聽(tīng)
private VrVideoEventListener mVrEventListener = new VrVideoEventListener() {
@Override
public void onLoadError(String errorMessage) {
Toast.makeText(VrVideoActivity.this, "onLoadError", Toast.LENGTH_SHORT).show();
}
@Override
public void onLoadSuccess() {
Toast.makeText(VrVideoActivity.this, "onLoadSuccess", Toast.LENGTH_SHORT).show();
}
@Override
public void onNewFrame() {
}
@Override
public void onCompletion() {
Toast.makeText(VrVideoActivity.this, "onCompletion", Toast.LENGTH_SHORT).show();
mVrVideoView.seekTo(0);//播放結(jié)束后重新開(kāi)始播放
}
@Override
public void onClick() {
togglePause();//點(diǎn)擊暫停或者播放
}
};
Demo
該Demo簡(jiǎn)單展示了全景圖控件VrPanoramaView的使用矾麻,及其相關(guān)的基本的配置纱耻。
初始化VrPanoramaView
private void initPanoramaView() {
mVrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_panorama_view);
//mVrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_MONO);//全屏模式,彈出一個(gè)全屏的Dialog
mVrPanoramaView.setInfoButtonEnabled(false);//隱藏信息按鈕
mVrPanoramaView.setStereoModeButtonEnabled(false);//隱藏cardboard按鈕
mVrPanoramaView.setFullscreenButtonEnabled(false);//隱藏全屏按鈕
mUrl = getIntent().getStringExtra("url");
OkGo.get(mUrl).cacheKey(mUrl).tag(mUrl).execute(new BitmapCallback() {
@Override
public void onSuccess(Bitmap bitmap, Call call, Response response) {
VrPanoramaView.Options options = new VrPanoramaView.Options();
//設(shè)置圖片類(lèi)型為單通道圖片
options.inputType = VrPanoramaView.Options.TYPE_MONO;
mVrPanoramaView.loadImageFromBitmap(bitmap, options);
}
});
}
初始化MediaPlayer
/**
* 如果有音樂(lè)數(shù)據(jù)則播放音樂(lè)
*/
private void initMediaPlayer() {
String mp3 = getIntent().getStringExtra("mp3");
if (mp3 != null) {
mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.setDataSource(this, Uri.parse(mp3));
mMediaPlayer.setOnPreparedListener(mOnPreparedListener);
mMediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
}
繩命周期管理
@Override
protected void onResume() {
super.onResume();
mVrPanoramaView.resumeRendering();
}
@Override
protected void onPause() {
super.onPause();
mVrPanoramaView.pauseRendering();
if (mMediaPlayer != null) {
mMediaPlayer.pause();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mVrPanoramaView.shutdown();
OkGo.getInstance().cancelTag(mUrl);//取消請(qǐng)求
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}