ARKit教程iOS-FFmpeg音视频开发音视频专辑

ARKit教程05_第三章: Session Managemen

2019-08-06  本文已影响3人  张芳涛

前言

ARKit感兴趣的同学,可以订阅ARKit教程专题
源代码地址在这里

正文

在本章中,我们将了解AR session是什么以及如何管理它。这包括启动,停止和重置。还将学习如何处理会话错误并跟踪典型AR应用程序生命周期中可能发生的问题。

准备工作

我们需要在上一个项目的基础之上添加一些可交互的事件,我们需要在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) {
}

创建一个 AR session

我们之前在Main.storyboard中添加的ARSCNView是一个很基本的SceneKit view。它包括一个ARSession对象,该对象负责处理ARKit的运动追踪和图像处理工作。需要注意的是,ARSession对象是基于会话来进行工作的,也就是说,你需要先创建一个AR session实例,然后运行它,才可以启动AR的追踪过程。

创建configuration

在启动AR session,之前,必须创建AR session configuration (AR 会话配置)。此配置用于在真实世界(设备所在的位置)和虚拟 3D 世界(虚拟内容所在的位置)之间建立连接。

有两种类型的配置:

3DOF

3DOF跟踪设备旋转,分为Pitch(俯仰)、Roll(滚动)和 Yaw(偏航) 组件,表示围绕X 轴、Y 轴和 Z 轴的旋转。这由 AR 定向跟踪配置会话配置类型支持。

6DOF

6DOF 跟踪PitchRollYaw,类似于 3DOF。它还使用 SwayHeaveSurge 组件跟踪 3D 空间中的设备移动。这些新组件表示与 X 轴、Y 轴和 Z 轴平行的移动。这由 ARWorldTrack 配置会话配置类型支持。

检查设备功能

您正在创建 AR 应用程序需要 6DF 跟踪,因此你将使用 ARWorldTrackingConfiguration对象。良好的编码实践是检查设备是否能够支持此功能。

为此,在 initARSession() 中添加以下内容:

guard ARWorldTrackingConfiguration.isSupported else { print("*** ARConfig: AR World Tracking Not Supported") return }

可以使用 类的isSupported属性来检查设备是否支持该配置。如果不是,这是一个伟大的地方,通知用户适当的消息。以机智的方式向用户提供坏消息总是一个好主意。

现在您知道设备支持 6DOF,可以创建配置对象。

将以下内容添加到 initARSession() 的底部:

// 1
let config = ARWorldTrackingConfiguration()
// 2 
config.worldAlignment = .gravity 
// 3 
config.providesAudioData = false

上面的代码主要功能如下:

运行session

现在已经创建了 AR 配置,剩下的唯一事情就是启动 AR 会话。

initARSession() 方法中添加以下内容:

sceneView.session.run(config)

在 ARSCNView 的 ARSession 上调用run(_:options:),传入刚刚创建的 ARWorldTrackingConfiguration。就是这个,你的AR session现在启动并运行,并且它正在积极收集6DOF跟踪数据。

操控AR session

尽管 AR session已启动并运行,但它不是你可以启动和忽略的内容。可能需要根据应用中发生的情况控制其行为。 其实,控制 AR session是非常简单的。

更新状态信息

我们可以把AR session的实时状态显示到屏幕上,我们可以添加一个对象: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>
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

显示Debug选项

显示Debug选项也不难,sceneView有一个debugOptions选项,该选项决定了你想要显示哪些Debug信息。

sceneView.debugOptions = []

下面是相关的文档信息:

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
}

你们可以自己试着加一下。例如,我们做如下设置:

sceneView.debugOptions = [
        SCNDebugOptions.showFeaturePoints,
        SCNDebugOptions.showWorldOrigin,
        SCNDebugOptions.showBoundingBoxes,
        SCNDebugOptions.showWireframe
    ]

呈现的效果如下:

上一章 目录 下一章
上一篇下一篇

猜你喜欢

热点阅读