当前位置:   article > 正文

Daydream VR入门基础教程,通过GVR示例SimpleVrPanorama制作VR全景图形应用_import com.google.vr.sdk.widgets.pano.vrpanoramaev

import com.google.vr.sdk.widgets.pano.vrpanoramaeventlistener; import com.go

前言

前两篇介绍了Daydream Android VR开发环境的搭建和官方VR Demo寻宝游戏的演示,这篇我们来一起研究下示例项目SimpleVrPanorama,同时通过了解它来了解如何开发一款VR全景图形应用。
--------------------------------------------------------------------------------------------------------------------
Daydream快速入门开发基础教程一:Android端开发环境配置一
Daydream快速入门开发基础教程二:Android端开发环境配置二
--------------------------------------------------------------------------------------------------------------------

SimpleVrPanorama例子介绍

SimpleVrPanorama VR 运行后效果图如下,运行效果有两种,分别是全景效果和分屏效果,分屏效果主要用于Cardboard纸盒(尝试录制gif,发现太大了,无法上传,只能这样了):
全景效果:

分屏效果(Cardboard纸盒模式):

很简单的一个Demo,就是一张“安第斯山脉”全景图,没有其他交互,内容也没什么好说的,你可以转动头部查看四周的环境,受制于手机硬件配置,不同的设备在转动时,延迟可能不同,反正我的测试机对VR的体验不算太好,是时候换个pixel XL或华为Mate9了。

VR view简单介绍

接下来我们来研究下它的源代码,整个APP模块的结构如下:


整体上没多少东西,注意看下assets资源文件夹中有个andes.jpg,也就是我们的“安第斯山脉”全景图了,打开图片看看,也就是我们在APP中看到的全景效果:


为什么是两张一模一样的呢?因为这是分别给左右眼观看的,遵循了VR view视图的基本规则,关于VR view,VR view是Google在2016年4月推出的一个VR基本概念,是一种“客户端”VR显示技术,可将 360 度照片或视频部署在各种设备上的简易方式,本篇文章就不做详细介绍了,想了解的请看看这篇Blog:
--------------------------------------------------------------------------------------------------------------------
Daydream VR入门基础教程,VR开发基础知识——VR view基本介绍
--------------------------------------------------------------------------------------------------------------------

源码研究

首先还是我们还是先从程序的入口Manifest文件看看有什么:
  1. <application android:label="SimpleVrPanoramaActivity"
  2. android:largeHeap="true"
  3. android:theme="@android:style/Theme.Holo.Light">
  4. <!-- This demo is singleTask since it makes launching via custom adb intents easier. -->
  5. <activity android:name=".SimpleVrPanoramaActivity"
  6. android:launchMode="singleTask">
  7. <intent-filter>
  8. <!-- Primary intent when launching from the home screen -->
  9. <action android:name="android.intent.action.MAIN" />
  10. <category android:name="android.intent.category.LAUNCHER" />
  11. <category android:name="com.google.intent.category.CARDBOARD" />
  12. </intent-filter>
  13. </activity>
  14. </application>
  15. <!-- These permissions are used by Google VR SDK to get the best Google VR headset profiles. !-->
  16. <uses-permission android:name="android.permission.INTERNET" />
  17. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
没什么特别的东西,可以看到主要用到的权限:
 ●  android.permission.INTERNET : 获取网络权限
 ●  android.permission.READ_EXTERNAL_STORAGE  : 读取拓展内容。
intent-filter过滤分类:
 ●   com.google.intent.category.CARDBOARD  : 兼容Cardboard纸盒

然后看看布局文件main_layout.xml:
  1. <com.google.vr.sdk.widgets.pano.VrPanoramaView
  2. android:id="@+id/pano_view"
  3. android:layout_margin="5dip"
  4. android:layout_width="match_parent"
  5. android:scrollbars="@null"
  6. android:layout_height="250dip"/>
整个布局文件中唯一特别的就是这个VrPanoramaView了,也就是VR全景视图组件。
com.google.vr.sdk.widgets.pano : VR全景视图组件,也就是在项目的libraries-panowidget模块下。

它在gradle中被引用:
  1. dependencies {
  2. compile project(':libraries-common') //Google VR API的公共代码。
  3. compile project(':libraries-commonwidget') //Google VR API的公共组件。
  4. compile project(':libraries-panowidget') //VR全景视图组件
  5. compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7' //序列化数据结构的方案
  6. }

