ARKit 是苹果 WWDC2017 中发布的用于开发iOS平台 AR 功能的框架。AR 全称 Augmented Reality(增强现实),是一种在摄像机捕捉到的真实世界中加入计算机程序创造的虚拟世界的技术。
AR 系统由以下几个基础部分组成:
- 捕捉真实世界:ARKit 利用摄像头拍摄现实场景的画面。
- 虚拟世界:用SceneKit来建立虚拟世界。
- 虚拟世界与现实世界相结合:ARKit 负责将现实世界和虚拟世界的信息融合,并渲染出一个 AR 世界。
- 维持世界追踪:当真实世界变化时(移动摄像头),要能追踪到当前摄像机相对于初始时的位置、角度变化信息,以便实时渲染出虚拟世界相对于现实世界的位置和角度。
- 进行场景解析:指的是解析现实世界中有无特征点、平面等关键信息。
- 处理与虚拟世界的互动:指的是当用户点击或拖动屏幕时,处理有没有点击到虚拟物体或者要不要进行添加/删除物体的操作。
由此可见,ARKit 主要做的事是:捕捉现实世界信息、将现实和虚拟世界混合渲染、并且时刻处理新的信息或者进行互动。
ARKit 提供了两个主要功能;第一个是 3D 空间里的相机位置,第二个是水平面检测。前者的意思是,ARKit 假定用户的手机是在真实的 3D 空间里移动的摄像机,所以在任意位置放置 3D 虚拟对象都会锚定在真实 3D 空间中对应的点上。对于后者来说,ARKit 可以检测诸如桌子这样的水平面,然后就可以在上面放置对象。
ARKit 框架提供了两种 AR 技术,一种是基于3D场景(SceneKit)实现的增强现实,一种是基于2D场景(SpriteKit)实现的增强现实。要想显示 AR 效果,必须要依赖于苹果的游戏引擎框架(3D引擎 SceneKit,2D引擎 SpriteKit),主要原因是游戏引擎才可以加载物体模型。虽然ARKit框架中视图对象继承于 UIView,但是由于目前 ARKit 框架本身只包含相机追踪,不能直接加载物体模型,所以只能依赖于游戏引擎加载 ARKit。
另外需要说明的一点是,ARKit 虽然是 iOS11 新出的框架,但并不是所有的 iOS11 系统都可以使用,而且必须要是处理器 A9 及以上才能够使用,苹果从 iPhone 6S 开始使用 A9 处理器,也就是 iPhone 6 及以前的机型无法使用 ARKit。
ARKit 并没有明确要求开发者使用哪种方式构建虚拟世界,开发者可以利用 ARKit 输出的真实世界、世界追踪以及场景解析的信息(存在于 ARFrame 中),自己将通过图形引擎创建的虚拟世界渲染到真实世界中。值得一提的是,ARKit 提供了 ARSCNView 类,该类基于 SceneKit 为 3D 虚拟世界渲染到真实世界提供了非常简单的 API,所以本文学习的是 SceneKit。
接下来介绍下ARKit API 中的几个主要的类,如 ARSession、ARSessionConfiguration、ARFrame、ARCamera 等。
ARSCNView——这是 SceneKit 主视图 SCNView 的子类,帮我们用 SceneKit 渲染的 3D 内容来增强实时摄像头视图,将设备摄像头的实时视频流渲染为场景背景,并会自动匹配 SceneKit 空间和真实世界。这个类做了下面几件事:
- 在视图中渲染设备摄像头的实时视频流,并就其设置为 3D 场景的背景
- ARKit 的 3D 坐标系会匹配 SceneKit 的 3D 坐标系,所以此视图渲染的对象会自动匹配增强后的 ARKit 世界视图
- 自动移动虚拟 SceneKit 3D 摄像头来匹配 ARKit 追踪到的 3D 位置,所以不需要再写代码连接 ARKit 移动事件与 SceneKit 3D 渲染。
ARSCNView 本身不会做 AR 处理,但它需要 AR session 对象来管理设备摄像头和运动处理。负责综合虚拟世界(SceneKit)的信息和现实世界的信息(由ARSession 类负责采集),然后将它们综合渲染呈现出一个 AR 世界。
ARSession——每个增强现实会话都都需要有一个 ARSession 实例。它负责控制摄像头、聚合所有来自设备的传感器数据等等以构建无缝体验(负责采集现实世界的信息)。ARSCNView 实例已经有 ARSession 实例,只需要在开始的时候配置一下。
ARFrame
ARFrame 包含了两部分信息:ARAnchor 和 ARCamera。
其中,ARCamera 指的是当前摄像机的位置和旋转信息。这一部分 ARKit 已经为我们配置好,不用特别配置。
ARAnchor 指的是现实世界中的锚点,具体解释如下:可以把 ARAnchor(锚点)理解为真实世界中的某个点或平面,anchor 中包含位置信息和旋转信息。拿到 anchor 后,可以在该 anchor 处放置一些虚拟物体。也可以与 SCNNode 可以绑定。它有一个子类:ARPlaneAnchor,专门指的是一个代表水平面的锚点。
ARWorldTrackingSessionConfiguration——这个类会告诉 ARSession,在真实世界中追踪用户时需要使用六个自由度,roll、pitch、yaw 以及 X轴、Y轴、Z轴上的变换。如果不用这个类,就只能创建在同一个点旋转查看增强内容的 AR 体验。有了这个类,就可以在 3D 空间里绕着物体移动了。如果你不需要在 X轴、Y轴、Z轴上的变换,用户就会在投影增强内容时保持在固定位置,这时可以用 ARSessionConfiguration 类替代此类来初始化 ARSession 实例。
ARSession 是整个ARKit系统的核心,ARSession 实现了世界追踪、场景解析等重要功能。而 ARFrame 中包含有 ARSession 输出的所有信息,是渲染的关键数据来源。
ARKit 本身并不提供创建虚拟世界的引擎,而是使用其他 3D/2D 引擎进行创建虚拟世界。iOS 系统上可使用的引擎主要有:
- Apple 3D Framework - SceneKit.
- Apple 2D Framework - SpriteKit.
- Apple GPU-accelerated 3D graphics Engine - Metal.
- OpenGl
- Unity3D
- Unreal Engine
ARKit 需要看向能检测出许多有用特征点的内容。可能检测不出特征点的情况如下:
- 光线差——没有足够的光或光线过强的镜面反光。尝试避免这些光线差的环境。
- 缺少纹理——如果摄像头指向一面白墙,那也没法获得特征,ARKit 也去无法找到并追踪用户。尝试避免看向纯色、反光表面等地方。
- 快速移动——通常情况下检测和估算 3D 姿态只会借助图片,如果摄像头移动太快图片就会糊,从而导致追踪失败。但 ARKit 会利用视觉惯性里程计,综合图片信息和设备运动传感器来估计用户转向的位置。因此 ARKit 在追踪方面非常强大。
ARSCNViewDelegate
先介绍 ARSCNView 的代理:ARSCNViewDelegate,他有以下几个回调方法。
func renderer(SCNSceneRenderer, nodeFor: ARAnchor)
当 ARSession 检测到一个锚点时,可以在这个回调方法中决定是否给它返回一个 SCNNode。默认是返回一个空的 SCNNode(),我们可以根据自己的需要将它改成只在检测到平面锚点(ARPlaneAnchor)时返回一个锚点,诸如此类。
func renderer(SCNSceneRenderer, didAdd: SCNNode, for: ARAnchor)
func renderer(SCNSceneRenderer, willUpdate: SCNNode, for: ARAnchor)
func renderer(SCNSceneRenderer, didUpdate: SCNNode, for: ARAnchor)
func renderer(SCNSceneRenderer, didRemove: SCNNode, for: ARAnchor)
以上方法会在为一个锚点已经添加、将要更新、已经更新、已经移除一个虚拟锚点时进行回调。
ARSessionDelegate
ARSession 类也有自己的代理:ARSessionDelegate
func session(ARSession, didUpdate: ARFrame)
在 ARKit 中,当用户移动手机时,会实时更新很多 ARFrame。这个方法会在更新了 ARFrame 时,进行回调。它可以用于类似于始终想维持一个虚拟物体在屏幕中间的场景,只需要在这个方法中将该节点的位置更新为最新的 ARFrame 的中心点即可。
func session(ARSession, didAdd: [ARAnchor])
func session(ARSession, didUpdate: [ARAnchor])
func session(ARSession, didRemove: [ARAnchor])
如果使用了 ARSCNViewDelegate 或 ARSKViewDelegate,那上面三个方法不必实现。因为另外的 Delegate 的方法中除了锚点以外,还包含节点信息,这可以让我们有更多的信息进行处理。
看下使用ARKit时的方向
解释一下:从手机左边向右边是x轴的正方向,从手机下边向上边是y轴的正方向,从手机的摄像头的里面向外面是z轴的正方向.补充一点,在ARKit中,距离单位是米.
接下来我们来敲一个最简单的ARKit项目
首先创建一个ARKit工程(这里有两种方式来创建,一种是创建单视图APP,还有一种是直接创建ARKit APP,这里我们为了容易上手,就选了第二种),如图
override func viewDidLoad() {
super.viewDidLoad()
// 存放所有 3D 几何体的容器
let scene = SCNScene()
//几何(想要绘制的 3D 立方体)
let box = SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0)
//渲染(可以渲染颜色或者图片)
let material = SCNMaterial()
//设置渲染的填充内容
material.diffuse.contents = UIImage(named:"000.jpg")
//渲染是一个数组,可以添加多种渲染
box.materials = [material]
//节点(将几何体包装为 node 以便添加到 scene)
let boxNode = SCNNode(geometry: box)
// 把 box 放在摄像头正前方
boxNode.position = SCNVector3(0,0,-0.3)
// rootNode 是一个特殊的 node,它是所有 node 的起始点
scene.rootNode.addChildNode(boxNode)
// 将 scene 赋给 view
sceneView.scene = scene
//设置默认光照
sceneView.autoenablesDefaultLighting = true
}
再简单介绍下视图即将出现和即将消失两个方法所包含的内容
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// 创建运行世界跟踪配置(世界跟踪配置跟踪设备的方向和位置。它还可以通过设备的相机检测现实世界的表面)
let configuration = ARWorldTrackingConfiguration()
//如果想在 ARKit 里检测水平面,可以通过设置 session configuration 对象的 planeDetection 属性来指定。
//configuration.planeDetection = .horizontal;
// 开启运行世界跟踪
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// 停止跟踪视图内容的运动和处理图像
sceneView.session.pause()
}
不想敲代码的,可以点这里直接下
关于ARKit初认识就简单介绍到这里