6

ARCore初探

1.关键技术的由来

SLAM是什么?

根据Wikipedia的介绍:“Simultaneous Localization and Mapping (SLAM) is the computational problem of constructing or updating a map of an unknown environment while simultaneously keeping track of an agent’s location within it.”
最简单而又直指本质的理解,SLAM指的是当某种设备(如机器人、VR设备等)来到一个完全陌生的环境时,它需要精准地建立时间和空间的对应关系,并能完美地回答以下一系列问题:我刚才在哪里,现在在哪里?我看到了什么,现在看到的和之前看到的有哪些异同?我过去的行走轨迹是什么?我现在看到的世界是什么样子,和过去相比有怎样的变化?我的轨迹抖吗,我的位置飘吗?我还能跟踪到自己的轨迹吗,如果我丢了应该怎么办?我过去建立的对世界的认识还有用吗?我能在已有世界的抽象里快速对我现在的位置进行定位吗?

SLAM方向分类:
1.基于传感器的slam
2.基于视觉的slam

基于视觉的slam: 分为sparse, dense

sparse

clipboard.png

dense

clipboard.png

visual SLAM

clipboard.png

Slam变种VIO - Visual Inertial Odometry视觉惯性里程计

VIO和之前的几种SLAM最大的不同在于两点:
首先,VIO在硬件上需要传感器的融合,包括相机和六轴陀螺仪,相机产生图片,六轴陀螺仪产生加速度和角速度。相机相对准但相对慢,六轴陀螺仪的原始加速度如果拿来直接积分会在很短的时间飘走(zero-drift),但六轴陀螺仪的频率很高,在手机上都有200Hz。
其次,VIO实现的是一种比较复杂而有效的卡尔曼滤波,比如MSCKF(Multi-State-Constraint-Kalman-Filter),侧重的是快速的姿态跟踪,而不花精力来维护全局地图,也不做keyframe based SLAM里面的针对地图的全局优化(bundle adjustment)。它并不是了解到了周围完整的3D结构,能做的是根据像机反馈进行估计。
最著名的商业化实现就是Google的Project Tango和已经被苹果收购的Flyby Media,其中第二代Project Tango搭载了Nividia TK1并有主动光源的深度摄像头的平板电脑,这款硬件可谓每个做算法的小伙伴的梦幻搭档,具体在这里不多阐述。

相机和惯性测量单元IMU

相机单目,双目

IMU惯性测量单元是测量物体三轴姿态角(或角速率)以及加速度的装置。一般的,一个IMU包含了三个单轴的加速度计和三个单轴的陀螺,加速度计检测物体在载体坐标系统独立三轴的加速度信号,而陀螺检测载体相对于导航坐标系的角速度信号,测量物体在三维空间中的角速度和加速度,并以此解算出物体的姿态。
涉及到的sensors: 陀螺仪,角速度传感器;g-sensor加速度传感器

2.ARCore 进化

在 ARCore 发布之前,确实有一些手机厂商在自研算法,也有一些手机厂商已经与 Google 对接中,但是从进度和可推广的能力来说,Google 确实是首选,所以安卓的 AR 能力依靠 Google 这是目前最理想的方式。
自研的代表,Usens 与展讯合作,让百元手机实现 ARCore 的效果。
因为底层的空间定位算法非常依赖于硬件的校准和标定,任何软件公司想越过 Google 去支持整个安卓平台,尤其还需能够得到大部分手机厂商的配合去标定 IMU 和摄像头的参数,这需要和 很多OEM 厂商有长期合作的关系,而这几乎是不可能的。

1到2年内各大厂商肯定推出很多支持ARCore手机。

Project tango是Google开发的一个AR平台,需要专门的硬件配合,效果很好。但是要定制硬件。对于发展不利。现实证明不是那么成功。而又适逢苹果在iOS推出了arkit。Google也着急了。把重心移到android平台。
arcore从projection tango发展而来。
早期的代码还保留了tango相关的东西。可以看到preview和之后的版本不兼容,core不一样。

clipboard.png

版本历史

clipboard.png

还在发展,GitHub提交还非常活跃

clipboard.png

不只android
渗透到已有的工业体系,3D,浏览器,IOS等,也反映了google AR的野心和决心

clipboard.png

3. ARCore

工作原理和基本概念

ARCore工作时要做两件事儿,首先跟踪手机的运动轨迹,然后构建出它对现实世界的理解。
ARCore的运动跟踪技术是通过 Camera 标识出特征点,并随着时间的推移跟踪这些特征点是如何移动的。通过这些特征点的运动数据及从手机惯性传感器读到的信息,ARCore计算出手机移动的位置和方向,并称其为姿态。

