已经是第7章节了,终于可以开始正式接触到我们梦寐以求的ARCore了,相信大家应该都有一点点小激动了吧。那么下面我们就开始讲解如何进行ARCore的开发。
一、Session简介
初看到Session,大家都摸不到头脑。最直接的解释,它是ARCore API的一个类com.google.ar.core.Session。它管理了AR系统的状态,有自己的生命周期,开始和停止访问摄像头图像帧的获取。
所管理AR系统状态,包含跟踪的Anchor信息、通过session.add(Pose)和session.removeAnchor(anchors)保存和删除。session.getAllPlanes()返回被检测到的平面、当前投影矩阵等。
当ARCore App退至后台,Activity调用onPause()方法时,也需要通过session.pause()暂停Session,来停止摄像机的图像获取并获取资源。在App呈现在前台的时候,onResume()方法中调用session.resume(Config)可以重新启用Session,获取摄像机图像等。
有了平面和虚拟内容位置等信息进行渲染。但是当手机的位置移动的时候,我们是如何保持绘制内容的“位置不变”的呢?这都是基于ARCore系统不断返回的图像帧、设备位置和朝向等信息。调用session.update()方法来获取最新的相机帧,更新设备的位置,更新被跟踪的Anchor信息,更新被检查的平面。
二、Config简介
Config,即ARCore API中com.google.ar.core.Config,保存了用于配置Session的设置。那么这个配置中都包含了什么呢?
- 光线评估子系统的行为Config.LightingMode,包含开启或者禁止光线评估。
- 平面检测子系统的行为Config.PlaneFindingMode,包含开启和禁止平面检测。
- update()的行为Config.UpdateMode。在大多数设备中,摄像头被配置每秒捕捉30帧。当调用update()从摄像机获取帧的时,没有新的相机图片包含两种行为:立即分会和阻塞等待。
另外前面提到过目前并不是所有设备都支持ARCore,session.isSupport(config)方法就能完成当前设备是否支持该ARCore的配置。
三、ARCore开发起步
了解了Config和Session的意义之后,正式开始ARCore开发。我们需要处理这么几件事情:
- ARCore设备支持检测:自定义或者创建默认Config,然后通过Session来检测当前设备是否支持当前ARCore配置。
- 处理Session生命周期和视图变化:
- 在Activity的onPause()和onResume()生命周期回调中,处理Session生命周期。正确的开始和暂停相机获取图像,释放资源等。
- 当手机屏幕变化等情况发生,导致GLSurfaceView大小变化。需要适当调整透视图矩阵和背景,设置纵横比和坐标缩放,用于UV坐标系和投影矩阵生成。保证变化后虚拟内容的正常渲染。
四、案例源码分析
了解了基本的概念和步骤后,我们来看看在Google的ARCore Demo中是如何处理的。
1. ARCore设备支持检测
com\google\ar\core\examples\java\helloar\HelloArActivity.java
public class HelloArActivity extends AppCompatActivity implements GLSurfaceView.Renderer {
... ...
private Session mSession;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
... ...
//Sessoin类是ARCore API的主要入口,管理AR系统状态和处理Session生命周期,接收帧允许访问摄像头的图片和设备的Pose
mSession = new Session(/this);
//创建默认的Config,平面检测,光线评估被启动,并且阻塞更新被选中。检查当前的设备是否支持ARCore,从这个Config创建Session
mDefaultConfig = Config.createDefaultConfig();
if (!mSession.isSupported(mDefaultConfig)) {
Toast.makeText(this, "This device does not support AR", Toast.LENGTH_LONG).show();
finish();
return;
}
... ...
}
}
2.处理Session生命周期和视图变化
com\google\ar\core\examples\java\helloar\HelloArActivity.java
public class HelloArActivity extends AppCompatActivity implements GLSurfaceView.Renderer {
... ...
private Session mSession;
@Override
protected void onResume() {
super.onResume();
//ARCore需要摄像机权限来操作。如果我们还没有Android M及以上得到运行时的权限,现在是一个向用户请求它的好时机
if (CameraPermissionHelper.hasCameraPermission(this)) {
showLoadingMessage();
//使用默认配置恢复Session,如果Session没有开始或者被暂停,这个方法必须在App的UI线程中被调用。它将会启动Session,初始化相机和运动跟踪,当update()被调用的时候,将会产生帧。注意这个顺序很重要 - 在onPause()中看到该说明,相反的在这里也同样适用。
mSession.resume(mDefaultConfig);
//恢复渲染线程,如果有必要的话重新创建OpenGL上下文,它和onPause对应
mSurfaceView.onResume();
} else {
CameraPermissionHelper.requestCameraPermission(this);
}
}
@Override
public void onPause() {
super.onPause();
//注意这个顺序很重要 - GLSurfaceView首先暂停所以它不会再尝试查询Session。如果Session在GLSurfaceView。前被暂停,GLSurfaceView可能一直调用mSession.update()并且获取一个SessionPauseException
mSurfaceView.onPause();
//暂停当前Session,这个方法将会停止相机反馈和释放资源
mSession.pause();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
//通知ARCore Session视图大小被改变,所以透视矩阵和视频背景可以适当的调整。设置纵横比和坐标缩放,这个数据将会被使用UV坐标系,生成投影矩阵
mSession.setDisplayGeometry(width, height);
}
}
1.新技术,新未来!尽在1024工场。时刻关注最前沿技术资讯,发布最棒技术博文!(甭客气!尽情的扫描或者长按!)
2.完整和持续更新的《使用Android打开AR的开发大门—ARCore》文档,欢迎大家阅读!
https://www.kancloud.cn/p3243986735/arcore_develop/457951