然后我们看看主代码(官方代码过于冗余,为方便新人理解学习,修改成如下):
  1. package com.google.vr.sdk.samples.simplepanowidget;
  2. import android.app.Activity;
  3. import android.graphics.BitmapFactory;
  4. import android.os.AsyncTask;
  5. import android.os.Bundle;
  6. import android.util.Log;
  7. import android.util.Pair;
  8. import com.google.vr.sdk.widgets.pano.VrPanoramaEventListener;
  9. import com.google.vr.sdk.widgets.pano.VrPanoramaView;
  10. import com.google.vr.sdk.widgets.pano.VrPanoramaView.Options;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. public class SimpleVrPanoramaActivity extends Activity {
  14. private static final String TAG = "SimpleVrPanoramaActivity";
  15. private VrPanoramaView panoWidgetView;//VR全景图形组件
  16. private String fileUri = "andes.jpg";//assets文件夹下的文件名
  17. private Options panoOptions = new Options();//VrPanoramaView需要的设置
  18. private ImageLoaderTask backgroundImageLoaderTask;//异步加载图片
  19. @Override
  20. protected void onCreate(Bundle savedInstanceState) {
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.main_layout);//获取布局
  23. panoWidgetView = (VrPanoramaView) findViewById(R.id.pano_view);//初始化VrPanoramaView
  24. panoWidgetView.setEventListener(new ActivityEventListener());//为VrPanoramaView添加监听
  25. //如果有任务在执行则停止它
  26. if (backgroundImageLoaderTask != null) {
  27. backgroundImageLoaderTask.cancel(true);
  28. }
  29. //设置inputType 为TYPE_STEREO_OVER_UNDER. 在后面会介绍TYPE_STEREO_OVER_UNDER的,暂时当做一个图片的显示类型就行
  30. panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;
  31. //创建图片异步加载任务
  32. backgroundImageLoaderTask = new ImageLoaderTask();
  33. //执行任务。将图片名(根据项目实际情况传吧)和设置传入
  34. backgroundImageLoaderTask.execute(Pair.create(fileUri, panoOptions));
  35. }
  36. //异步任务
  37. class ImageLoaderTask extends AsyncTask<Pair<String, Options>, Void, Boolean> {
  38. @Override
  39. protected Boolean doInBackground(Pair<String, Options>... fileInformation) {//真正写项目根据情况添加条件判断吧
  40. InputStream istr = null;
  41. try {
  42. istr = getAssets().open(fileInformation[0].first);//获取图片的输入流
  43. } catch (IOException e) {
  44. Log.e(TAG, "Could not decode default bitmap: " + e);
  45. return false;
  46. }
  47. Bitmap bitmap = BitmapFactory.decodeStream(istr);//创建bitmap
  48. panoWidgetView.loadImageFromBitmap(bitmap, fileInformation[0].second);//参数一为图片的bitmap,参数二为 VrPanoramaView 所需要的设置
  49. try {
  50. istr.close();//关闭InputStream
  51. } catch (IOException e) {
  52. Log.e(TAG, "Could not close input stream: " + e);
  53. }
  54. return true;
  55. }
  56. }
  57. private class ActivityEventListener extends VrPanoramaEventListener {
  58. @Override
  59. public void onLoadSuccess() {//图片加载成功
  60. Log.e(TAG, "onLoadSuccess");
  61. }
  62. @Override
  63. public void onLoadError(String errorMessage) {//图片加载失败
  64. Log.e(TAG, "Error loading pano: " + errorMessage);
  65. }
  66. @Override
  67. public void onClick() {//当我们点击了VrPanoramaView 时候出发
  68. super.onClick();
  69. Log.e(TAG, "onClick");
  70. }
  71. @Override
  72. public void onDisplayModeChanged(int newDisplayMode) {//改变显示模式时候出发(全屏模式和纸板模式)
  73. super.onDisplayModeChanged(newDisplayMode);
  74. Log.e(TAG, "onDisplayModeChanged");
  75. }
  76. }
  77. @Override
  78. protected void onPause() {
  79. panoWidgetView.pauseRendering();//暂停3D渲染和跟踪
  80. super.onPause();
  81. }
  82. @Override
  83. protected void onResume() {
  84. super.onResume();
  85. panoWidgetView.resumeRendering();//恢复3D渲染和跟踪
  86. }
  87. @Override
  88. protected void onDestroy() {
  89. panoWidgetView.shutdown();//关闭渲染下并释放相关的内存
  90. if (backgroundImageLoaderTask != null) {
  91. backgroundImageLoaderTask.cancel(true);//停止异步任务
  92. }
  93. super.onDestroy();
  94. }
  95. }
