編輯:關於Android編程
其實這篇應該寫SimpleVrPanorama和simplevideowidget 兩個,但是由於篇幅過長就分開寫了
用AS錄的沒有觸摸點顯示,先湊合看吧
官方在這裡介紹了VR view 、支持平台等。我挑幾個相對重要的介紹一下:
1、圖像規格
VR查看圖像可以保存為PNG,JPEG或GIF。Google建議使用JPEG改進壓縮。
為了獲得最大的兼容性和性能,圖像尺寸應該是2的倍數(例如,2048或4096)。
單個圖像應為2:1縱橫比(例如4096×2048)。
立體圖像應為1:1縱橫比(例如4096×4096)。
如圖:
2、 視頻規格
VR view視頻應該被存儲為H264編碼的mp4文件。
單個視頻應是2:1縱橫比。
立體視頻應是1:1縱橫比。
一些較舊的設備不能解碼的視頻最大不能超過超過1080(192??0×1080)。最大的兼容性和質量是頭等大事,Google建議用戶同時提供平面視覺1920x1080的視頻和2048×2048處以上的立體視頻。
3、如何錄制VR視頻
生活中拍攝:
360度拍攝的照片和視頻越來越方便和實惠。 VR視圖可以使用由支持上述equirect-全景格式的任何攝像機產生的圖像。對於有興趣在快速入門用戶來說,我們最喜歡的解決方案如下:
Cardboard Camera App:這個免費的Andr??oid應用程序,允許用戶快速捕捉立體圖像360。
Ricoh Theta:一個非常流行的,用於捕獲單360度的圖像和視頻相對廉價的解決方案。
CG(計算機動畫)拍攝:
遙感影像數據的VR觀點並沒有從現實世界限於捕獲。 CGI軟件可以生成360圖像和視頻,一切從建築到演練預演的電影。我們的一些最流行的捕獲解決方案的列舉如下:
360 Panorama Capture for Unity:一個免費的,易於使用的360捕獲了Unity插件。
Unreal(虛幻):UE4的最新版本內置了360捕獲解決方案。
Domemaster3D for Maya :從瑪雅捕獲單聲道和立體聲圖像360免費的解決方案。
Renderman:開源庫,用於捕捉360的內容。
Rendering Omnidirectional Stereo Content:一個有興趣的人都在書寫自己360捕獲解決方案白皮書。
Android平台
在這裡官方有這Android平台的詳細介紹,主要內容如下:
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxjb2RlPjxjb2RlPsirxsHEo8q9o7o8YnIgLz4NCjxpbWcgYWx0PQ=="這裡寫圖片描述" src="/uploadfile/Collfiles/20160806/20160806091707947.jpg" title="\" />有這表明在官方SDK中的VR View 功能的兩個示例應用程序:simplepanowidget和simplevideowidget。這兩個樣品的是顯示分別使用VrPanoramaView和VrVideoView嵌入全景圖像和視頻。
允許用戶通過旋轉他們的電話,看全景的不同部分。
simplevideowidget示例還允許用戶暫停(點擊 VR View就暫停了。 VR View也就是視頻那個區域),可以使用進度條改變進度。允許用戶更改模式,分別是全屏模式和紙板模式。
紙板模式:
代碼分析
(^_^ 為了方便學習與理解,基於官方Demo的代碼進行了修改 )
前言
這個栗子中需要注意幾個知識點:
VrPanoramaView //Google提供給我們現實全景圖片的View
Options //VrPanoramaView 所需的設置
VrPanoramaEventListener//為 VrPanoramaView 設置監聽
loadImageFromBitmap//加載圖片的主要方法
AndroidManifest
build.gradle
上一篇文章有介紹到這些庫
dependencies {
compile project(':libraries-common')
compile project(':libraries-commonwidget')
compile project(':libraries-panowidget')
}
布局文件
只有一個主要標簽
SimpleVrPanoramaActivity
正題來了~
看下我為了本次學習更改過的代碼:
不了解Pair的請看這裡: http://blog.csdn.net/qq_24889075/article/details/52127398
package com.google.vr.sdk.samples.simplepanowidget;
import android.app.Activity;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.Pair;
import com.google.vr.sdk.widgets.pano.VrPanoramaEventListener;
import com.google.vr.sdk.widgets.pano.VrPanoramaView;
import com.google.vr.sdk.widgets.pano.VrPanoramaView.Options;
import java.io.IOException;
import java.io.InputStream;
public class SimpleVrPanoramaActivity extends Activity {
private static final String TAG = "VrPanorama";
private VrPanoramaView panoWidgetView;//上面說的Google提供給我們現實全景圖片的View
private String fileUri = "first.jpg";//assets文件夾下的文件名
private Options panoOptions = new Options();//VrPanoramaView需要的設置
private ImageLoaderTask backgroundImageLoaderTask;//異步加載圖片
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);//布局上面貼了
panoWidgetView = (VrPanoramaView) findViewById(R.id.pano_view);//初始化VrPanoramaView
panoWidgetView.setEventListener(new ActivityEventListener());//為VrPanoramaView添加監聽
//如果有任務在執行則停止它
if (backgroundImageLoaderTask != null) {
backgroundImageLoaderTask.cancel(true);
}
//設置inputType 為TYPE_STEREO_OVER_UNDER. 在後面會介紹TYPE_STEREO_OVER_UNDER的,暫時當做一個圖片的顯示類型就行
panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;
//創建一個任務
backgroundImageLoaderTask = new ImageLoaderTask();
//執行任務。將圖片名(根據項目實際情況傳吧)和設置傳入
backgroundImageLoaderTask.execute(Pair.create(fileUri, panoOptions));
}
//異步任務
class ImageLoaderTask extends AsyncTask, Void, Boolean> {
@Override
protected Boolean doInBackground(Pair... fileInformation) {//真正寫項目根據情況添加條件判斷吧
InputStream istr = null;
try {
istr = getAssets().open(fileInformation[0].first);//獲取圖片的輸入流
} catch (IOException e) {
Log.e(TAG, "Could not decode default bitmap: " + e);
return false;
}
Bitmap bitmap = BitmapFactory.decodeStream(istr);//創建bitmap
panoWidgetView.loadImageFromBitmap(bitmap, fileInformation[0].second);//參數一為圖片的bitmap,參數二為 VrPanoramaView 所需要的設置
try {
istr.close();//關閉InputStream
} catch (IOException e) {
Log.e(TAG, "Could not close input stream: " + e);
}
return true;
}
}
private class ActivityEventListener extends VrPanoramaEventListener {
@Override
public void onLoadSuccess() {//圖片加載成功
Log.e(TAG, "onLoadSuccess");
}
@Override
public void onLoadError(String errorMessage) {//圖片加載失敗
Log.e(TAG, "Error loading pano: " + errorMessage);
}
@Override
public void onClick() {//當我們點擊了VrPanoramaView 時候出發
super.onClick();
Log.e(TAG, "onClick");
}
@Override
public void onDisplayModeChanged(int newDisplayMode) {//改變顯示模式時候出發(全屏模式和紙板模式)
super.onDisplayModeChanged(newDisplayMode);
Log.e(TAG, "onDisplayModeChanged");
}
}
@Override
protected void onPause() {
panoWidgetView.pauseRendering();//暫停3D渲染和跟蹤
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
panoWidgetView.resumeRendering();//恢復3D渲染和跟蹤
}
@Override
protected void onDestroy() {
panoWidgetView.shutdown();//關閉渲染下並釋放相關的內存
if (backgroundImageLoaderTask != null) {
backgroundImageLoaderTask.cancel(true);//停止異步任務
}
super.onDestroy();
}
}
看完了有木有感覺炒雞簡單啊?現在你已經掌握了如何使用 VrPanoramaView 了吧。
用 VrPanoramaView 的確簡單,但是局限性特別大,後面有機會 會詳細說的。
再介紹下代碼中沒提到的兩個方法:
setFullscreenButtonEnabled (false); //隱藏全屏模式按鈕
setVrModeButtonEnabled(false); //隱藏VR模式按鈕
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像素的圖像中給出(即1000x250像素每個眼睛),全景將覆蓋360x90度與垂直范圍是-45至+45度。
我要顯示的圖片是下圖這樣的,所以就要設置為 ‘TYPE_STEREO_OVER_UNDER’
那麼什麼樣的圖片設置為 ‘TYPE_MONO’ 呢?
請看:
不知道有沒有眼神好的同學發現這個問題:TYPE_STEREO_OVER_UNDER類型的圖片每次切換模式時候 圖片中間都會有一條垂直於水平線的分割線(很淺 很淺 然後逐漸消失),TYPE_MONO 就沒有 ^_^
Options類中的代碼也十分簡單
public static class Options {
private static final int TYPE_START_MARKER = 0;//起始標記
public static final int TYPE_MONO = 1;
public static final int TYPE_STEREO_OVER_UNDER = 2;
private static final int TYPE_END_MARKER = 3;//結束標記
public int inputType = 1;//默認為一
public Options() {
}
void validate() {
if(this.inputType <= 0 || this.inputType >= 3) {//標記錯誤處理
String var10000 = VrPanoramaView.TAG;
int var1 = this.inputType;
Log.e(var10000, (new StringBuilder(38)).append("Invalid Options.inputType: ").append(var1).toString());
this.inputType = 1;
}
}
}
調皮的你如果在loadImageFromBitmap(bitmap,options)方法中 將options不小心設置為null了,也沒關系。我在源碼中我發現下面的代碼,感覺挺溫馨的
public void loadImageFromBitmap(Bitmap bitmap, VrPanoramaView.Options options) {
//有木有那裡暖暖的 ^_^
if(options == null) {
options = new VrPanoramaView.Options();
} else {
options.validate();
}
//重點不在這裡 可以無視它
this.renderer.loadImageFromBitmap(bitmap, options, this.eventListener);
}
至此com.google.vr.sdk.widgets.common包、com.google.vr.sdk.widgets.pano包和com.google.vr.sdk.widgets.video包(代碼下一篇介紹) 的主要內容都介紹完了,總結下吧
總結
總結下如何在Android設備上用Google的SDK做一款全景圖的顯示器(播放器?查看器?… 不知道叫什麼合適):
導入google的庫 在相應的布局文件中引入控件 com.google.vr.sdk.widgets.pano.VrPanoramaView 初始化控件 為VrPanoramaView設置options 找到圖片的Bitmap 調用VrPanoramaView的loadImageFromBitmap方法 在onPause、onResume、onDestroy中做出相應處理
最近比較忙,而且又要維護自己的博客,視頻和公眾號,也就沒仔細的梳理源碼的入門邏輯,今天也就來講一個源碼的玩法,各位看官,一起學習學習! 參考資料 官方教程:http:/
ROOT幾乎成了安卓手機發燒友不可不做的一道程序。常在河邊走,哪能不濕鞋。即使是老手,也能碰到root失敗的情況。那為什麼手機root失敗?刷機精靈root
正如我們知道的,android是不讓在子線程中更新ui的。在子線程中更新ui會直接拋出異常Only the original thread that created a
先看看效果圖:首先是布局文件<FrameLayout android:layout_width=match_parent android:layout_margin