1. ARKit 工作流程
ARkit 是一個(gè)業(yè)界領(lǐng)先的AR框架, 先簡單介紹一下AR的原理. 基本上ARKit工作的流程是:
- 從攝像頭觀察周圍環(huán)境, 并構(gòu)建環(huán)境的基本模型, 這樣, 我們得到一個(gè)現(xiàn)實(shí)空間的簡單描述.
- 將手機(jī)中的虛擬空間和現(xiàn)實(shí)空間進(jìn)行"對(duì)齊"
- 在手機(jī)的虛擬空間放置的物件, 就能在現(xiàn)實(shí)空間中顯示了.
我們很大部分的創(chuàng)作在于虛擬空間的搭建和編程上, 當(dāng)我們得到一個(gè)虛擬的空間, ARKit的強(qiáng)大能力就能夠幫助我們將這個(gè)虛擬的空間疊加到現(xiàn)實(shí)空間中, 在你的屏幕上實(shí)現(xiàn)增強(qiáng)現(xiàn)實(shí)的魔法!
2. 搭建虛擬空間 - 場景 (Scene)
1 ) 場景的組成
ARKit中, 上面提到虛擬空間稱為場景(Scene). 場景通過節(jié)點(diǎn)(Node)組成
打個(gè)比喻, 場景就是電影的錄影廠, 燈光, 演員, 道具都可以稱為一個(gè)節(jié)點(diǎn). 并可以成為一定的層級(jí)關(guān)系 ( 如果你有數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ), 節(jié)點(diǎn)間的關(guān)系其實(shí)是來自于一個(gè)根節(jié)點(diǎn)的樹 ), 舉個(gè)例子
不過當(dāng)然, 你的Scene不一定是電影拍攝這樣的語境, 我們可以很自由地進(jìn)行組織, 不必拘泥例子中的結(jié)構(gòu)
2 ) Demo - 如何構(gòu)建一個(gè)場景
下面就通過Apple官方的Starter Project進(jìn)行解釋如何構(gòu)建一個(gè)場景
首先, 我們創(chuàng)建一個(gè)AR 項(xiàng)目,
然后在Content Technology中選取SceneKit
這樣我們得到一個(gè)簡單的 AR app, 它是直接就能運(yùn)行的
代碼中的sceneView
很重要:
@IBOutlet var sceneView: ARSCNView!
它是一個(gè) ARSCNView
, 這個(gè)是一個(gè)用于展示AR物件的視圖, 負(fù)責(zé)渲染, 相當(dāng)于AR的前端
sceneView
顧名思義, 其實(shí)就是"to view a scene", 沒錯(cuò)就是展示場景, 它顯示什么場景由它的.scene
屬性決定, 下面介紹兩個(gè)設(shè)置它的方式
- 方式1 -
XCode提供的初始代碼是第一種設(shè)置方式:
let scene = SCNScene(named: "art.scnassets/ship.scn")!
sceneView.scene = scene
即通過直接設(shè)置sceneView
的scene
來展示預(yù)先搭建的.scn
文件, Xcode的默認(rèn)AR項(xiàng)目中這個(gè).scn
文件是一個(gè)飛船模型, .scn
格式文件是在Xcode中創(chuàng)作的三維文件, 除了這個(gè)格式今穿,我們也可以傳入其他三維格式的作品
這是一個(gè)很簡單的方式, 優(yōu)點(diǎn)是可以讓編程和虛擬物件的創(chuàng)作這兩個(gè)流程較好地分離, 如果你是一名CG設(shè)計(jì)師, 那這個(gè)方式就很直接方便了
- 方式2 -
我們上面提到, 場景由節(jié)點(diǎn)組成, 所以第二種我要介紹的, 就是增量地進(jìn)行節(jié)點(diǎn)的添加, 為了說明這個(gè)方法, 我們可以嘗試從一個(gè)一無所有的sceneView
開始
我們先將Xcode的默認(rèn)AR項(xiàng)目中刪除飛船的資源文件, 也就是清空art.scnassets
中的文件
然后去掉ViewDidLoad()
中設(shè)置sceneView.scene
的代碼. 然后我們?nèi)牧汩_始用代碼搭一個(gè)場景
我們嘗試制作一個(gè)棒棒糖, 這里創(chuàng)建一個(gè)makeLollipop
函數(shù), 在這個(gè)函數(shù)中, 我們給sceneView
的根節(jié)點(diǎn)綁定一個(gè)子節(jié)點(diǎn), 用來后續(xù)存放棒棒糖的結(jié)構(gòu)
func makeLollipop(_ x: Float, _ y: Float, _ z: Float) {
let lollipopNode = SCNNode()
sceneView.scene.rootNode.addChildNode(lollipopNode)
}
然后我們可以增量地添加棒棒糖的幾個(gè)實(shí)體, 一個(gè)是糖球, 一個(gè)是糖棒
func makeLollipop(_ x: Float, _ y: Float, _ z: Float) {
let lollipopNode = SCNNode()
sceneView.scene.rootNode.addChildNode(lollipopNode)
// add candy
let candyNode = SCNNode(geometry: SCNSphere(radius: 0.05))
candyNode.position = SCNVector3(x, y, z)
lollipopNode.addChildNode(candyNode)
// add stick
let stickNode = SCNNode(geometry: SCNCylinder(radius: 0.008, height: 0.3))
stickNode.position = SCNVector3(x, y-0.15, z)
lollipopNode.addChildNode(stickNode)
}
這里我用了快速創(chuàng)建簡單幾何體的函數(shù), 它們還是比較直觀的, 這里不多作解釋了, 步驟基本是:
上面, 我們通過增量的方式, 構(gòu)建了這樣一個(gè)場景結(jié)構(gòu):
- 創(chuàng)建節(jié)點(diǎn), 這個(gè)時(shí)候可以指定節(jié)點(diǎn)中的幾何體
- 將節(jié)點(diǎn)加入到你選定的父節(jié)點(diǎn)中
注: 幾何體也可以來自于預(yù)先搭建好的三維文件
效果:
關(guān)鍵:
你完全可以結(jié)合上述兩種方法來搭建場景, 其實(shí)兩種方法都是基于節(jié)點(diǎn)的結(jié)構(gòu)的當(dāng)你用Xcode創(chuàng)建的三維實(shí)體, 節(jié)點(diǎn)的關(guān)系能夠被很好的解析, 其他軟件制作的可能需要進(jìn)行一定的拆分和組織, 所以我們也需要學(xué)會(huì)通過指定
geometry
參數(shù)來創(chuàng)建SCNNode()
的方法
3. 現(xiàn)實(shí)空間的要素
1 ) AR攝像機(jī)
文檔: ARCamera
這個(gè)攝像機(jī)的定義和CG概念上的攝像機(jī)類似, 它包含一個(gè)攝像機(jī)的三維位置信息, 旋轉(zhuǎn)姿態(tài)信息, 現(xiàn)實(shí)空間各個(gè)點(diǎn)和這個(gè)攝像機(jī)的相對(duì)位置對(duì)于描述這個(gè)現(xiàn)實(shí)空間是很關(guān)鍵的
2 ) AR 幀
文檔: ARFrame
現(xiàn)實(shí)空間的基本輸入首先就是一幀幀的圖像, 在ARKit中, 除了基本的像素信息, 它還包含了設(shè)備的三維空間的位置信息, 環(huán)境的跟蹤信息等等, 得到ARFrame
需要用到的硬件不只是攝像頭, 還需要運(yùn)動(dòng)傳感器
3 ) 特征點(diǎn) ( 點(diǎn)云 )
文檔: rawFeaturePoints
ARPointCloud
當(dāng)你移動(dòng)你的設(shè)備時(shí), 攝像頭會(huì)分析視頻幀并搜集環(huán)境中一些有代表性的特征點(diǎn), 有時(shí)可能是角點(diǎn) ( 指尖, 桌角, 屏幕的角, 鍵盤鍵粒, 文字邊緣等等 ), 有時(shí)可能是紋理 ( 木紋, 衣物皺褶, 纖維 ), 也有可能是色彩轉(zhuǎn)折 ( 比如地面和墻面 ). 我不知道Apple用的特征點(diǎn)檢測算法有哪些, 但是你可以去了解一下常見的幾個(gè)算法
特征點(diǎn)的跨幀匹配是ARKit對(duì)世界描述的很關(guān)鍵的步驟, 比如說, 你在一個(gè)幀中用上了一個(gè)鈕扣上的特征點(diǎn), 如果你能在后面的幀也能找到鈕扣的特征點(diǎn)并成功匹配, 你就能得到這個(gè)鈕扣在三維空間的位置估計(jì)
當(dāng)你的點(diǎn)不止一個(gè)而是很多的時(shí)候, 你對(duì)這個(gè)空間的描述就更加準(zhǔn)確. 當(dāng)然, 當(dāng)前這個(gè)技術(shù)不能做到完美, 所以很多時(shí)候AR還是會(huì)"飄", ARKit 的文檔也提到
ARKit does not guarantee that the number and arrangement of raw feature points will remain stable between software releases, or even between subsequent frames in the same session.
4 ) 錨點(diǎn)
文檔: ARAnchor
錨是比特征點(diǎn)更加可靠的現(xiàn)實(shí)空間標(biāo)記, 它能夠提高其周圍區(qū)域的現(xiàn)實(shí)跟蹤質(zhì)量, 文檔中提到一些很有用的錨點(diǎn):
ARPlaneAnchor: ARKit能夠檢測空間中的平面, 你可以給這些平面綁定一個(gè)"平面錨點(diǎn)", 它常常是一個(gè)干凈的桌面, 地面等等, 宜家的虛擬家具app就用到了平面檢測來減少虛擬家具的漂移
ARImageAnchor, 掃描一張圖片, 并記憶這個(gè)圖像的特征, 當(dāng)我們下次見到這個(gè)圖像的時(shí)候, 我們就能夠?qū)⑺O(shè)置為一個(gè)錨點(diǎn), 在其周圍展示我們的虛擬世界, 它比平面特征更加豐富, 因?yàn)槠矫嫱且恍┑孛? 桌面的紋理, 而圖片則細(xì)節(jié)更多. 這種錨點(diǎn)常常會(huì)用來做虛擬故事書. 當(dāng)掃描到故事書上特定的圖片時(shí), 能夠在其上播放虛擬場景, 讓情節(jié)"躍然紙上"
ARObjectAnchor: 這個(gè)真的太badass了! 能夠檢測并記錄一個(gè)現(xiàn)實(shí)三維物件, 你可以將一個(gè)杯子作為一個(gè)"物體錨", 創(chuàng)建這樣一個(gè)錨需要用攝像機(jī)掃描這個(gè)三維物件并得到豐富的特征點(diǎn). 當(dāng)攝像機(jī)下次看到這個(gè)三維物件的時(shí)候, 它能夠記住它并將它作為現(xiàn)實(shí)空間的描述標(biāo)記, 比特征點(diǎn)和圖片更加高級(jí)!
ARFaceAnchor
這個(gè)能夠準(zhǔn)確定位你的五官, 并為你戴上虛擬飾物, 很多美顏相機(jī), 直播軟件都有用到這個(gè)功能, 這個(gè)就非常容易聯(lián)想到了
5 ) 環(huán)境光
文檔: lightEstimate
要讓我們的虛擬物件在現(xiàn)實(shí)環(huán)境中疊加得更加真實(shí), 我們希望它被打上和環(huán)境一樣的燈光
ARKit 提供了對(duì)環(huán)境光位置估計(jì)的功能, 你可以估計(jì)環(huán)境光的位置, 強(qiáng)度后, 往你的場景中添加一盞對(duì)應(yīng)位置和強(qiáng)度的燈. 這樣你的虛擬物件才能和周圍的現(xiàn)實(shí)真正的契合. 方法我會(huì)在后續(xù)教程講到, 敬請(qǐng)期待哦
點(diǎn)個(gè)喜歡吧~??