除了识别出这些特征点外,ARCore还能检测出像地板、桌面等平面信息以及在某个地方的光线强度。这些信息使得ARCore能够构建出自己理解的真实世界。构建出这样一个模型后,可以在上面放置一些虚拟内容了。

ARCore 是一个用于在 Android 上构建增强现实应用的平台。 ARCore 使用三个主要技术将虚拟内容与通过手机摄像头看到的现实世界整合:
运动跟踪
让手机可以理解和跟踪它相对于现实世界的位置。
环境理解
让手机可以检测平坦水平表面(例如地面或咖啡桌)的大小和位置。
光估测
让手机可以估测环境当前的光照条件。

运动跟踪 (motion tracking)

clipboard.png

动时,ARCore 会通过一个名为并行测距与映射(或 COM)的过程来理解手机相对于周围世界的位置。 ARCore 会检测捕获的摄像头图像中的视觉差异特征(称为特征点),并使用这些点来计算其位置变化。 这些视觉信息将与设备 IMU 的惯性测量结果结合,一起用于估测摄像头随着时间推移而相对于周围世界的姿态(位置和屏幕方向)。

通过将渲染 3D 内容的虚拟摄像头的姿态与 ARCore 提供的设备摄像头的姿态对齐,开发者能够从正确的透视角度渲染虚拟内容。 渲染的虚拟图像可以叠加到从设备摄像头获取的图像上,让虚拟内容看起来就像现实世界的一部分一样。

运动跟踪demo
clipboard.png

环境理解 (environmental understanding)

clipboard.png
ARCore 会通过检测特征点和平面来不断改进它对现实世界环境的理解。

ARCore 可以查找看起来位于常见水平表面(例如桌子和书桌)上的成簇特征点,并让这些表面可以由您的应用用作平面。 ARCore 也可以确定每个平面的边界,并将该信息提供给您的应用。 您可以使用此信息将虚拟物体置于平坦的表面上。

由于 ARCore 使用特征点来检测表面,因此可能无法正确检测像白色书桌一样没有纹理的平坦表面。

环境理解demo
clipboard.png

光估测 (light estimation)

ARCore 可以检测其环境光线的相关信息,并为您提供给定摄像头图像的平均光强度。 此信息让您能够使用与周围环境相同的光照来照亮您的虚拟物体,提升它们的真实感。
clipboard.png
demo
clipboard.png

用户交互 (user interaction)

ARCore 利用命中测试来获取对应于手机屏幕的 (x,y) 坐标(通过点按或您希望应用支持的任何其他交互提供),并将一条射线投影到摄像头的视野中,返回这条射线贯穿的任何平面或特征点以及交叉位置在现实世界空间中的姿态。 这让用户可以选择环境中的物体或者与它们互动。

定向点 (oriented points)

定向点可以让您把虚拟物体摆放在非水平的表面上。 当您运行命中测试而返回特征点时,ARCore 将查看附近的特征点并使用它们来尝试估计给定特征点处的表面角度。 然后 ARCore 将返回一个顾及该角度的姿势。

由于 ARCore 使用特征点簇来检测表面的角度,因此可能无法正确检测到没有纹理的表面(如白色墙壁)。

锚点和可跟踪对象 (anchor and trackables)

姿态会随着 ARCore 改进它对自身位置和环境的理解而变化。 当您想要放置一个虚拟物体时,您需要定义一个锚点来确保 ARCore 可以跟踪物体随时间推移的位置。 很多时候,您需要基于命中测试返回的姿态创建一个锚点,如用户交互中所述。

姿态会发生变化,这就意味着 ARCore 可能会更新平面和特征点等环境物体随时间推移的位置。 平面和特征点是一种特殊类型的物体,称为可跟踪对象。 顾名思义,ARCore 可以随着时间推移跟踪这些物体。 您可以将虚拟物体锚定到特定的可跟踪对象,确保您的虚拟物体与可跟踪对象之间的关系即使在设备移动时也能保持稳定。 这意味着,如果您将一个虚拟的 Android 小雕像放在您的书桌上,即使 ARCore 稍后调整了与书桌关联的平面的姿态,Android 小雕像仍会看起来位于桌子上。

缺点:

无法检测没有纹理的表面

纹理就是每个物体表面上不同的样子,也就是事物的特征,ARCore是基于特征点检测的,对于没有特征的事物,无法检测。比如白色桌面。我的理解是光滑的平坦纯色的表面?
平常办公或小会议室的桌面没有纹理,前台大会议室的会议桌有纹理木头纹路。