代码很简单,流程就是获取VrPanoramaView组件——添加事件监听——异步载入图片。
如果想要隐藏VrPanoramaView组件的按钮:

  1. panoWidgetView.setFullscreenButtonEnabled(false); // 是否启用全屏按钮
  2. panoWidgetView.setStereoModeButtonEnabled(false); // 是否启用纸盒按钮

了解Options
这是设置Options的两个主要属性:
  1. //图像被预期以覆盖沿着其水平轴360度,而垂直范围是根据图像的宽高比来计算。例如,如果一个1000x250像素的图像,给出所述全景将覆盖360x90度与垂直范围是-45至+45度。
  2. public static final int TYPE_MONO = 1;
  3. //包含两个大小相等的投影 全景图垂直叠加。顶部图像被显示给左眼、底部图像被显示给右眼。
  4. 图像将覆盖沿水平轴360度,而垂直范围是根据图像的宽高比来计算。例如,如果一个1000x500像素的图像中给出(即1000x250像素每个眼睛),全景将覆盖360x90度与垂直范围是-45至+45度。
  5. public static final int TYPE_STEREO_OVER_UNDER = 2;
也就是上面VR view文章中介绍的(360度单图和立体图),想实现左边的效果设置为TYPE_MONO,右边的设置为TYPE_STEREO_OVER_UNDER:

Options的源代码:
  1. public static class Options {
  2. private static final int TYPE_START_MARKER = 0;//起始标记
  3. public static final int TYPE_MONO = 1;
  4. public static final int TYPE_STEREO_OVER_UNDER = 2;
  5. private static final int TYPE_END_MARKER = 3;//结束标记
  6. public int inputType = 1;//默认为一
  7. public Options() {
  8. }
  9. void validate() {
  10. if(this.inputType <= 0 || this.inputType >= 3) {//标记错误处理
  11. String var10000 = VrPanoramaView.TAG;
  12. int var1 = this.inputType;
  13. Log.e(var10000, (new StringBuilder(38)).append("Invalid Options.inputType: ").append(var1).toString());
  14. this.inputType = 1;
  15. }
  16. }
  17. }

如何开发一款VR图形全景应用

通过研究SimpleVrPanorama的源代码,我们来总结下如何通过GVR的安卓SDK在Android Studio上开发一款VR图形全景应用:
 ●  在Gradle模块中引用GVR的库,如compile project(':libraries-panowidget')。
 ●  准备好遵循VR view基本准则的全景图片。
 ●  在布局XML中添加com.google.vr.sdk.widgets.pano.VrPanoramaView控件。
 ●  在主代码中初始化VrPanoramaView控件,并设置options模式。
 ●  调用VrPanoramaView的loadImageFromBitmap方法异步加载图片
 ●  在onPause、onResume、onDestroy中做出相应处理

通过对 SimpleVrPanorama示例项目的研究,我们理解了Android VR图形全景应用的开发方式 ,所以我们不难理解,在Gvr-Android-SDK源代码内的另外一个示例项目 samples-sdk-simplevideowidget也是同样的道理,只不过它是对VR全景视频的应用,视频格式也是遵循VR view的基本准则。如果有时间,我会写一篇关于simplevideowidget的应用和研究,看看如何通过gvr创建Android全景视频应用。

一起探讨

Daydream相关学习技术交流群,有什么最新的技术和教程以及VR开发工具等会第一时间在群内发布, 欢迎广大VR爱好者的加入:
①群号:418310684
点此加入: Google DayDream


声明

欢迎转载,但请保留文章原始出处
作者:Jaiky_杰哥 
出处:http://blog.csdn.net/jaikydota163/article/details/53048273

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/530951
推荐阅读
相关标签
  

闽ICP备14008679号