原文鏈接: http://fighting300.com...
增強(qiáng)現(xiàn)實(shí)技術(shù)(Augmented Reality,簡(jiǎn)稱AR),是一種實(shí)時(shí)地計(jì)算攝影機(jī)影像的位置及角度并加上相應(yīng)圖像、視頻、3D模型的技術(shù),這種技術(shù)的目標(biāo)是在屏幕上把虛擬世界套在現(xiàn)實(shí)世界并進(jìn)行互動(dòng)。
ARKit是2017年6月6日,蘋果發(fā)布的iOS11系統(tǒng)所新增的框架,它能夠幫助我們以最簡(jiǎn)單快捷的方式實(shí)現(xiàn)AR技術(shù)功能。而且ARKit框架對(duì)基于3D場(chǎng)景(SceneKit)和2D場(chǎng)景(SpriteKit)的增強(qiáng)現(xiàn)實(shí)都提供了支持。
本文將會(huì)使用ARKit創(chuàng)建一個(gè)簡(jiǎn)單的app,結(jié)束時(shí)就可以在AR世界里放置3D物體,并且可以用iOS設(shè)備繞著它移動(dòng)。雖然這是一個(gè)非常簡(jiǎn)單的app,我們會(huì)在之后的文章中繼續(xù)為其編寫更多功能,包括平面檢測(cè)、3D物理效果等其他東西。
開發(fā)環(huán)境
- Xcode版本: Xcode9以上
Xcode 9 Beta:https://developer.apple.com/download/
下載最新的beta版本就可以了,不過Xcode需要Mac 10.12.4及以上的版本。 - iOS系統(tǒng): iOS11以上
- iOS設(shè)備: A9/A10處理器的iOS設(shè)備,即iPhone6s、iPad2017及以上的設(shè)備
創(chuàng)建項(xiàng)目
首先打開Xcode,選擇ARKit模板,如下所示:

之后,填寫完項(xiàng)目信息后,選擇Content Technology為SceneKit,當(dāng)然也可以選擇SpriteKit,不過在3D空間中就不是那么立體了。
開發(fā)語言選擇Swift,Swift天然親和ARKit,很多網(wǎng)上的Demo都是用Swift寫的,這樣也方便移植和借鑒。
然后連接你的測(cè)試設(shè)備并運(yùn)行,app就可以運(yùn)行了。該模版APP會(huì)在實(shí)施攝像頭鏡頭中展示一架飛機(jī)的3D模型。如下圖所示:

實(shí)際項(xiàng)目中,你也可以不使用該模版來創(chuàng)建項(xiàng)目,直接引入相關(guān)庫(kù)也可以進(jìn)行開發(fā)。
在項(xiàng)目中可以看到viewWillAppear方法中已經(jīng)初始化了ARWorldTrackingConfiguration實(shí)例。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARWorldTrackingConfiguration()
// Run the view's session
sceneView.session.run(configuration)
}
放置3D物體
SceneKit有一些基礎(chǔ)類,SCNScene是所有3D內(nèi)容的容器,可以在其中添加多個(gè)3D物體。
要向scene中添加內(nèi)容,要?jiǎng)?chuàng)建SCNGeometry,然后將其包裝為SCNNode并添加到SCNScene中。
首先注釋掉let scene = SCNScene(named: "art.scnassets/ship.scn")! sceneView.scene = scene,然后添加代碼如下:
override func viewDidLoad() {
super.viewDidLoad()
// 存放所有3D幾何體的容器
let scene = SCNScene()
// 想要繪制的 3D 立方體
let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0.0)
// 將幾何體包裝為node以便添加到scene
let boxNode = SCNNode(geometry: boxGeometry)
// 把box放在攝像頭正前方
boxNode.position = SCNVector3Make(0, 0, -0.5)
// rootNode是一個(gè)特殊的node,它是所有node的起始點(diǎn)
scene.rootNode.addChildNode(boxNode)
// 將 scene 賦給 view
sceneView.scene = scene
}
現(xiàn)在運(yùn)行該項(xiàng)目,就會(huì)看到有3D立方體懸浮在空中,并且全方位無死角。
此外還可以增加一些調(diào)試信息
// ARKit統(tǒng)計(jì)信息例如fps等
sceneView.showsStatistics = YES;
sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints];
// 調(diào)整攝像頭屬性 當(dāng)前攝像頭有效直徑在10m范圍內(nèi)
if let camera = sceneView.pointOfView?.camera {
camera.wantsHDR = true
camera.wantsExposureAdaptation = true
camera.exposureOffset = -1
camera.minimumExposure = -1
camera.zFar = 10
}
之前簡(jiǎn)單體驗(yàn)了ARKit的功能,下面簡(jiǎn)單介紹ARKit的工作原理:
ARKit工作原理
在ARKit中,創(chuàng)建虛擬3D模型其實(shí)可以分為兩個(gè)步驟:
- 相機(jī)捕捉現(xiàn)實(shí)世界圖像--由ARKit實(shí)現(xiàn)
- 在圖像中顯示虛擬3D模型/2D模型--由SceneKit/SpriteKit實(shí)現(xiàn)
ARKit中ARSCNView用于顯示3D虛擬AR的視圖,它的作用是管理一個(gè)ARSession,一個(gè)ARSCNView實(shí)例默認(rèn)持有一個(gè)ARSession。
在一個(gè)完整的AR體驗(yàn)中,ARKit框架只負(fù)責(zé)將真實(shí)世界畫面轉(zhuǎn)變?yōu)橐粋€(gè)3D場(chǎng)景,這一個(gè)轉(zhuǎn)變的過程主要分為兩個(gè)環(huán)節(jié):由ARCamera負(fù)責(zé)捕捉攝像頭畫面,由ARSession負(fù)責(zé)搭建3D場(chǎng)景,而將虛擬物體顯示在3D場(chǎng)景中則是由SceneKit框架來完成,每個(gè)虛擬物體都是一個(gè)節(jié)點(diǎn)SCNNode,每個(gè)節(jié)點(diǎn)構(gòu)成一個(gè)場(chǎng)景SCNScene。
ARCamera只負(fù)責(zé)捕捉圖像,不參與數(shù)據(jù)的處理。它屬于3D場(chǎng)景中的一個(gè)環(huán)節(jié),每一個(gè)3D Scene都會(huì)有一個(gè)Camera,它決定了我們看物體的視野。
下圖是ARKit與SceneKit的框架關(guān)系圖:

ARSessionConfiguration的主要目的就是負(fù)責(zé)追蹤相機(jī)在3D世界中的位置以及一些特征場(chǎng)景的捕捉(例如平面捕捉),這個(gè)類本身比較簡(jiǎn)單卻作用巨大。ARSessionConfiguration是一個(gè)父類,為了更好的看到增強(qiáng)現(xiàn)實(shí)的效果,蘋果官方建議我們使用它的子類ARWorldTrackingSessionConfiguration,該類只支持A9芯片之后的機(jī)型,也就是iPhone6s之后的機(jī)型。
當(dāng)ARWorldTrackingSessionConfiguration計(jì)算出相機(jī)在3D世界中的位置時(shí),它本身并不持有這個(gè)位置數(shù)據(jù),而是將其計(jì)算出的位置數(shù)據(jù)交給ARSession去管理,而相機(jī)的位置數(shù)據(jù)對(duì)應(yīng)的類就是ARFrame。ARSession類一個(gè)屬性叫做currentFrame,維護(hù)的就是ARFrame這個(gè)對(duì)象。

ARKit的完整運(yùn)行流程可以參考下圖:
- ARSCNView加載場(chǎng)景SCNScene
- SCNScene啟動(dòng)ARCamera開始捕捉圖像
- ARSCNView開始將SCNScene的場(chǎng)景數(shù)據(jù)交給ARSession
- ARSession通過管理ARSessionConfiguration實(shí)現(xiàn)場(chǎng)景的追蹤并且返回一個(gè)ARFrame(添加3D物體模型時(shí)計(jì)算3D模型相對(duì)于相機(jī)的真實(shí)矩陣位置時(shí)需要使用)
- 給ARSCNView的SCNScene添加一個(gè)子節(jié)點(diǎn)(SCNNode)