平面只支持水平的,不支持竖直的平面,比如墙面。

飘移感(drift)

ARCore从摄像头捕获的图片中探测视觉上不同的特征点和IMU传感器数据,来了解手机移动时相对于周围世界的位置,计算其位置的变化。
在小范围场景内使用不会有明显的飘移感,但在大场景距离稍远的情况下,不准确的计算可能导致虚拟对象在视角中上漂浮游动。
为了解决这个问题ARCore内置了场景学习(area learning)算法。
场景学习的输出是场景中的一些特征,并将它们保存下来,以便将来能够重新定位以前到过的场景,或者用于校正漂移(drift),提高追踪算法的整体精度。
但是环境发生一些明显的变化,还是会影响场景学习的判断,产生飘移感。

数据共享

不支持多个设备共享数据。

drift demo? video is not supprot.

Android开发运行环境

开发环境

同时支持SDK和NDK
Android studio 3.0 or higher
SDK platform 7.0 (API level 24) or higher
ARCore SDK for Android

运行环境

Android 7.0 or higher (软件环境)
你开发应用使用的API在这些Android版本里才是available的。
ARCore environment is installed (软件环境)
ARCore环境实际上就是一个ARCore的apk,内置或安装在手机上,为ARCore应用提供AR相关服务。也可以叫ARCore engine。
确保你手机上的ARCore是最新的版本,如果不是最新的在程序运行时候会有相应的提示。因为ARCore在快速发展,接口变化也比较快,有些新的接口只有在新的ARCore中才有。
安装ARCore engine有两种途径,一个是通过Google play

clipboard.png

一个是在官方GitHub下载相应的apk

clipboard.png

安装好之后在手机应用里就能看到相应的信息,再次运行你的apk。
应该不需要GMS的支持,毕竟是独立的东西,国内的很多固件已经移除了GMS。

clipboard.png

ARCore的核心库

clipboard.png

支持的机型 (硬件环境)
 并不是所有机型都支持ARCore的,实际上支持ARCore的机型是很少的,尤其国内市场基本没有,一个是ARCore刚出来不久大家还没反应过来,还有就是刚才提到的“需要手机厂商配合google去标定 IMU 和摄像头的参数”。

clipboard.png

在不支持的手机上是可以安装ARCore apk的,但是在运行基于ARCore的应用时会收到该手机不支持AR的提示。

“this device does not support AR”
在早期的preview版本里,这个机型列表示在java代码里写死的,可以通过修改jar包来绕过检查,使得自己的手机支持ARCore应用的运行。

在后来的版本里,从写死的改为check设备的相关profile。通过session_ceate_implementation.cc 208 readDeviceInfo()检查设备是否满足要求,猜测已经不是写死的,而是设备在出厂前适配了这个调用。
这样就几乎没有办法hack了。

发布 (应用商店/google play)

有两种类型的AR应用
AR optional
代表您的应用起码有一项只会在支持 ARCore 的设备上才被激活的 AR 功能。 但是该应用仍然可以在没有 ARCore 支持的设备上安装和运行。
manifest设置
AR required
代表您的应用必须有 AR 才能运作,仅在支持ARCore 的设备上才可使用。
manifest设置

应用与实践

ARCore Java核心类

ArCoreApk
com.google.ar.core.ArCoreApk类,管理ARCore在设备上的状态,是否avaliable,是否需要安装,安装相关的UI提示等,里边都是静态方法。

Session
com.google.ar.core.Session类,Session管理AR系统状态并处理Session生命周期。 该类是ARCore API的主要入口点。 该类允许用户创建Session,配置Session,启动/停止Session,最重要的是接收com.google.ar.core.Frame,以允许访问Camera image和device pose。

Config
com.google.ar.core.Config类,用户保存session的设置,light estimate模式,udpate模式等。

Camera
com.google.ar.core.Camera类,提供了Cmeara相关的信息,是一个长期存在的对象,Camera的属性随着Session.update()更新。

Frame
com.google.ar.core.Frame类,通过调用Session.update()方法可以获得该对象,获取AR系统信息,如Camera image, Anchors等。

HitResult
com.google.ar.core.HitResult类,该类定义了命中射线与估算的真实世界的几何图形的交叉点,也就是命中点结果。

Anchor
com.google.ar.core.Anchor类,描述了现实世界中的一个固定位置和方向。 为了保持物理空间的固定位置,这个位置的数字描述信息将随着ARCore对空间的理解的不断改进而更新。

Plane
com.google.ar.core.Plane类,描述了现实世界平坦表面的最新信息。有两种平面类型,一种是朝下的如天花板,另外一种是朝上的如桌面,地板等。

