VR

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

附:Wikipedia

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版本号最好为最新版本号。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhbmd6aGlob25nOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">

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

在真机上执行时。会有一个Cardboard选项。点击上图红色框中的button就可以进入Cardboard模式。

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是由两张图片组成,上面一张是给左眼看。以下一张是给右眼看。

Demo的声音的实现是载入assets文件夹下的congo.mp4视频到VrVideoView中。

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

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

treasurehunt

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

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 onLoadSuccess() {
super.onLoadSuccess();
} /**
* 载入数据失败回调
*/
@Override
public void onLoadError(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 onLoadError(String errorMessage) {
Toast.makeText(VrVideoActivity.this, "onLoadError", Toast.LENGTH_SHORT).show();
} @Override
public void onLoadSuccess() {
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

本demo实现一个全景图控制显示的效果。

这里主要演示下VrPanoramaView控件的使用。

初始化VrPanoramaView

private void initPanoramaView() {
mVrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_panorama_view);
//mVrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_MONO);//全屏模式,弹出一个全屏的Dialog
mVrPanoramaView.setInfoButtonEnabled(false);//隐藏信息button
mVrPanoramaView.setStereoModeButtonEnabled(false);//隐藏cardboardbutton
mVrPanoramaView.setFullscreenButtonEnabled(false);//隐藏全屏button
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 onLoadSuccess() {
loadImageSuccessful = true;
} /**
* Called by pano widget on the UI thread on any asynchronous error.
*/
@Override
public void onLoadError(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 onLoadSuccess() {
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 onLoadError(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()时调用,用来释放占用内存。

附:VRDemo

Google VR技术大揭秘的更多相关文章

  1. 【腾讯Bugly干货分享】iOS黑客技术大揭秘

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5791da152168f2690e72daa4 “8小时内拼工作,8小时外拼成长 ...

  2. 【高德地图API】汇润做爱地图技术大揭秘

    原文:[高德地图API]汇润做爱地图技术大揭秘 昨日收到了高德地图微信公众号的消息推送,说有[一大波免费情趣用品正在袭来],点进去看了一眼,说一个电商公司(估计是卖情趣用品的)用高德云图制作了一张可以 ...

  3. 自动化测试面试官:登录或注册时有验证码怎么处理?OCR图像识别技术大揭秘!

    本节大纲 读取cookie实现免登陆 pytesseract+tesseract-ocr实现图像识别 Pillow库对验证码截图 API接口实现图像识别 今天的这个技术点,为什么要给大家分享一下呢? ...

  4. 全景技术大揭秘,市场核心早洞悉——VR全景加盟

    未来已来,未来已见.2017是3D全景创业的天时,全景行业逐步走向成熟.全景智慧城市专注vr全景6年,技术国内遥遥领先.全景智慧城市市场总监常诚,透漏3D全景技术和市场的核心. 拍摄全景必备的设备:单 ...

  5. VR技术在数据中心3D机房中的应用(上)

    VR技术在数据中心3D机房中的应用(上)   前两天跟朋友A吃饭,吃着吃着就说到了VR.近几年来,VR技术越来越火,感觉能跟VR沾点边的都特别高大上,朋友A也是,一提到VR,就怎么都掩盖不住他发自肺腑 ...

  6. 2020中国.NET开发者峰会近50场热点技术专题揭秘

    简介 / Summary 2014年微软组织并成立.NET基金会,微软在成为主要的开源参与者的道路上又前进了一步.2014年以来已经有众多知名公司加入.NET基金会,微软,Google,AWS三大云厂 ...

  7. 关于VR技术和未来发展---转

    原文地址:http://mp.weixin.qq.com/s?__biz=MzA4MTIwNTczMQ==&mid=2651345594&idx=3&sn=2741ab7321 ...

  8. fir.im Weekly - 2016 移动开发技术大回顾

    2016 年是移动技术发展迅速的一年,认认真真回顾这一年必不可少.@移动开发前线 的 这篇 2016移动开发技术巡礼 ,精心盘点了 2016 年 移动开发技术大事件,分为 iOS/Android平台篇 ...

  9. 数娱科技:借助VR技术可让你了解自己的大脑

    你可能很好奇自己的大脑,如果你是一个脑部病患,可能更想了解下自己的大脑.好消息是,脑机接口让这个想法成为可能. 在上周六,AR/VR科技公司广州数娱科技发布了联合5家单位共同研发的"VR人脑 ...

随机推荐

  1. gulp几个常见问题及解决方案

    1. 找不到local gulp 报错代码: $ gulp [23:29:31] Local gulp not found in [23:29:31] Try running: npm install ...

  2. python使用大漠插件进行脚本开发的尝试(一)

    关于游戏脚本是纯然的小白,记一下学习过程遇到的问题.是在win10系统下对PC端的游戏进行脚本编辑,不知道会不会半途放弃. 一.大漠插件 大漠插件在游戏脚本编辑过程中是比较常见的工具,按我理解大致做的 ...

  3. bzoj3786星系探索(splay维护dfs序)

    Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...

  4. 学习笔记:Vue——处理边界情况

    访问元素&组件 01.访问根实例 $root // Vue 根实例 new Vue({ data: { foo: 1 }, computed: { bar: function () { /* ...

  5. 洛谷 P2299 Mzc和体委的争夺战

    洛谷 P2299 Mzc和体委的争夺战 题目背景 mzc与djn第四弹. 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁(做过前三弹的都知道).但如此之多的男家丁吸引来了我们的体委(矮胖小伙), ...

  6. 微信支付v2开发(7) 告警通知

    本文介绍微信支付中如何获得告警通知. 一.告警通知 为了及时通知商户异常,提高商户在微信平台的服务质量.微信后台会向商户推送告警通知,包括发货延迟.调用失败.通知失败等情况,通知的地址是商户在申请支付 ...

  7. oled屏幕模块

    oled屏幕模块似乎是厂家提供的 也许可以根据屏幕驱动芯片去写 根据现在了解的芯片一般有两个:SH1106和SSD1306 不过这次我们用的是SSD1306芯片驱动的屏幕 下面是从裸屏到模块的pcb: ...

  8. Vue里父子组间的通讯

    父组件代码 <template> <div> <child @child-say="listenToBoy" :mes=count></c ...

  9. 2.Docker初体验【Docker每天5分钟】

    原文:2.Docker初体验[Docker每天5分钟] Docker给PaaS世界带来的“降维打击”,其实是提供了一种非常便利的打包机制.该机制打包了应用运行所需要的整个操作系统,从而保证了本地环境和 ...

  10. jtag引脚

    如果不能下载,可能原因也许是电量不足了... 在电力不足的时候,仿真也不能进行... ///////////////////////////////////////////////////////// ...