ARKit初认识

ARKit 是苹果 WWDC2017 中发布的用于开发iOS平台 AR 功能的框架。AR 全称 Augmented Reality(增强现实),是一种在摄像机捕捉到的真实世界中加入计算机程序创造的虚拟世界的技术。


AR系统

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 和 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 需要看向能检测出许多有用特征点的内容。可能检测不出特征点的情况如下:

  1. 光线差——没有足够的光或光线过强的镜面反光。尝试避免这些光线差的环境。
  2. 缺少纹理——如果摄像头指向一面白墙,那也没法获得特征,ARKit 也去无法找到并追踪用户。尝试避免看向纯色、反光表面等地方。
  3. 快速移动——通常情况下检测和估算 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时的方向
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初认识就简单介绍到这里

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容