Point
com.google.ar.core.Point类,它代表ARCore正在跟踪的空间中的一个点。 它是创建锚点(调用createAnchor方法)时,或者进行命中检测(调用hitTest方法)时,返回的结果。

PointCloud
com.google.ar.core.PointCloud类,它包含一组观察到的3D点和信心值。

Pose
com.google.ar.core.Pose类,姿势表示从一个坐标空间到另一个坐标空间位置不变的转换。 在所有的ARCore API里,姿势总是描述从对象本地坐标空间到世界坐标空间的转换。

随着ARCore对环境的了解不断变化,它将调整坐标系模式以便与真实世界保持一致。 这时,Camera和锚点的位置(坐标)可能会发生明显的变化,以便它们所代表的物体处理恰当的位置。

这意味着,每一帧图像都应被认为是在一个完全独立的世界坐标空间中。锚点和Camera的坐标不应该在渲染帧之外的地方使用,如果需考虑到某个位置超出单个渲染框架的范围,则应该创建一个锚点或者应该使用相对于附近现有锚点的位置。

ImageMetadata
com.google.ar.core.ImageMetadata类,提供了对Camera图像捕捉结果的元数据的访问。

LightEstimate
com.google.ar.core.LightEstimate类,保存关于真实场景光照的估计信息。 通过 getLightEstimate()得到。

Trackable
com.google.ar.core.Trackable类,是一个接口类,代表了一些ARCore可以跟踪并且锚点可以贴上的对象。比如Point,Plane等他们都是Trackable的子类。

TrackingState
com.google.ar.core.TrackingState类,描述了Trackable的跟踪状态,有三种状态paused, stopped, tracking。

ARCore C核心结构体

跟java核心类基本一样,除了语法的不同,其他都差不多。
这样的设计,降低了sdk和ndk开发之间切换的学习成本。
api都在arcore_c_api.h里包含,接口格式ArClass_method(),例如ArSession_create(),ArAnchor_getPose()等。

代码结构

clipboard.png

3D models

obj文件是3D模型文件格式。由Alias|Wavefront公司为3D建模和动画软件"Advanced Visualizer”开发的一种标准,适合用于3D软件模型之间的互导,也可以通过Maya读写。利用了现有的工业成果。
obj包含了物体的几何信息,但是不包含材质颜色光照,动画,贴图等信息。
所以需要一个材质库文件,就是mtl。
obj(shape)

clipboard.png

one of the materials

clipboard.png

the final look

clipboard.png

其他3D模式文件格式,3ds,awd,max,fbx,mesh,blend,dae,c4d等

shaders, opengles

一段在gpu上执行的程序,编程语言OpenGLES SL语言。

实例分析
了解了原理之后,分析下demo程序的流程。
创建Session和Config
在 Activity中的 onCreate 方法中创建 Session 和 Config是个不错的地方。

mSession = new Session(/context=/this);

mDefaultConfig = Config.createDefaultConfig();
if (!mSession.isSupported(mDefaultConfig)) {

Toast.makeText(this, "This device does not support AR", Toast.LENGTH_LONG).show();
finish();
return;

}
Session: 是ARCore的管理类,它非常重要。ARCore的打开,关闭,视频帧的获取等都是通过它来管理的。
Config:存放一些配置信息,如平面的查找模式,光照模式等信息都是记录在该类中。目前该类还比较简单,里边没存多少东西。
isSupported:该方法主要是对 SDK的版本及机型做控制。目前官方只支持几款Google和三星的机子做测试。其它机型还都不支持ARCore,当然有一些机型通过破解后的SDK是可以使用 ARCore的。该方法中的 Config 参数没有用到。

创建 GLSurfaceView 用于AR展示
在 Google 提供的Demo中,AR的展示部分使用的是 GLSurfaceView。做视频开发的同学都清楚,Android 可以使用三种View进行视频渲染。分别是:

SurfaceView
GLSurfaceView
TextureView

其中,SurfaceView最灵活,效率也最高,但使用起来比较繁琐。而GLSurfaceView是SurfaceView的子类相对 SurfaceView就是简单很多,只需要实现它的 Render 接口即可。而 TextureView使用最简单,很多工作都由 Android 的窗口管理器帮你做了,但灵活性相对较差。
选择GLSurfaceView的原因是它可以很方便的支持OpenGL渲染。

为了渲染的高效,Google在Demo中大量使用了OpenGL技术。

