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继承关系图:
package com.android.vrpicture
import 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);//隐藏信息按钮
/**
* 控件赋值
*/
vrPanoramaView.loadImageFromByteArray(imageToByte(fileUri),options);
vrPanoramaView.setEventListener(new VrPanoramaEventListener(){
@Override
public void onLoadSuccess() {
super.onLoadSuccess();
Toast.makeText(MainActivity.this, "视图成功加载", Toast.LENGTH_SHORT).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();
}
}
总结: