首页 > 其他分享 >Google VR技术大揭秘

Google VR技术大揭秘

时间:2022-12-27 17:06:59浏览次数:41  
标签:Google videoWidgetView void public mVrPanoramaView VR video Override 揭秘


VR

虚拟现实(Virtual Reality)技术是一种可以创建和体验虚拟世界的计算机仿真系统,它利用计算机生成一种模拟环境,是一种多源信息融合的、交互式的三维动态视景和实体行为的系统仿真, 使用户沉浸到该环境中。

VR产品

Google VR
​Oculus
​HTC Vivi

Google VR for Android

Google VR SDK同时支持DayDream和CardBoard。 包含了一些用于创建App的简单API和支持DayDream手机、DayDream控制器的复杂API。同时涵盖了Android、iOS、Unity三大平台。

SDK下载

sdk地址:

git clone https://github.com/googlevr/gvr-android-sdk.git

运行官网项目

在使用之前,我们先运行下官网的项目。导入gvr-android-sdk到Android Studio, 同步的过程中需要下载很多库所以会比较耗时,另外可能出现build失败的情况,这时可以尝试使用本地的gradle来编译。

gradle版本最好为最新版本。

Google VR技术大揭秘_sdk

项目展示了印加文明遗迹马丘比丘的全景图(Panorama):

Google VR技术大揭秘_android_02

在真机上运行时,会有一个Cardboard选项。点击上图红色框中的按钮即可进入Cardboard模式。

Google VR技术大揭秘_ide_03

Demo代码的主要逻辑就是加载一张全景图放入VrPanoramaView中。

panoOptions = new Options();
panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;//图像类型为立体图像
istr = assetManager.open("andes.jpg");//加载assets目录下的全景图
panoWidgetView.loadImageFromBitmap(BitmapFactory.decodeStream(istr), panoOptions);

全景图片andes是由两张图片组成,上面一张是给左眼看,下面一张是给右眼看。

Google VR技术大揭秘_android_04

Demo的声音的实现是加载assets目录下的congo.mp4视频到VrVideoView中。

videoWidgetView.loadVideoFromAsset("congo.mp4", options);

congo.mp4的视频内容也是分为上下部分,上面给左眼看,下面给右眼看。

treasurehunt

treasurehunt展示了一个简单到离谱的寻宝游戏,当vr世界中矩形变成金黄色时,点击手机屏幕或者使用Daydream的控制器,即可完成寻宝。游戏还伴有音效。

Google VR技术大揭秘_ide_05

controllerclient

接收DayDream控制器输入示例

videoplayer

使用Asynchronous Reprojection播放视频示例

全景图(PanoramaActivity)

1. 配置build.gradle

//修改minSDK为19
minSdkVersion 19
//添加依赖
compile 'com.google.vr:sdk-panowidget:1.20.0'

2. 配置AndroidManifest.xml

由于全景图占内存较大,当加载多张全景图时可能存在内存溢出的情况,所以这里开启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();
//图片类型为立体图像
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. 事件监听

mVrPanoramaView.setEventListener(mVrPanoramaEventListener);

private VrPanoramaEventListener mVrPanoramaEventListener = new VrPanoramaEventListener() {
/**
* 点击回调
*/
@Override
public void onClick() {
super.onClick();
}

/**
* 加载数据成功回调
*/
@Override
public void onl oadSuccess() {
super.onLoadSuccess();
}

/**
* 加载数据失败回调
*/
@Override
public void onl oadError(String errorMessage) {
super.onLoadError(errorMessage);
}
};

360 视频

1. 配置build.gradle

//添加依赖//
minSdkVersion 19
//已经配置则忽略
compile 'com.google.vr:sdk-videowidget:1.20.0'

2. 配置AndroidManifest.xml (已经配置则忽略)

<application android:largeHeap="true"></application>

3. 加载视频

VrVideoView.Options options = new VrVideoView.Options();
//视频类型为立体视频
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. 事件监听

private VrVideoEventListener mVrEventListener = new VrVideoEventListener() {

@Override
public void onl oadError(String errorMessage) {
Toast.makeText(VrVideoActivity.this, "onLoadError", Toast.LENGTH_SHORT).show();
}

@Override
public void onl oadSuccess() {
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);//播放结束后重新开始播放
}

@Override
public void onClick() {
togglePause();//点击暂停或者播放
}
};

Demo

Google VR技术大揭秘_虚拟现实_06

本demo实现一个全景图控制显示的效果。这里主要演示下VrPanoramaView控件的使用。

初始化VrPanoramaView

private void initPanoramaView() {
mVrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_panorama_view);
//mVrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_MONO);//全屏模式,弹出一个全屏的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();
//设置图片类型为单通道图片
options.inputType = VrPanoramaView.Options.TYPE_MONO;
mVrPanoramaView.loadImageFromBitmap(bitmap, options);
}
});
}

初始化MediaPlayer

/**
* 如果有音乐数据则播放音乐
*/
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);//取消请求
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}

VR View

VR View允许开发者在网站或app中嵌入360度全景多媒体文件(图片和视频)。这个技术主要是提供给传统的开发者,可以通过在app中添加动态内容来提升用户体验。比如旅行或房地产类型的app,可以让用户足不出户就体验到虚拟场景。VR View同时支持web和Native app。
VR View同时支持单声道和立体声的图片和视频,但是图片和视频的存储格式必须为equirectangular-panoramic格式,这是一种常见的摄像头尺寸支持的格式。
VR view是客户端的显示技术,那么我们怎么去拍摄符合VR view要求的内容呢?

真实世界中的拍摄

Cardboard Camera App​ ,用这个app可以和方便的拍摄360照片,拍摄完成后需要通过conversion tool来创建一个立体声的360照片。

Ricoh Theta 一个非常流行的,相对廉价的用来拍摄单声道相片和视频的设备。

1,CG 拍摄
VR view的图片不仅仅限制在真实世界中拍摄。CGI(计算机合成图像)可以为所有的东西生成360度全景照片和视频,最流行拍摄解决方案如下:

360 Panorama Capture for Unity​ Unity插件
​Unreal​ 虚幻引擎
​Domemaster3D for Maya
​Renderman​ 一个开源库
​Rendering Omnidirectional Stereo Content

下面用伪代码展示如何用VrPanoramaView和VrVideoView展示360度图片和视频。

<com.google.vr.sdk.widgets.pano.VrPanoramaView
android:id="@+id/pano_view"
android:layout_margin="5dip"
android:layout_width="match_parent"
android:scrollbars="@null"
android:layout_height="250dip"/>

<com.google.vr.sdk.widgets.video.VrVideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:scrollbars="@null"
android:layout_height="250dip"/>
//展示全景图片
panoWidgetView = (VrPanoramaView) findViewById(R.id.pano_view);
//图片加载结果回调
private class ActivityEventListener extends VrPanoramaEventListener {
/**
* Called by pano widget on the UI thread when it's done loading the image.
*/
@Override
public void onl oadSuccess() {
loadImageSuccessful = true;
}

/**
* Called by pano widget on the UI thread on any asynchronous error.
*/
@Override
public void onl oadError(String errorMessage) {
loadImageSuccessful = false;
Toast.makeText(
SimpleVrPanoramaActivity.this, "Error loading pano: " + errorMessage, Toast.LENGTH_LONG)
.show();
Log.e(TAG, "Error loading pano: " + errorMessage);
}
}
//设置图片加载监听
panoWidgetView.setEventListener(new ActivityEventListener());

//加载图像的Bitmap数据 istr是一个文件输入流
//VrPanoramaView.Options是用来配置图片格式的
// TYPE_MONO 包含单一圆柱的全景图像
// TYPE_STEREO_OVER_UNDER 图像包含了两个大小相等、垂直相交的圆柱全景图像。上图展示给左眼,下图展示给右眼。
panoWidgetView.loadImageFromBitmap(BitmapFactory.decodeStream(istr), panoOptions);


//展示全景视频
videoWidgetView = (VrVideoView) findViewById(R.id.video_view);
videoWidgetView.setEventListener(new ActivityEventListener());
//VrVideoEventListener同时对视频加载和操作的回调
private class ActivityEventListener extends VrVideoEventListener {
/**
* Called by video widget on the UI thread when it's done loading the video.
*/
@Override
public void onl oadSuccess() {
Log.i(TAG, "Sucessfully loaded video " + videoWidgetView.getDuration());
loadVideoStatus = LOAD_VIDEO_STATUS_SUCCESS;
seekBar.setMax((int) videoWidgetView.getDuration());
updateStatusText();
}

/**
* Called by video widget on the UI thread on any asynchronous error.
*/
@Override
public void onl oadError(String errorMessage) {
// An error here is normally due to being unable to decode the video format.
loadVideoStatus = LOAD_VIDEO_STATUS_ERROR;
Toast.makeText(
SimpleVrVideoActivity.this, "Error loading video: " + errorMessage, Toast.LENGTH_LONG)
.show();
Log.e(TAG, "Error loading video: " + errorMessage);
}

@Override
public void onClick() {
togglePause();
}

/**
* Update the UI every frame.
*/
@Override
public void onNewFrame() {
updateStatusText();
seekBar.setProgress((int) videoWidgetView.getCurrentPosition());
}

/**
* Make the video play in a loop. This method could also be used to move to the next video in
* a playlist.
*/
@Override
public void onCompletion() {
videoWidgetView.seekTo(0);
}
}
//支持两种加载方式,从asset文件夹中或从一个uri中读取视频数据
//VrVideoView.Options同样是用来配置视频格式的
videoWidgetView.loadVideoFromAsset("congo.mp4", options);

videoWidgetView.loadVideo(fileInformation[0].first, fileInformation[0].second)

//除此外还有一些控制渲染、播放的方法:
videoWidgetView.pauseRendering();
videoWidgetView.resumeRendering();
videoWidgetView.shutdown();
videoWidgetView.playVideo();
videoWidgetView.pauseVideo();

//shutdown()一定要在onDestroy()时调用,用来释放占用内存。


标签:Google,videoWidgetView,void,public,mVrPanoramaView,VR,video,Override,揭秘
From: https://blog.51cto.com/u_13657808/5972979

相关文章

  • Android NDK下编译google protocol buffer(protobuf)
    前面发了一片windows下编译protobuf的文章后来把生成的.a文件加到android工程后发现不可用所以只好自己使用NDK编译protobuf了(虽然这样,生成的Inclule的头文件还是很有用......
  • 小游戏变现方式大揭秘!
    随着羊了个羊等小游戏的爆火,不少人发现了小游戏赛道的巨大潜力,也想要在此赛道有所尝试。但是很多游戏赛道的新人对于小游戏变现问题存有疑问,今天就来跟大家分享一下小程序游......
  • VR应急安全生产定制,交互式情景模拟创新教学方式
    安全问题存在于社会各行各业、各个环节之中,职工的安全教育是保证运输生产安全的关键,持久地开展安全教育和培训工作能够有效降低伤亡数量。目前传统的安全培训存在着众多的......
  • 揭秘:CIO走向成功的十二条秘笈
    本人与众多成功的CIO进行了交流,并分析其成功之处,得出了共性的十二条成功秘笈,供大家参考。1、管理好IT供应商一个企业经过大规模的信息化建设后,企业对IT的投入将会减少,在......
  • 使用 Google Cloud Pub/Sub 发送消息
    本指南将引导您完成在程序的不同部分或不同程序之间交换消息的过程,使用弹簧集成通道适配器和谷歌云发布/订阅作为底层消息交换机制。您将构建的内容一个弹簧启动向自身发送......
  • 广播 goAsync 源码分析,为什么 Google 大佬都在使用它
    hi大家好,我是DHL。公众号:ByteCode,专注有用、有趣的硬核原创内容,Kotlin、Jetpack、性能优化、系统源码、算法及数据结构、大厂面经。近期在分析问题过程中,需要反编译Goog......
  • 改进差分进化算法求解容量受限的车辆路径(CVRP)问题MATLAB代码
    ​​▎​​​​号内搜索​​hello,大家好。各位可点击上方号内搜索搜索往期推文,点击左下方阅读原文,即可访问公众号官方店铺。谨防上当受骗,感谢各位支持!在​​改进差分进化算......
  • 《基于赛朋风格的 VR 射击游戏的设计与开发》读后随笔
    VR技术利用计算机将现实生活中数据模拟的一种环境,使用户沉浸到环境中,能感受到人类在真实事境中的听觉、嗅觉、触觉和味觉等一切感知功能,具有超强的仿真系统,真正地......
  • 《基于VR技术的运动健身游戏》读后随笔
    随着计算机图形学、计算机系统工程等技术的告诉发展,虚拟现实已得到国家有关部门和科学家们的高度重视,引起我过各界人士的关注,研究与应用。在快节奏的当今社会,许多针对健......
  • 《探究游戏设计中VR技术的优势与实践应用》读后随笔
    VR技术是结合计算机应用、多媒体、信息技术和仿真技术等综合在一起的应用型技术,在广告、体育、游戏设计等多个领域都有着广阔的市场发展空间。目前在美国和欧洲等发达国家......