mSurfaceView = (GLSurfaceView) findViewById(R.id.surfaceview);
...
mSurfaceView.setPreserveEGLContextOnPause(true);
mSurfaceView.setEGLContextClientVersion(2);
mSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); // Alpha used for plane blending.
mSurfaceView.setRenderer(this); mSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);

该段代码首先通过资源文件创建一个GLSurfaceView对象,然后初始化 GLSurfaceView 管理的EGL display的一些信息。并将Activity作为GLSurfaceView的回调对象(也就是说该Activity要实现 GLSurfaceView.Renderer中定义的接口,如onSurfaceCreated、onSurfaceChanged、onDrawFrame等),最后设置 mSurfaceView 的渲染模式为 GLSurfaceView.RENDERMODE_CONTINUOUSLY,即对 GLSurfaceView 持续不断的渲染。
创建各种渲染的对象
要理解本节内容,首先大家要知道AR的详细工作原理是怎样的。这里再做个简要的说明。

背景展示

用过AR的人都知道,AR是将一些虚拟物品放到真实的场景中。那么这个真实的场景从哪里来呢?当然是从手机的 Camera上获取。

我们把从 Camera中获取的视频当作 AR的背景。其实,AR 就是将虚拟物品放到视频上,只不过不是简单的放置,而是需要经过大量的计算,找到视频中的平面位置再放置。

而Android中视频的采集相对比较简单,ARCore内部完成了Camera数据的采集,调用相关API即可获得。

平台检测

上面我们已经说了,AR就是实时视频+虚拟物品。但虚拟物不能简单的放到视频上,而是先对视频中的每一帧进行检测,找到视频中的平面,确定好位置后,再将虚拟物品放置上去。这样才算是AR呀。

点云

上面我们知道了,AR=实时视频+平面+虚拟物品。除此之外,它还应该能对虚拟物品进行跟踪,也就是可以在不同的角度观察同一个物品,并得出不同的姿态,所以就有了“点云” 技术。那什么是点云呢?顾名思义,形象的说就是一堆点,这些的形状有点像云。点云中的每个点都是一个特征点,它是通过Camera获得的。

放置虚拟物品

找到了平面,有了跟踪手段,我们就可以将准备好的虚拟物品放置到平台上,现在才是真正的AR。

好,知道了这些基本原理后,我们来看看Google Demo是如何做的呢?

创建渲染对象

对于上面的每一个方面,Demo都创建了一个对象用来渲染,代码如下
...

// Create the texture and pass it to ARCore session to be filled during update().
mBackgroundRenderer.createOnGlThread(/context=/this);
mSession.setCameraTextureName(mBackgroundRenderer.getTextureId());

// Prepare the other rendering objects.
try {

mVirtualObject.createOnGlThread(/*context=*/this, "andy.obj", "andy.png");
mVirtualObject.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
...

} catch (IOException e) {

Log.e(TAG, "Failed to read obj file");

}
try {

mPlaneRenderer.createOnGlThread(/*context=*/this, "trigrid.png");

} catch (IOException e) {

Log.e(TAG, "Failed to read plane texture");

}
mPointCloud.createOnGlThread(/context=/this);


需要说明的是在OpenGL中一个EGL context是单线程的,我们可以把GLSurfaceView理解成一个EGL context所以GLSufraceView的Render是单线程的,也就是onSurfaceCreated(),onSurfaceChanged(),onDrawFrame()是在同一个OpenGL线程,各个渲染对象的OpenGL操作都必须在这个线程里,比如创建这些渲染对象都是在onSurfaceCreated()里完成的,而渲染的动作是在onDrawFrame()里完成的。

上面的代码中首先创建了一个背景渲染对象,用来将从Camera中获取的视频渲染到屏幕上当背景。数据是从哪里来的呢?就是通过 Session.update 获取 Camera 数据,再通过纹理交给背景渲染对象。

对纹理没有概念的同学可以把它理解为一张2D图片。

然后创建虚拟物品渲染对象,用于绘制虚拟物品,及发生角度变化时,更新虚拟物别的姿势。紧接着创建平面渲染对象来绘制平面。最后创建点云渲染对象绘制特征点。

到此,各种渲染对象就创建完毕了。下面我们来说一下如何渲染。

命中检测与渲染
命中检测

