揭开VR View之全景图的神秘面纱
来源:互联网 发布:怎么看端口号是什么 编辑:程序博客网 时间:2024/06/08 08:09
GoogleVR SDK简称GVR,在一些休闲娱乐、旅行观光或房地产类型的App中,我们可以通过VR技术动态添加内容来提升用户体验,让人们足不出户享受虚拟场景所带给的惊喜。这里以VR全景图为探索起点,让你不再对VR感到陌生,同时了解VR全景图实现细节。上图:
下面是针对VR全景视图官网案例做一些重要功能的介绍(VR全景图官网传送门):
全景图像规格(英文描述)
VR图像可以保存为PNG、JPEG、GIF,Google建议使用JPEG(可以尽可能的节省内存) ;
为了最大化性能和兼容设备,图像尺寸应该是2的倍数(例如,1024、2048或4096);
单个图像纵横比应为2:1(例如4096×2048) ;
立体图像纵横比应为1:1(例如4096×4096)。
如图:
支持平台和设备:PC端(Windows、 macOS、Linux、Unity),客户端(Android、iOS);苹果8以及以上、安卓API 19: Android 4.4 (KitKat)以及以上。
Panowidget————Google提供专门显示VR全景图的依赖库,所在包见下图:
该库中有三个常用类:
VrPanoramaRendererrenderer;//Vr全景图渲染类
VrPanoramaEventListener eventListener;//事件监听类,可以重写4个方法,详见java代码
全景图赋值方式一:
loadImageFromBitmap(Bitmapbitmap,com.google.vr.sdk.widgets.pano.VrPanoramaView.Optionsoptions)
赋值方式二:
将图片转换为byte[],这里以获取assets中图片资源为例,见完整java代码
loadImageFromByteArray(byte[]jpegImageData,com.google.vr.sdk.widgets.pano.VrPanoramaView.Optionsoptions)
可以使用到的Options参数:
public static final int TYPE_MONO = 1;
从gif中可以看到图像预先沿着水平轴360度进行渲染,垂直范围根据图像的宽高比来显示,(如果一个1000x250像素的图像,全景图水平将覆盖360x90度,垂直范围是-45至+45度)。
public staticfinal int TYPE_STEREO_OVER_UNDER = 2;
包含两个大小相等的投影全景图垂直叠加。顶部图像被显示给左眼、底部图像被显示给右眼,中间有一个黑色的圆,(如果一个1000x500像素的图像中给出(即1000x250像素/每个眼睛),全景将覆盖360x90度与垂直范围是-45至+45度)。
隐藏界面自带的按钮设置:
vrPanoramaView.setStereoModeButtonEnabled(false);//隐藏VR模式按钮
vrPanoramaView.setFullscreenButtonEnabled (false);//隐藏全屏模式按钮
vrPanoramaView.setInfoButtonEnabled(false);//隐藏信息按钮
VrPanoramaView继承关系图:
完整代码如下:
依赖引入:
compile'com.google.vr:sdk-panowidget:1.30.0'布局文件参考:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.google.vr.sdk.widgets.pano.VrPanoramaView android:id="@+id/vr_view" android:layout_width="match_parent" android:layout_height="match_parent" > </com.google.vr.sdk.widgets.pano.VrPanoramaView></RelativeLayout>
JAVA代码参考:
package com.android.vrpictureimport android.app.Activity;import android.graphics.Bitmap;import android.os.Bundle;import android.widget.Toast;import com.google.vr.sdk.widgets.pano.VrPanoramaEventListener;import com.google.vr.sdk.widgets.pano.VrPanoramaView;import java.io.ByteArrayOutputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;public class MainActivity extends Activity { /** * 定义VR 全景视图控件 */ private VrPanoramaView vrPanoramaView; /** * assets文件夹下的文件全称 */ private String fileUri = "sea.jpg"; /** * 创建一个bitmap */ private Bitmap bitmap=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); vrPanoramaView= (VrPanoramaView) findViewById(R.id.vr_view);//加载控件,防止空指针 /**设置加载VR图片的相关设置 **/ VrPanoramaView.Options options = new VrPanoramaView.Options(); options.inputType = VrPanoramaView.Options.TYPE_MONO ; vrPanoramaView.setStereoModeButtonEnabled(false);//隐藏全屏模式按钮 vrPanoramaView.setInfoButtonEnabled(false<span lang="EN-US" style="" color:"="">);//隐藏信息按钮/** * 控件赋值 */ vrPanoramaView.loadImageFromByteArray(imageToByte(fileUri),options); vrPanoramaView.setEventListener(new VrPanoramaEventListener(){ @Override public void onLoadSuccess() { super.onLoadSuccess(); Toast.makeText(MainActivity.this, "视图成功加载", Toast.LENGTH_SHORT<span lang="EN-US" style="" color:"="">).show(); } @Override public void onLoadError(String errorMessage) { super.onLoadError(errorMessage); Toast.makeText(MainActivity.this, "视图加载失败了", Toast.LENGTH_SHORT).show(); } @Override public void onClick() { super.onClick(); Toast.makeText(MainActivity.this, "点击了全景图", Toast.LENGTH_SHORT).show(); } /** * 显示模式改变回调 * 1.默认 * 2.全屏模式 * 3.VR观看模式,即横屏分屏模式 * @param newDisplayMode 模式 */ @Override public void onDisplayModeChanged(int newDisplayMode) { Toast.makeText(MainActivity.this, "显示模式改变了", Toast.LENGTH_SHORT).show(); } }); } //Assets中图片转byte数组 public byte[] imageToByte(String path){ byte[] data = null; InputStream input = null; ByteArrayOutputStream output = null; try { input = getAssets().open(path); output = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int numBytesRead = 0; while ((numBytesRead = input.read(buf)) != -1) { output.write(buf, 0, numBytesRead); } data = output.toByteArray(); } catch (FileNotFoundException ex1) { ex1.printStackTrace(); } catch (IOException ex1) { ex1.printStackTrace(); } finally { try { if (input != null) { input.close(); } if (output != null) { output.close(); } } catch (IOException e) { e.printStackTrace(); } } return data; } /** * 获得焦点,恢复3D渲染和跟踪 */ @Override protected void onResume() { super.onResume(); if (vrPanoramaView != null) { vrPanoramaView.resumeRendering(); } } //暂停3D渲染和跟踪 @Override protected void onPause() { super.onPause(); if (vrPanoramaView != null) { vrPanoramaView.pauseRendering(); } } /** * 销毁页面,释放资源 */ @Override protected void onDestroy() { vrPanoramaView.shutdown();//关闭渲染下并释放相关的内存 一定要在onDestroy()时调用。 /** * 如果图片不为空,且没有被系统GC,执行回收,释放资源 */ if(bitmap!=null && !bitmap.isRecycled()) { bitmap.recycle(); System.gc(); } super.onDestroy(); }}
github上有一个sdk-simplepanowidget——全景图Demo案例,大家可以下载参考,传送门直达,效果图参考如下:
总结:
- 一般来讲,在清单文件中不进行ConfigChanges配置,屏幕旋转时,Activity的生命周期会重新来过,但在对应的Activity中加入VrPanoramaView控件后,无论怎样旋转屏幕,Activity的生命周期只走一次,同时支持与Activity生命周期联动,亲测。
- VrPanoramaView内部自动调用陀螺仪传感器,不需要额外进行陀螺仪的配置。
- VrPanoramaView目前只在水平方向上支持触摸滑动。
- 揭开VR View之全景图的神秘面纱
- 揭开木马的神秘面纱
- 揭开Expect的神秘面纱
- 揭开IRC的神秘面纱
- 揭开Expect的神秘面纱
- 揭开木马的神秘面纱
- 揭开点穴的神秘面纱
- 揭开Winsock的神秘面纱
- 揭开SOCKET的神秘面纱
- 揭开主板的神秘面纱
- 揭开进程的神秘面纱
- 揭开Expect的神秘面纱
- 揭开MVC的神秘面纱
- 揭开计算机的神秘面纱
- 揭开计算机的神秘面纱
- 揭开Shellcode的神秘面纱
- 揭开LiteOS的神秘面纱
- 揭开runtime的神秘面纱
- Android字符串进阶之三:字体属性及测量(FontMetrics)
- Maven
- ACdream 1103 瑶瑶正式成为CEO (树链剖分+最小费用最大流)
- Android----------RecyclerView数据展示
- ssm整合的增删改查
- 揭开VR View之全景图的神秘面纱
- java代码使用ImageJ解析dicom文件成图片
- 给jqGrid表格某一列值添加点击事件
- java学习(1) 第一个java小程序运行解释
- ACM一类方程问题的求解[最短路建模] bzoj2118
- hdu1505—City Game(1506的加强版)
- CSAPP 第一章 计算机系统漫游
- CodeForces
- 出现如下错误服务器: 消息 544,级别 16,状态 1,行 1 当 IDENTITY_INSERT 设置为 OFF 时,不能向表 'OrderList' 中的标识列插入显式值。