谷歌官方——Google VR(全景图模块)
Posted android与kotlin以及java架构
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了谷歌官方——Google VR(全景图模块)相关的知识,希望对你有一定的参考价值。
最近微博上的全景图火了,所以决定实现一下。 手机上面可能有些代码看不全,推荐大家用电脑去看
工程里面图片资源来自网络,如有侵权请联系我,马上删除
当然实现的方式很多比如OpenCV、u3d等。
这里提供两种方式实现:
1. OpenGL ES
2. GoogleCardboard(Google VR)上面的一个集成模块,我们只使用里面展示全景图部分模块
第一种我会在后续继续完善加入更多的可选参数,你们有兴趣也可以自己优化。
第二种是谷歌VR模块的没什么好说的,毕竟官方俩字就够了。
下面给大家看一下效果图:
第一种 OpenGL ES
第一种方式使用OpenGL来实现(上面gif图截取因为博客限制上传图片的大小,我压缩了,看起来有些卡其实很流畅的)
可以看到支持旋转手机查看、或者拖动图片查看、可以看到右边中心部分有个指示器会随着角度变化而变化并且点击可以还原起始位置。
一.使用
有些小伙伴懒得看原理,直接就想拿来用所以我先说集成方式吧!
Step 1
在build.gradle 文件中添加库依赖:
Step 2.Add the dependency
在 build.gradle 文件中添加库依赖:
build.gradle 完整代码:
Step 3.创建布局文件.XML
Step 4.传入你的全景图
R.drawable.imggugong 这张全景图传到控件里面
OK现在你可以测试玩玩了(别用模拟器玩咔咔报错就来找我)。
二.分析
首先我们需要了解全景图是什么东西,全景图是一种广角图。通过全景播放器可以让观看者身临其境地进入到全景图所记录的场景中去,通常标准的全景图是一张2:1的图像,其背后的实质就是等距圆柱投影。等距圆柱投影是一种将球体上的各个点投影到圆柱体的侧面上的一种投影方式,投影完之后再将它展开就是一张2:1的长方形的图像。比较常见的就是应用在地图上的投影。
得到全景图后那我们就需要展示了,看到旁边地球了吗?
怎么展示呢简单来说就是把全景图片整个贴到一个球体上。
好了知道原理那我们就该考虑在android上怎么实现了,在android中绘制3d图形可以使用OpenGL (就不说OpenGL 基础了想看的自己百度一大堆资料)。
1.绘制球体:
引用tim_shadow大佬的关于全景图一篇文章介绍
在OpenGL ES中基本上所有的立体图像都是通过一个个的小三角形拼接而成我们知道球面上面的每一个点(P(x,y,z))都会满足方程组(球的极坐标方程):
x = r * sin(a) *cos(b)
y = r * cos(a)
z = r * sin(a)*sin(b)
其中 r为球的半径,a为线段 OP与 z轴正方向所夹角,b为 OP在xoy平面的投影 OP‘ 与x的正方向所夹角
我们可以根据这个方程组,通过控制∠a和∠b的变化,从上到下,逆时针的取得我们需要用来组合称三角形的点,然后我们需要将全景图片上的点与我们在球上面选取的点一一对应起来(注意:球的坐标是3维坐标,图片的坐标是2维坐标)
球上面的点与图片上面的点一一对应起来。
纹理和图片绑定绘制到屏幕上
2.利用传感器让球随着手机转动而转动
第一想到的就是重力感应传感器,可是只能获得我们向那个位置偏移的方向,显然不可能满足我们旋转的需求,使用陀螺仪传感器。
陀螺仪就是内部有一个陀螺,它的轴由于陀螺效应始终与初始方向平行,这样就可以通过与初始方向的偏差计算出实际方向。
陀螺仪对设备旋转角度的检测是瞬时的而且是非常精确的。
1.注册陀螺仪传感器
首先注册陀螺仪传感器根据具体需要自己设置灵敏度,当然越灵敏,越耗电。
注册陀螺仪传感器,并设定传感器向应用中输出的时间间隔类型是SensorManager.SENSOR_DELAY_GAME(20000微秒)
SensorManager.SENSOR_DELAY_FASTEST(0微秒):最快。最低延迟,一般不是特别敏感的处理不推荐使用,该模式可能在成手机电力大量消耗,由于传递的为原始数据,算法不处理好会影响游戏逻辑和UI的性能
SensorManager.SENSOR_DELAY_GAME(20000微秒):游戏。游戏延迟,一般绝大多数的实时性较高的游戏都是用该级别
SensorManager.SENSOR_DELAY_NORMAL(200000微秒):普通。标准延时,对于一般的益智类或EASY级别的游戏可以使用,但过低的采样率可能对一些赛车类游戏有跳帧现象
SensorManager.SENSOR_DELAY_UI(60000微秒):用户界面。一般对于屏幕方向自动旋转使用,相对节省电能和逻辑处理,一般游戏开发中不使用
我这里为了测试设置了SENSOR_DELAY_FASTEST,实际使用建议用SENSOR_DELAY_GAME
2.获得传感器数据
当传感器的值发生变化时,例如磁阻传感器方向改变时会调用OnSensorChanged(). 当传感器的精度发生变化时会调用OnAccuracyChanged()方法。
从 x、y、z 轴的正向位置观看处于原始方位的设备,如果设备逆时针旋转,将会收到正值;否则,为负值
得到两次检测到手机旋转的时间差(纳秒),并将其转化为秒
将手机在各个轴上的旋转角度相加,即可得到当前位置相对于初始位置的旋转弧度,将弧度转化为角度
3.设置填充球的Y,X的角度
每次获得角度数据后只需要y,x的值计算位移的值
因为全景图上下旋转会翻转整个图所以我这里设置了上下只能偏移50f,如果不限制你可以去掉
mBall.yAngle += dx * 2.0f;这里*2.0也就是陀螺仪传过来的值乘以得出偏移的角度,数值越大,每次偏移更快!
3.加入手势操控,拖动图片转动
加入手势这里没什么好说的了,就是重写onTouchEvent()方法。
这里唯一要注意的就是,当手指点击屏幕的时候要关闭陀螺仪传感器的监听不然会引起冲突。当手指离开屏幕,重新监听陀螺仪传感器。
和上面也一样只是这里换成获取手指偏移角度,而不是传感器的数值,直接看代码。
4.加入指示器
指示器这里弄了一个角标指示当前在全景图的角度,并且点击还原起始角度。
可以想象同样是获取角度,我们直接放在全景图改变的地方,让指示器一起改变,而我们改变的地方只有2个陀螺仪和拖动屏幕。
我这里指示器放了一张图也就是一个 ImageView 控件
1.为指示器加入动画跟随全景图一起转
2.点击指示器还原起始位置
当点击还原的时候,我一开始是直接恢复起始位置可是太生硬了,通过获取当前旋转的角度,逆向旋转,慢慢还原,让其有个过渡的效果。
Y轴=旋转的角度-90f(起始角度)/10f(每次偏移多少,经过我多次尝试10f在我的手机上刚刚好);
得到我们总共偏移几次可以复位;
X轴同理,因为我上面限制了X轴的最大偏移,这里就不就算X轴了,不过在完成的同时直接复位X轴。(只是没有过渡的效果),你可以加上。
我设置的起始角度是90f和0f,也就是X,Y轴的起始点
mHandlers.postDelayed(this, 16);
这行代码就是多少毫秒复位一次。
看代码:
至此第一种OpenGL ES方式核心代码分析完毕,有不明白的地方可以找我
第二种 Google VR
第二种也就是谷歌官方为移动平台下VR解决方案,有兴趣的可以点开下面链接玩玩,我们只使用其中全景图模块。
一.使用
Step 1.Add the dependency
目前GitHub上最新版本号为1.8.0,我这里也用最新的了。
最低支持到 minSdkVersion 19 也就是Android 4.4.0
在 build.gradle 文件中添加库依赖:
Step 2.创建布局文件.XML
Step 3.AndroidManifest中添加权限
Step 4.Activity中初始化组件
第二种到这里已经可以显示玩玩了,也没什么可分析的,都是官方提供的sdk,会调用相关的方法就好了,具体都有那些方法接口,最好的文档永远都是官方提供的,上面已经给出了链接,最好自己把GitHub上的官方提供的demo拿下来跑一遍,我就不多介绍了。
以上是关于谷歌官方——Google VR(全景图模块)的主要内容,如果未能解决你的问题,请参考以下文章
Android -- 开源库Google VR 给用户呈现 360° 全景图
Daydream VR入门基础教程,学习Google VR for Android全景应用示例SimpleVrPanorama制作VR全景应用