当我们要向背景绘制虚拟物品时,首先要进行命中检测。代码如下
MotionEvent tap = queuedSingleTaps.poll();

        if (tap != null && camera.getTrackingState() == TrackingState.TRACKING) {
            for (HitResult hit : frame.hitTest(tap)) {
                // Check if any plane was hit, and if it was hit inside the plane polygon
                Trackable trackable = hit.getTrackable();
                // Creates an anchor if a plane or an oriented point was hit.
                if ((trackable instanceof Plane && ((Plane)
                       trackable).isPoseInPolygon(hit.getHitPose()))
                        || (trackable instanceof Point
                        && ((Point) trackable).getOrientationMode()
                        == Point.OrientationMode.ESTIMATED_SURFACE_NORMAL)) {
                    // Hits are sorted by depth. Consider only closest hit on a plane or oriented point.
                    // Cap the number of objects created. This avoids overloading both the
                    // rendering system and ARCore.
                    if (anchors.size() >= 20) {
                        anchors.get(0).detach();
                        anchors.remove(0);
                    }
                    // Adding an Anchor tells ARCore that it should track this position in
                    // space. This anchor is created on the Plane to place the 3D model
                    // in the correct position relative both to the world and to the plane.
                    anchors.add(hit.createAnchor());
                    break;
                }
            }
        }

在例子中,它查看是否有点击事件,且图像处理于跟踪状态?如果是,就对其进行命中检测,看是否可以找到一个平面或者一个定向点,如果找到就在命中位置创建一个锚点。

渲染背景

// Draw background.
mBackgroundRenderer.draw(frame);
通过上面的代码就可以将纹理中的内容推给 EGL,上面创建的渲染对象从 EGL 上下文中获取数据,最终将Camera视频渲染到屏幕上。

绘制点云

mPointCloud.update(pointCloud);
mPointCloud.draw(viewmtx, projmtx);
同理,通过上面的代码,就可以将数据传给点云渲染对象把点云叠加在背景上进行绘制。

绘制平面
// Visualize planes.
mPlaneRenderer.drawPlanes(

                mSession.getAllTrackables(Plane.class), camera.getDisplayOrientedPose(), projmtx);

通过上面代码将数据传给平面渲染对象和前边数据进行矩阵叠加并绘制。

绘制虚拟物品

for (Anchor anchor : anchors) {

if (anchor.getTrackingState() != TrackingState.TRACKING) {
    continue;
}
// Get the current pose of an Anchor in world space. The Anchor pose is updated
// during calls to session.update() as ARCore refines its estimate of the world.
anchor.getPose().toMatrix(mAnchorMatrix, 0);

// Update and draw the model and its shadow.
mVirtualObject.updateModelMatrix(mAnchorMatrix, mScaleFactor);
mVirtualObject.draw(viewmtx, projmtx, lightIntensity);
                
mVirtualObjectShadow.updateModelMatrix(mAnchorMatrix, scaleFactor);
mVirtualObjectShadow.draw(viewmtx, projmtx, lightIntensity);

}
最后,遍历所有的锚点,在每个锚点上绘制虚拟物品。

通过这个例子可以强化之前介绍的一些概念,比较幸运的是我们得到一台单目的google pixel可以进行调试,在真机上调试对ARCore相关概念的理解帮助还是比较大的,京东上有部分机型卖,不过价格稍贵。
期待国产2000档,甚至千元机支持ARCore这一天的到来。

有了ARCore可以做一些有意思的事情,比如我们远程桌面和远程camera可以实现把remote画面投射到AR场景中。
首先获取到远程的数据,通过RTCSurfaceViewRender它是SurfaceViewRender的子类,该类重写了SurfaceViewRender的renderFrame(I420Frame frame)方法,并将I420Frame通过listener返回,在demo中导入rtcsdk.aar,并注册这个listener即可获取到I420Frame
mSurfaceViewRender.register(new RTCSurfaceViewRenderListener() {

@Override
public void onRenderFrame(I420Frame frame) {
    //got the remote video frame here,and add it to RemoteVideoSource
}

});

I420Frame{

int width;
int height;
int[] yuvStrides;
ByteBuffer[] yuvPlanes;
boolean yuvFrame;
float[] samplingMatrix;
Int textureId;
Long nativeFramePointer;
Int rotationDegree;

}
通过绘制yuvPlanes[]或texureId可以得到图像。

根据需要将RemoteVideoSource的图像绑定在锚点上,就跟demo一样,实现AR效果。

clipboard.png

总结

1.再次领教了google强大的技术整合能力。

利用学术界,工业界现有的成果,结合各方面资源整合出ARCore。

2.目前市场上支持ARCore的手机很少

国内除了新发的小米MIX2S,P20,oneplus5还没看到其他机型。
google后边应该会放开机型的管制,但是看ARCore目前的发展,这个时间可能比较长,作为手机厂商应该等不到那个时候,18年肯定有很多AR或ARCore手机冒出来。

3.ARCore缺点:

