前言

说起AR(增强现实技术),印象最深的应该是去年流行的Pokémon Go,宠物小精灵的AR游戏模式,让人惊喜万分。今年的WWDC17上,苹果在开发会上发布了ARKit,惊艳的演示效果,让人记忆犹新,这也让iOS开发者能够使用OC或swift语言在手机上进行开发,AR将会更加普及。

准备

ARKit,需要手机升级到iOS11,并需要Xcode9,这些都需要你拥有开发者账号才能进行,这是 链接地址
这里提供手机升级到iOS11的描述文件,请用Safari打开,点击下载
另外也需要你的硬件支持

1.Xcode版本:Xcode9及以上
2.iOS系统:iOS11及以上
3.iOS设备:处理器A9及以上(6S机型及以上)
4.MacOS系统:10.12.4及以上(安装Xcode9对Mac系统版本有要求)

code


ARKit的提供了三个个渲染类,ARSCNView用来渲染3D视图,ARSKView用来渲染2D视图,以及苹果Metal图形API。
首先,我们创建工程:

选择AR模板,
,接着选择SceneKit.
进入初始化的工程,我们看一看到下图:

比比以往工程多了一个art.scnassets文件,里面放着初识苹果给的飞机模型文件,另外我们可以看到飞机上面的坐标系

我们可以删除掉这里面模型,放进自己的3D模型文件,这里支持scn和dae的3D模型,另外注意的是,不要将模型直接拉近工程文件中,请打开art.scnassets进行真实添加。
我们这里就用自带的飞机文件进行简单操作。

推荐的模型下载地址:https://vr.google.com/objects/cMwwpQvuiui     注意需要用blender重新导出dae文件。

我们创建一个新的节点

  var planeNode: SCNNode!

viewDidLoad中进行初始化和设置代码如下

  // 设置代理
       sceneView.delegate = self
        // 显示一些数据,如fps,计时信息等
        sceneView.showsStatistics = true
        // 创建一个SCNScene,用于显示3d模型
        let scene = SCNScene(named: "art.scnassets/ship.scn")!
        // 节点名称设置为 飞机
        planeNode = scene.rootNode.childNode(withName: "shipMesh", recursively: true)
        // 将飞机变小
        planeNode.scale = SCNVector3Make(0.01, 0.01, 0.01)
        // 向Z方向移动1单位 蓝色方向为Z
        planeNode.position = SCNVector3Make(0.0, 0.0, -1.0)
        // 自适应环境光照度,过渡更平滑
        sceneView.automaticallyUpdatesLighting = true;
        // 将加载了3d模型的SCNScene设置成ARSCNView的scene
        sceneView.scene = scene

这里的showsStatistics属性,可以给我们显示fps等信息,可以选择开启或者关闭,开启后可以看到在界面中,下面点开后所展示的信息

我们通过代码来设置了飞机的大小,以及距离,也可以通过模型文件直接设置如下图:

接下来我们要为ARSCNView设置一个会话配置类,会话配置类主要目的就是负责追踪相机在3D世界中的位置以及一些特征场景的捕捉,配置后将真实的设备运动映射到3D场景的坐标系统里。

 // 为ARSCNView设置一个会话配置类(会话配置类,在配置类对象里设置会话如何将真实的设备运动映射到3D场景的坐标系统里,这里默认是使用重力)
        let configuration = ARWorldTrackingConfiguration()
        // 设置追踪平面类型为水平
        configuration.planeDetection = .horizontal
        // 自适应灯光
        configuration.isLightEstimationEnabled = true;
        // 开始
        sceneView.session.run(configuration)

我们在viewWillDisappear添加暂停操作

// 暂停
        sceneView.session.pause()

当启用平面检测时,ARKit会为每个检测到的平面添加并更新锚点,为这些锚点添加可视化内容使用以下代理,也是ARKit中重要的代理。

// MARK: - ARSCNViewDelegate代理
    // 重要:当启用平面检测时,ARKit会为每个检测到的平面添加并更新锚点,为这些锚点添加可视化内容使用以下代理
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        // This visualization covers only detected planes.
        guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

        // 创建SceneKit平面,依据它位置和范围展示节点
        let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))
        let planeNode = SCNNode(geometry: plane)
        planeNode.position = SCNVector3Make(planeAnchor.center.x, 0, planeAnchor.center.z)
        // 旋转
        planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)

        node.addChildNode(planeNode)
    }

完成以上内容,就可以Run起来,看到一个飞机模型,会随着手机的移动来个看到各个方位,以及随着远近变幻距离。
下面我们来实现一个小的点击事件,点击模型后,可以在别的地方添加更多的模型,
在系统的touchesBegan事件中添加代码,如下

 // MARK: - 添加点击事件
    // 点击节点,创建节点副本,得到hitTest,再次点击后添加新节点
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        let results = sceneView.hitTest(touch.location(in: sceneView), types: .featurePoint)
        guard let anchor = results.first else { return }
        let hitPointTransform = SCNMatrix4(anchor.worldTransform)
        let hitPointPosition = SCNVector3Make(hitPointTransform.m41,
                                              hitPointTransform.m42,
                                              hitPointTransform.m43)
        let planeClone = planeNode.clone()
        planeClone.position = hitPointPosition
        sceneView.scene.rootNode.addChildNode(planeClone)
    }

通过对touches的捕捉,得到hitTest后,在点击的位置创建基于锚点位置的节点。
效果如下:

以上,这是对ARKit的简单实现,可以看到,ARKit在使用中并不困难,在不久的将来,AR肯定会成为广大APP的主流。

ARKit文档:ARKit

项目下载: Github

本博客所有内容采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可

转载文章请注明:iOS开发-初识ARKit - https://yimouleng.com/2017/08/28/arkitfirstsight/

分类: iOS开发

丶伊眸冷

静水流深,沧笙踏歌;三生阴晴圆缺,一朝悲欢离合。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

我不是机器人*