ARKIT是苹果公司在今年发布的一个AR开发包,用于现有的IOS设备,是的,就是用在手机或者平板上,类似于pokemon go的效果。看了下演示视屏,嗯,看起来很厉害。
对于一个资深软粉,居然被要求研究它,尽管不情愿,还是得去看看。
先花半天时间熟悉下swift,再去苹果开发者中心看看arkit的文档。接着MacBook和ipad pro也到了(请注意! ARKIT 理论上支持现有的所有IOS设备,但是,要进行平面解析以及位置追踪的话,处理器必须是A9及更快)。将它们的系统都升级到最新(MacOS10.12.6和IOS 11 beta),安装xcode 9beta,安装Unity 2017,开发环境就弄好了。你问我为什么要安装Unity2017 ? 因为Unity 也可以用于ARKit的开发。
废话说完了,下面正是进入开发阶段。
首先打开Xcode,新建一个项目(不知道IOS Developer 们是不是叫新建项目) , 选择IOS项目,选择Augmented Reality APP 模版,next,输入你的项目名称 next,create。一个基本的AR应用就建好了,可以先用真机调试下,看能不能运行,如果不能运行的话,那我也没办法。
下面转到ARKit开发文档页面,看看它到底是个什么情况。在First Steps 有两项:
- Understanding Augmented Reality
- ARSession
建议不知道或者不太知道AR的朋友戳进去Understanding下。
ARSession在ARKIT中是一个非常重要的API,它搭建了整个AR世界以及摄像头管理。我们点进去可以看到一个run方法,它的作用可以理解为调用了该方法就开始加载ar世界了。它的参数是一个ARSessionConfiguration,从名字可以看出这是一个决定ARKit如何运行的类,它还有一个子类ARWorldTrackingSessionConfiguration,以后我们要用到的也大多是它的子类。出了run方法外,它还有一个pause方法,顾名思义就是暂停的意思。它还有add和remove方法,用于添加和移除描点,关于描点后面会讲到。属性currentFrame获取当前帧,类型是ARFrame。
接下来看看ARWorldTrackingSessionConfiguration,它的作用就是能让你的AR应用拥有6个自由度(不知道什么是自由度的请使用搜索引擎),它有一个PlaneDetection属性,如果要检测真实世界中的平面的话,请将它设为horizontal,isLightEstimationEnabled属性为自动光照,建议true。
接下来看看另外一个非常重要的东西:ARSCNView,它继承自SCNView,SCNView则是用于SceneKit的显示,SceneKit是苹果公司收购的一个游戏引擎。简而言之,AR程序中真实世界部分由ARSession提供,虚拟部分由ARSCNViwe提供(如果在Unity下开发,虚拟部分则由Unity提供,其它游戏引擎同理)。 ARSCNView有一个Session属性,就是上面讲的ARSession,还有一个scene属性,scene属性是一个场景,可以理解为整个虚拟世界就是一个scene,scene由无数node组成,关于scene的详细理解请阅读SceneKit文档。
下面讲讲比较重要的平面检测以及Node添加,前面说过要实现平面检测必须将planedetection设置为水平,然后通过
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) 事件(这是叫事件么?)来获取到识别的平面,这里由一个ARAnchor类型的参数,它就是获取到的平面的锚点,它包含了获取平面的坐标,可以通过这样来添加一个物体到这个平面上:
let plane=SCNBox( CGFloat(arPlaneAnchor.extent.x), height: 0.0, length: CGFloat(arPlaneAnchor.extent.z), chamferRadius: 0); plane.firstMaterial?.diffuse.contents=UIColor.red; let pnode=SCNNode(geometry: plane); pnode.position=SCNVector3Make(arPlaneAnchor.center.x, 0, arPlaneAnchor.center.z); node.addChildNode(pnode);
以上代码添加了一个和检测到的平面等大,高度为0,颜色为红色的平面,因为检测到的平面是看不到的,需要我们添加一个东西来标示。请仔细阅读以上代码。
除了添加一个物体到平面上,还可以进行和平面的碰撞检测,相信做游戏的朋友不会陌生。ARSCNVi 额外提供了一个hittest方法,传入参数是一个CGPoint和hittesttype,CGPoint也就是一个二维世界的点,也就是屏幕上的一个点;type有单点(也就是相机中的任何一个地方,遗憾的是返回的结果没有什么参考价值,都是错的),有边界平面和无边界的平面(二者的区别应该很好理解)。返回值是一个ARHittestResult,它有distance,worldtransform,localtransform,分别对应距离,世界坐标和本地坐标,关于世界坐标和本地坐标请自行了解。
一个最简单的AR应用基本就完成了 , 不过现在看来也没有其它更复杂的操作了。总体而言,ARKIt的开发难度是很低的,毕竟我这种渣渣接触几天就弄懂了。效果来说,位置追踪做得相当不错,几乎没有抖动和漂移的现象,平面解析还是能用的,不过也就是能用的水平,速度慢,边界不准,有时候根本检测不出。不过鉴于只有一个摄像头,能作出这样的效果还是很不错了,遗憾的是只能检测水平平面,并不能检测垂直平面。
期待更好的技术出现。