不能识别没有纹理的表面 (这个不能优化,VIO决定的)
不能识别竖直的表面(这个google解决了后边会说到)
飘移感,大幅度移动,距离较远场景下 (可以优化)
单目相机可以获得精确的尺度,但是初始化时间较长,识别平面,特征点时间较长(双目没有机器,所以没有数据)(可以优化)
没有多人数据共享的解决方案(这个google已经解决了后边会说到)

4.不支持前置相机

这个不能算缺点,因为现在ARCore只支持识别平面,很难在人脸上识别特征点。而且前置相机开启人总是挡在前边,不是ARCore关注的场景。所以市面上流行的录像或即时通讯的人脸贴图用ARCore不是最佳实现方案。
对于系统厂商应该可以欺骗ARCore得到想要的前置相机效果,实现的难度取决于ARCore使用相机的方式,还涉及到一些相机参数的标定,前后相机的参数肯定是不一样的,支持前置的意义可以讨论。

5.ARCore目前的开发学习成本较高

主要是图形知识,3D模型,opengl等比如高级光照的一些处理等等。
我认为google下一步会拿出方案降低开发学习成本,也许下一个版本就有免费全家桶了。也许会有一些第三方的团队提供ARCore套餐,这个需要比较强的团队实力和时间,免不免费就不好说了。

6.可能手机厂商还要关心的是

与google集成完camera,IMU等数据,后续自己是否还可以继续提升,如何做,如何综合客观精确评价提升的效果,会不会优化出兼容性问题,有没有类似于cts,gts这样的case保证兼容性。
这些问题目前在internet上找不到相关答案,也许只有google自己知道。

7.AR云

(1)多个人如何融入同一个场景,信息完全同步。
(2)更有深度的,这个AR云可以理解为现实世界的1:1模型,完全覆盖在实体世界之上,可由机器读取。而我们的AR设备则是虚拟和现实世界的实时交互界面。我们的AR设备是这个平行虚拟世界的实时界面,它完美地覆盖了现实世界。

8.虽然过了preview阶段,但是目前还处在完善开发工具的阶段

可以作为卖点让市场狂欢,作为从业人员现阶段要抱着理性的心态,脚踏实地不抱有过高的期望,尤其是还没弄清楚AR是什么,AR的意义是什么的时候。
任何AR应用存在的唯一原因(与普通的智能手机应用程序相比)是它与现实世界有某种互动或联系。

在这个调研完不到两周,google ARCore又有大动作。

这也打乱了既定学习计划和技术路线。

ARCore升级至1.2.0

回答了部分我们之前提出的应用层面的问题,比如不能识别垂直的表面,AR cloud等,开始考虑应用场景,增加了图像增强的功能。

在之前预测,google ARCore团队会在降低渲染引擎的开发学习成本方面给出方案

果然,推出了Sceneform SDK简化渲染引擎的开发学习成本,但是我们没想到它来的这么快。
因为我们也在这方面做了一些探索工作,尝试将ARCore和rajawali结合生成一套更加简化的API。
Rajawali也是google用java语言开发的一个渲染引擎,它封装了opengles的api,而且内置了很多3D模型的解析,矩阵运算等模块,扩展了surfaceview实现render,也可以嵌入Android GLSurfacView。它的核心是Scene,Object3D,Renderer, SurfaceView(extends android surfaceview)等。
学习Sceneform后感觉很多思想概念跟Rajawali类似,推断它是基于rajawali开发的。

加入了更多手机

包括很多国内的手机,华为,小米,联想,一加(oppo)等。

Rajawali + ARCore实践

降低学习开发成本

clipboard.png

github:稍后会放到github上

Arcore 1.2.0

clipboard.png

clipboard.png

augmented image:图像增强

enables ARCore apps to detect and track images.
AugmentedImage,描述了增强图像在现实世界的最佳状态
AugmentedImageDatabase,database, up to 1000 images, build tool arcoreimg demo
clipboard.png

cloud anchor(锚点云)

Anchor cloud on google servers
cloud free now
Keep data for 7 days on the cloud
arcore cloud block by the great wall? don’t know yet.
sync anchors not objects,同步的是锚点不是物体
使用anchor cloud的多个设备或用户必须在同一场景下,也就是所有用户要聚在一个可能最多100平方米的场景内。极端的例子,用户在不同的地点但相似甚至一样的场景下???
firebase realtime database, for syncing room code and cloud anchor id, it deepens on GMS and blocked by the great wall.
Quotas
Quota type Maximum Duration Applies to
Number of anchors Unlimited N/A Project
Anchor host requests 30 minute User and project
Anchor resolve requests 300 minute User and project
画了张图

