使用安卓设备的传感器实现3Dof的VR效果
渲染框架
Sceneform-EQR:
这是我对sceneform的扩展,目前已依赖最新版本(v1.54)的filament。
安卓传感器
利用 Android 传感器框架,可以访问多种类型的传感器。其中一些传感器 基于硬件,有些基于软件。基于硬件的传感器是构建的物理组件 手机或平板设备他们通过直接测量特定环境状况来推导出数据 例如加速度、地磁场强度或角度变化。基于软件 虽然它们模拟了基于硬件的传感器,但它们不是物理设备。基于软件的传感器 从一个或多个基于硬件的传感器获取数据,有时也称为虚拟传感器, 传感器或合成传感器例如,线性加速度传感器和重力传感器 基于软件的传感器。下图 总结了 Android 支持的传感器 平台。
很少有 Android 设备拥有所有类型的传感器。例如,大多数手机设备和 带有加速度计和磁力计的平板电脑,但配备 气压计或温度计此外,一个设备可以有多个特定类型的传感器。对于 例如,一个设备可以有两个重力传感器,每个重力传感器的范围各不相同。
实现步骤
步骤简述:通过使用安卓的传感器获取到实时的三轴旋转角度,再同步给场景相机,即可实现3dof的VR效果。
通过旋转矢量传感器获取方位角
- 注册传感器
public void registerListener(){mSensorManager.registerListener(this,mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR),SensorManager.SENSOR_DELAY_GAME);}
- 获取方位角
@Overridepublic void onSensorChanged(SensorEvent event) {//1.switch (event.sensor.getType()) {case Sensor.TYPE_ROTATION_VECTOR:processSensorOrientation(event.values);break;}}
- 处理方位角
这里需要针对手机的旋转状态(横屏or竖屏)作处理。
private void processSensorOrientation(float[] srcRotation) {float[] rotationMatrix = new float[9];
// float[] rotation = {-srcRotation[1],srcRotation[2],srcRotation[0]};SensorManager.getRotationMatrixFromVector(rotationMatrix, srcRotation);final int worldAxisX;final int worldAxisY;switch (windowManager.getDefaultDisplay().getRotation()) {case Surface.ROTATION_90:worldAxisX = SensorManager.AXIS_Z;worldAxisY = SensorManager.AXIS_MINUS_X;break;case Surface.ROTATION_180:worldAxisX = SensorManager.AXIS_MINUS_X;worldAxisY = SensorManager.AXIS_MINUS_Z;break;case Surface.ROTATION_270:worldAxisX = SensorManager.AXIS_MINUS_Z;worldAxisY = SensorManager.AXIS_X;break;case Surface.ROTATION_0:default:worldAxisX = SensorManager.AXIS_X;worldAxisY = SensorManager.AXIS_Z;break;}float[] adjustedRotationMatrix = new float[9];SensorManager.remapCoordinateSystem(rotationMatrix, worldAxisX,worldAxisY, adjustedRotationMatrix);// yaw/pitch/rollfloat[] orientation = new float[3];SensorManager.getOrientation(adjustedRotationMatrix, orientation);}
这时,获取到的orientation中三个分量,分别表示方位角、俯仰角、横滚角。
下一步我们需要将其转为渲染框架中设置相机姿态所需的四元数。
将欧拉角转为旋转四元数
- 将角度转为四元数
注意:这里需要注意设备坐标系和渲染框架坐标系的方向的区别。
下面传入的参数更改了坐标轴。
/*** 计算旋转四元数* @return ENU坐标系的姿态//东北天坐标系*/private Quaternion calculateRotation(float yaw,float pitch,float roll){return PoseUtils.toQuaternion(-pitch, -yaw, -roll);}
更新场景相机的姿态
获取场景相机,并更新其Rotation
getScene().getCamera().setWorldRotation(quaternion);
运行效果
VR效果
下图源于:通过手势事件实现在AR/VR等三维场景中的控制模型旋转、平移与缩放
由于采用同一个场景,因此不再额外录屏上传
补充:3Dof的AR效果可用同样的方式实现,只是需要额外接入相机实时预览画面。可以使用安卓提供的Camera2类实现。
源码示例
请转至github查看。链接:Sceneform-EQR
相关类
- VrSceneView.java
Git仓库
- Sceneform-EQR