前言
對ARKit感興趣的同學(xué),可以訂閱ARKit教程專題
源代碼地址在這里
正文
在本章中,我們將了解AR session是什么以及如何管理它。這包括啟動虚循,停止和重置。還將學(xué)習(xí)如何處理會話錯誤并跟蹤典型AR應(yīng)用程序生命周期中可能發(fā)生的問題样傍。
準(zhǔn)備工作
我們需要在上一個項目的基礎(chǔ)之上添加一些可交互的事件横缔,我們需要在ViewController.swift添加一些UI控件和一些事件方法:
// MARK: - Outlets
@IBOutlet var sceneView: ARSCNView!
@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var startButton: UIButton!
@IBOutlet weak var styleButton: UIButton!
@IBOutlet weak var resetButton: UIButton!
// MARK: - Actions
@IBAction func startButtonPressed(_ sender: Any) {
}
@IBAction func styleButtonPressed(_ sender: Any) {
}
@IBAction func resetButtonPressed(_ sender: Any) {
}
創(chuàng)建一個 AR session
我們之前在Main.storyboard中添加的ARSCNView是一個很基本的SceneKit view。它包括一個ARSession對象衫哥,該對象負(fù)責(zé)處理ARKit的運動追蹤和圖像處理工作茎刚。需要注意的是,ARSession對象是基于會話來進(jìn)行工作的撤逢,也就是說膛锭,你需要先創(chuàng)建一個AR session實例,然后運行它蚊荣,才可以啟動AR的追蹤過程初狰。
創(chuàng)建con?guration
在啟動AR session,之前,必須創(chuàng)建AR session con?guration (AR 會話配置)。此配置用于在真實世界(設(shè)備所在的位置)和虛擬 3D 世界(虛擬內(nèi)容所在的位置)之間建立連接妇押。
有兩種類型的配置:
- AROrientationTrackingConfiguration, 用于三個自由度跟蹤, 簡稱3DOF跷究。
- ARWorldTrackingConfiguration姓迅,用于六個自由度跟蹤, 簡稱 6DOF敲霍。
3DOF
3DOF跟蹤設(shè)備旋轉(zhuǎn),分為Pitch(俯仰)俊马、Roll(滾動)和 Yaw(偏航) 組件,表示圍繞X 軸、Y 軸和 Z 軸的旋轉(zhuǎn)肩杈。這由 AR 定向跟蹤配置會話配置類型支持柴我。
6DOF
6DOF 跟蹤Pitch、Roll和 Yaw,類似于 3DOF扩然。它還使用 Sway艘儒、Heave 和 Surge 組件跟蹤 3D 空間中的設(shè)備移動。這些新組件表示與 X 軸夫偶、Y 軸和 Z 軸平行的移動界睁。這由 ARWorldTrack 配置會話配置類型支持。
檢查設(shè)備功能
您正在創(chuàng)建 AR 應(yīng)用程序需要 6DF 跟蹤,因此你將使用 ARWorldTrackingConfiguration對象兵拢。良好的編碼實踐是檢查設(shè)備是否能夠支持此功能翻斟。
為此,在 initARSession() 中添加以下內(nèi)容:
guard ARWorldTrackingConfiguration.isSupported else { print("*** ARConfig: AR World Tracking Not Supported") return }
可以使用 類的isSupported屬性來檢查設(shè)備是否支持該配置。如果不是,這是一個偉大的地方,通知用戶適當(dāng)?shù)南⑺盗濉R詸C智的方式向用戶提供壞消息總是一個好主意访惜。
現(xiàn)在您知道設(shè)備支持 6DOF,可以創(chuàng)建配置對象。
將以下內(nèi)容添加到 initARSession() 的底部:
// 1
let config = ARWorldTrackingConfiguration()
// 2
config.worldAlignment = .gravity
// 3
config.providesAudioData = false
上面的代碼主要功能如下:
- 首先,創(chuàng)建一個 ARWorldTrackingConfiguration配置實例, 該實例已分配給config腻扇。
- 設(shè)置worldAlignment屬性,用于指定虛擬內(nèi)容與真實世界的關(guān)系债热。這里有三個選項:
?a) gravity: 這將設(shè)置虛擬內(nèi)容坐標(biāo)系的 Y 軸,與地球引力平行。這可確保 Y 軸始終在實際空間中向上指向幼苛。它還使用設(shè)備的初始位置作為坐標(biāo)系源,稱為世界原點窒篱。這是 AR 會話開始時設(shè)備在真實世界中的位置。
?b) gravityAndHeading:這還會設(shè)置虛擬內(nèi)容坐標(biāo)系的 Y 軸,與重力平行蚓峦。它還定向 X 軸,使其從西向東運行,并且 Z 軸,以便從北到南運行:
?最后,它還使用設(shè)備的初始位置作為世界起源舌剂。例如,你可以使用它將用戶指向真實世界的指南針方向。
?c)camera:這將使用設(shè)備方向和 3D 空間中的位置作為世界原點暑椰。例如,用戶可以在啟動 AR 會話之前將其設(shè)備放在墻上霍转。
- 設(shè)置worldAlignment屬性,用于指定虛擬內(nèi)容與真實世界的關(guān)系债热。這里有三個選項:
- 通過將providesAudioData設(shè)置為false來禁用該功能。此屬性允許 AR 會話捕獲音頻一汽。
- 這里還有一個其他的屬性避消,isLightEstimationEnabled。在后面的章節(jié)中你會了解它的召夹。
運行session
現(xiàn)在已經(jīng)創(chuàng)建了 AR 配置,剩下的唯一事情就是啟動 AR 會話岩喷。
在 initARSession() 方法中添加以下內(nèi)容:
sceneView.session.run(config)
在 ARSCNView 的 ARSession 上調(diào)用run(_:options:),傳入剛剛創(chuàng)建的 ARWorldTrackingConfiguration。就是這個,你的AR session現(xiàn)在啟動并運行,并且它正在積極收集6DOF跟蹤數(shù)據(jù)监憎。
操控AR session
盡管 AR session已啟動并運行,但它不是你可以啟動和忽略的內(nèi)容纱意。可能需要根據(jù)應(yīng)用中發(fā)生的情況控制其行為鲸阔。 其實,控制 AR session是非常簡單的偷霉。
Pausing:ARSession.pause()暫停AR session追蹤迄委。在用戶切換到另一個應(yīng)用程序時,可以很好地使用會話。
Resuming: ARSession.run() 將恢復(fù)暫停的會話类少。它將利用現(xiàn)有的跟蹤配置來恢復(fù)追蹤過程叙身。
Updating: ARSession.run(ARSessionConfig)用于更新對配置的更改。也許你確實希望啟用音頻采樣,但僅當(dāng)用戶按下按鈕時硫狞。首先從活動運行的會話獲取配置,調(diào)整其屬性,然后使用已更改的配置重新運行會話信轿。
Resetting: ARSession.run(_:options:)在異常情況下很有用,并且別無選擇,只能重新啟動 AR session。有可能用戶長時間關(guān)閉設(shè)備,這將使任何以前收集的跟蹤信息毫無意義残吩。
更新狀態(tài)信息
我們可以把AR session的實時狀態(tài)顯示到屏幕上财忽,我們可以添加一個對象:var trackingStatus: String = ""
。然后添加如下代碼:
func renderer(_ renderer: SCNSceneRenderer,
updateAtTime time: TimeInterval) {
DispatchQueue.main.async {
self.statusLabel.text = self.trackingStatus
}
}
AR session錯誤處理
我們可以通過ARSessionDelegate來得知AR session的一些問題泣侮。
@protocol ARSessionDelegate <ARSessionObserver>
我們可以作如下操作:
extension ViewController : ARSCNViewDelegate {
// MARK: - SceneKit Management
func renderer(_ renderer: SCNSceneRenderer,
updateAtTime time: TimeInterval) {
DispatchQueue.main.async {
self.statusLabel.text = self.trackingStatus
}
}
// MARK: - Session State Management
func session(_ session: ARSession,
cameraDidChangeTrackingState camera: ARCamera) {
switch camera.trackingState {
// 1
case .notAvailable:
trackingStatus = "Tacking: Not available!"
// 2
case .normal:
trackingStatus = "Tracking: All Good!"
// 3
case .limited(let reason):
switch reason {
case .excessiveMotion:
trackingStatus = "Tracking: Limited due to excessive motion!"
// 3.1
case .insufficientFeatures:
trackingStatus = "Tracking: Limited due to insufficient features!"
// 3.2
case .initializing:
trackingStatus = "Tracking: Initializing..."
// 3.3
case .relocalizing:
trackingStatus = "Tracking: Relocalizing..."
}
}
}
// MARK: - Session Error Managent
func session(_ session: ARSession,
didFailWithError error: Error) {
trackingStatus = "AR Session Failure: \(error)"
}
func sessionWasInterrupted(_ session: ARSession) {
trackingStatus = "AR Session Was Interrupted!"
}
func sessionInterruptionEnded(_ session: ARSession) {
trackingStatus = "AR Session Interruption Ended"
}
// MARK: - Plane Management
}
想必大部分的代碼你們可以看得很明白定罢,不過需要解釋的是ARCamera.trackingStatus:
- notAvailable: 由于不可預(yù)見的原因,AR session無法跟蹤。在這種情況下,你沒有什么可以做的,只是希望狀態(tài)改變到更可控的狀態(tài)旁瘫。
- normal: AR session 處于正常狀態(tài)祖凫。
顯示Debug選項
顯示Debug選項也不難,sceneView有一個debugOptions選項酬凳,該選項決定了你想要顯示哪些Debug信息惠况。
sceneView.debugOptions = []
下面是相關(guān)的文檔信息:
public struct SCNDebugOptions : OptionSet {
public init(rawValue: UInt)
public static var showPhysicsShapes: SCNDebugOptions { get } //show physics shape
public static var showBoundingBoxes: SCNDebugOptions { get } //show object bounding boxes
public static var showLightInfluences: SCNDebugOptions { get } //show objects's light influences
public static var showLightExtents: SCNDebugOptions { get } //show light extents
public static var showPhysicsFields: SCNDebugOptions { get } //show SCNPhysicsFields forces and extents
public static var showWireframe: SCNDebugOptions { get } //show wireframe on top of objects
@available(iOS 11.0, *)
public static var renderAsWireframe: SCNDebugOptions { get } //render objects as wireframe
@available(iOS 11.0, *)
public static var showSkeletons: SCNDebugOptions { get } //show skinning bones
@available(iOS 11.0, *)
public static var showCreases: SCNDebugOptions { get } //show subdivision creases
@available(iOS 11.0, *)
public static var showConstraints: SCNDebugOptions { get } //show slider constraint
@available(iOS 11.0, *)
public static var showCameras: SCNDebugOptions { get } //show cameras
}
你們可以自己試著加一下。例如宁仔,我們做如下設(shè)置:
sceneView.debugOptions = [
SCNDebugOptions.showFeaturePoints,
SCNDebugOptions.showWorldOrigin,
SCNDebugOptions.showBoundingBoxes,
SCNDebugOptions.showWireframe
]
呈現(xiàn)的效果如下:
Feature points: 這些是你整個場景中看到的小點;它們代表了 ARKit 在攝像機圖像中檢測到的顯著功能,這些功能又用作地標(biāo),以在設(shè)備移動時準(zhǔn)確跟蹤設(shè)備的位置和方向稠屠。
World origin: 這是紅色、綠色和藍(lán)色線的大交叉點,位于開始AR session的位置翎苫。紅線表示正 X 軸,綠線表示正 Y 軸,藍(lán)線表示正 Z 軸权埠。
Bounding boxes: 這些是所有 3D 對象周圍的框狀輪廓。
Wireframe: 需要注意的是,你現(xiàn)在可以在 AR 場景中每個 3D 對象的曲面上看到多邊形的輪廓煎谍。你可以精確查看這些幾何形狀的詳細(xì)程度攘蔽。
上一章 | 目錄 | 下一章 |
---|