clipboard.png

google arcore usage team demo

clipboard.png

vertical plane

HORIZONTAL_DOWNWARD_FACING
HORIZONTAL_UPWARD_FACING
VERTICAL

Sceneform 1.0.0

Sceneform是google ARCore团队开发的一套API,为了简化ARCore应用渲染引擎的开发学习成本,开发者可以不用了解OpenGLES的API即可进行开发。

Sceneform is an render engine for ARCore

clipboard.png

the relationship between Sceneform and ARCore

clipboard.png

核心模块

ArFragment
ArSceneView
Renderable

它是一个3D模型,由网格meshes,材料materials,和纹理textures组成,它可以被Sceneform渲染在屏幕上。
Sceneform提供了3种方式创建Renderable:
(1).standard Android widgets
(2).basic shapes/materials
(3).3D assert files, support OBJ,FBX,glTF

Scene

每个ArSceneView都绑定了一个Scene。Scene是一个树状的数据结构,包含了很多Nodes,这些Nodes就是要被渲染的虚拟物体。

Node

一个Node代表了在scene图层的一个变换transformation。每个Node包含一个Renderable,它包含了Sceneform渲染需要的所有信息,包括它的位置,方向orientation和Renderable object.

与Scene交互

(1).触摸
(2).手势
(3).客制化nodes,利用Node的生命周期
(4).动画nodes,利用Node的生命周期
(5).灯光Lights,可以为每个Node指定
(6).阴影Shadows,在Sceneform里有的objects可以广播shadows有的objects接收shadows,一个object可以同时广播和接收自己的shadows。

SFA

Sceneform Asset Definition, It points to the models and textures in your source asset and also defines materials by providing material parameters for Sceneform’s physically-based materials.

SFB

Sceneform Binary asset,是SFA编译生成的结果。

demo
clipboard.png

4个Android platform渲染方案比较

android platform渲染方案技术路线从接触ARCore开始一直在主动变更

(1).opengl es

这不用多说,android平台图形3D渲染接口
优点:原生接口,经验可复制到其他平台
缺点:学习开发成本较高

(2).rajawali

google开发的渲染引擎,封装了opengl es,抽象了一些opengl的概念
优点:简化了学习开发难度,基于opengl es,java编写,android平台通用
缺点:java编写,限于android平台,经验不可复制到其他平台
核心机制:scene, object3D,surfaceview,renderer

(3).the third party

接触评估的一个第三方商业方案,技术上分析它是rajawali的变种或再封装,看它的核心机制
核心机制:XXsceneplay,XXwidget,XXSurfaview
优点:简化了学习开发难度,基于rajawali(在android平台,推测);而且有ios的版本API,开发流程基本一样,经验可以复制到其他平台
缺点:接入;商业方案,money,money,money钱能解决的都不是问题,但是钱是个问题;第三方的技术实力,简单评估并没有暴露的问题,比如和ARCore,以及android的整合是否完美,更新速度是否跟得上google的速度

(4).sceneform

google为ARCore开发的渲染引擎,技术上分析它也是rajawali的变种或封装开发,卡它的核心机制
核心机制:scene,node and renderable,ArSceneView
优点:简化学习开发成本,基于rajawali(推测),ARCore官方,与ARCore配合较好坑应该少一些,与anroid的view,widget等结合的很好,google技术实力强大,新能力迭代更新速度快
缺点:只有 android平台,经验不可以复制到其他平台

Google Play ARCore apps now

few apps
no killer app

应用方向:

工具类
营销类
教育类
游戏类
拍照类

现在支持的机型

看到了oneplus3T,去年发布的机型,间接说明了ARCore对硬件要求不是很高(camera+IMU) ,老的机型也是可以适配的。
这对国内厂家来说有重要意义。可以通过升级固件,给已经上市的机型的用户带来AR相关的体验。

clipboard.png

clipboard.png

google的一盘棋

运行环境/平台:
硬件平台:手机(相机+imu)
软件平台:Android
开发工具:arcore, unity3d, sceneform, opengles, rajawali...
分发渠道:Google Play
开发者:上边的都构建好了,不缺开发者

ARCore关注度

baidu/google指数

Baidu
arcore:4,110,000
p20 arcore:419,000
mix2s arcore: 178,200

google
arcore:6,050,000
p20 arcore: 714,000
mix2s arcore: 9,680

p20 launched in Paris
mix2s launched in Shanghai

开发者意愿,每个开发者后边可能代表了一个公司或行

clipboard.png

note: 代码分析部分内容参考了来自agora的2篇分享


WalkerXu
95 声望29 粉丝