终于等到清明节假期可以来更新点内容了,ARKit 3.5是11天前发布的,也拖的够久的了。废话不多说,正文开始。

如何查看Apple文档的更新?

以ARKit文档为例,虽然我们知道了苹果更新了ARKit 3.5,但是我们如何找到更新的内容呢?我们先看一下默认的界面:

根本啥也看不出来啊,感觉跟之前是一样的。先别急,我们可以看一下右上角的“API Changes: Show”字样,点击一下,看看会有什么变化:

这样文档就把新版本文档的修改内容展示出来了,具体的修改、增加和废弃条目的数量也会展示出来。这个数量只是表示当前页面的数量,具体各层级文档的修改数量要到各个层级页面去查看。接下来继续看看ARKit 3.5究竟更新了哪些文档吧。

修改内容

首页修改的内容有4部分:ARSession, ARConfiguration, ARView, World Tracking.

1. ARSession

ARSession中的修改只有一处修改,即ARSession.RunOptions(当修改AR会话的配置项时,可以用来转变ARSession当前状态的可选项)

再深入ARSession.RunOptions,可以看到其增加了一个可选项resetSceneReconstruction(用来重置scene mesh - 场景网格的可选项)。

1.1 resetSceneReconstruction

用来重置场景网格的可选项

声明

static var resetSceneReconstruction: ARSession.RunOptions { get }

讨论

当重置场景重建时,ARKit将会移除所有会话中已经存在的网格锚点(ARMesh Anchor)

我们可以看到,该属性需要iOS 13.4以上的系统才能够支持。

2.ARConfiguration

ARConfiguration中只有一处增加,即增加了Reconstructing the Scene - 重建场景

2.1 ARConfiguration.SceneReconstruction

允许ARKit检测物理环境形状的可选项。

声明
struct SceneReconstruction
概述

当你设置其中一个值到世界追踪配置的场景重建属性值时,ARKit将会为你提供一套网格来对用户周围的真实环境建模。

主题

环境建模


init(rawValue: UInt)

初始化一个场景重建对象

static var mesh: ARConfiguration.SceneReconstruction

近似物理环境的多边形网格

static var meshWithClassification: ARConfiguration.SceneReconstruction

一个近似物理环境的形状,包含了对真实世界中的物体进行分类的标示

关联

符合OptionSet 接口

3. ARView

其中有三处修改和一处新增,分别是:Scene, ARView.Enviroment, ARView.DebugOptions 和 gestureRecognizer

3.1 Scene

3.1.1 CollisionGroup 碰撞组

在碰撞组中增加了一个新的类型属性 sceneUnderstanding

3.2 ARView.Enviroment

其中增加了一个属性sceneUnderstanding 和其结构体的定义struct ARView.Environment.SceneUnderstanding

3.2.1 sceneUnderstanding
声明
var sceneUnderstanding: ARView.Environment.SceneUnderstanding { mutating get set }
3.2.2 struct ARView.Environment.SceneUnderstanding
声明
struct ARView.Environment.SceneUnderstanding
主题

实例属性 - var options: ARView.Environment.SceneUnderstanding.Options

结构体(内容较多后续翻译) - struct ARView.Environment.SceneUnderstanding.Options

3.3. ARView.DebugOptions

其中修改了两个地方init(rawValue: Int)static let showSceneUnderstanding: ARView.DebugOptions

3.3.1 init(rawValue: Int)

没看出来具体的变化

3.3.2 类型属性 showSceneUnderstanding: ARView.DebugOptions

3.4. gestureRecognizer

修改了该方法,增加了接受UIEvent事件的识别方法

3.4.1 func gestureRecognizer(UIGestureRecognizer, shouldReceive: UIEvent) -> Bool

询问委托,手势识别器是否可以接受一个表示触摸或者按压的事件的对象

声明
optional func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, 
                  shouldReceive event: UIEvent) -> Bool
参数

gestureRecognizer - UIGestureRecognizer 虚基类的子类的实例

event - 来自于当前一系列按压或者触摸的UIEvent对象

返回值

通过返回false,在收到该事件时阻止手势识别器

讨论

UIKit无论在调用gestureRecognizer(_:shouldReceive:) 方法(参数时UIPress事件)还是 gestureRecognizer(_:shouldReceive:) 方法(参数时UITouch事件)之前,都会调用该方法一次。

4. World Tracking

其中修改了class ARWorldTrackingConfiguration ,添加了class ARMeshAnchor

4.1 ARWorldTrackingConfiguration

其中增加了var sceneReconstruction: ARConfiguration.SceneReconstruction - 用来启用场景重建的标志位,和 class func supportsSceneReconstruction(ARConfiguration.SceneReconstruction) -> Bool 查看设备是否支持场景重建的方法。

4.1.1 sceneReconstruction
声明
var sceneReconstruction: ARConfiguration.SceneReconstruction { get set }
讨论

当你启用场景重建功能后,ARKit将会根据预估物理环境的形状来提供一套多边形网格。在设置这个属性之前,通过调用supportsSceneReconstruction(_:) 方法来确保设备支持。场景重建的demo app参见Visualizing and Interacting with a Reconstructed Scene.

如果你启用了平面检测,ARKit将会将会应用该信息到网格上。当LiDAR扫描仪可能在现实世界的表面上产生一个略微不平整的网格时,ARKit会在检测到该表面上的平面时将网格平滑化。

如果你启用了人体遮挡,ARKit将会根据它在摄像头信息流中检测到的任何人体来调整网格。ARKit按照personSegmentation或personSegmentationWithDepth帧语义定义的那样,删除场景网格中与人物重叠的任何部分。

4.2 ARMeshAnchor

重建后的场景网格的一部分

声明
class ARMeshAnchor : ARAnchor
概述

ARKit将用户周围的重构的真实世界场景细分为网格锚点。

随着ARKit对现实世界的理解的完善,网格锚点会不断地更新它们的数据。虽然ARKit会更新一个网格来反映物理环境的变化(比如人拉出椅子时),但网格的后续变化并不是为了做出实时的反映。

主题
4.2.1 var geometry: ARMeshGeometry

网格的形状和分类等三维信息。

声明
var geometry: ARMeshGeometry { get }
讨论

包含了锚点的网格数据部分,与AR会话中的任何其他网格锚点一起,共同重建用户周围的场景。网格锚点将这些数据记录在自己的坐标系中。

4.2.2 class ARMeshGeometry

网格信息以高效、基于数组的格式存储。

声明
class ARMeshGeometry : NSObject
概述

这个类中的信息持有场景网格中的单个锚点的几何数据。锚点的网格中的每个顶点代表一个连接点。每个三个顶点组合形成一个独特的三角形,称为面。每个面包括一个外向法线和一个分类。如果ARKit不能对一个特定的面进行分类,那么这个值是0,即ARMeshClassification.none的值。

主题

访问几何数据

4.2.2.1 var vertices: ARGeometrySource

网格的顶点

声明

var vertices: ARGeometrySource { get }

讨论

count等于顶点的总数。由于每个顶点的类型是SIMD3,所以componentsPerVector是三个。

下面的代码演示了在特定索引处检索一个顶点。

extension ARMeshGeometry { 
    func vertex(at index: UInt32) -> SIMD3<Float> {
        assert(vertices.format == MTLVertexFormat.float3, "Expected three floats (twelve bytes) per vertex.")
        let vertexPointer = vertices.buffer.contents().advanced(by: vertices.offset + (vertices.stride * Int(index)))
        let vertex = vertexPointer.assumingMemoryBound(to: SIMD3<Float>.self).pointee
        return vertex
    }
}
4.2.2.2 class ARGeometrySource

保存在基于缓冲区数组的网格数据

声明

class ARGeometrySource : NSObject

概述

网格锚点的几何体(ARMeshGeometry) 使用几何体来源以一种有效的、类似数组的格式来保存三维数据,如顶点和法线。一个Metal缓冲区封装了这些数据,而其他属性表述了如何解释这些数据。

在componentPerVector大于1的情况下,几何体来源数组的元素类型本身就是一个序列(成对、三元组等)。

主题

4.2.2.2.1 var buffer: MTLBuffer

保存了向量列表的Metal缓冲区

声明

var buffer: MTLBuffer { get }

讨论

缓冲区中的每个向量是由格式定义的类型。每个向量本身可能包含多个标量,由componentPerVector定义。

缓冲区的存储模式是MTLStorageMode.share,它允许同时在CPU和GPU上访问。

4.2.2.2.2 var componentsPerVector: Int

每个向量中的标量分量的数量。

声明

var buffer: MTLBuffer { get }

讨论

在 componentsPerVector大于1的情况下,几何体-来源数组的元素类型本身就是一个序列。

4.2.2.2.3 var count: Int

缓冲区中向量的数量。

声明

var count: Int

4.2.2.2.4 var format: MTLVertexFormat

缓冲区中向量的数量。

声明

var format: MTLVertexFormat { get }

4.2.2.2.5 var offset: Int

从缓冲区开始的偏移量,以字节为单位。

声明

var offset: Int { get }

4.2.2.2.5 var stride: Int

缓冲区中一个向量的起始点到下一个向量的起始点的长度,单位为字节。

声明

var stride: Int { get }

讨论

Stride可能包含padding,所以它不一定等于向量格式的总大小(以字节为单位)。

4.2.2.3 var classification: ARGeometrySource?

网格中每个面的分类。

声明

var classification: ARGeometrySource? { get }

讨论

数组的每个元素(ARGeometrySource)都是一个分类,对应于几何体中的一个面。这个属性的计数表示几何体中的面的数量。每个索引的默认值是0, 即 ARMeshClassification.none的值。

下面的代码演示了如何检索一个特定面的分类。

extension ARMeshGeometry {
    func classificationOf(faceWithIndex index: Int) -> ARMeshClassification {
        guard let classification = classification else { return .none }
        let classificationAddress = classification.buffer.contents().advanced(by: index)
        let classificationValue = Int(classificationAddress.assumingMemoryBound(to: UInt8.self).pointee)
        return ARMeshClassification(rawValue: classificationValue) ?? .none
    }
}

如下的demo app展示了分类操作 Visualizing and Interacting with a Reconstructed Scene.

4.2.2.3 enum ARMeshClassification

ARKit可以识别的现实世界物体的类目的枚举。

声明

enum ARMeshClassification : Int

概述

当你在一个世界追踪配置项上启用场景重建(SeneReconstruction)时,ARKit提供了几个网格锚点(ARMeshAnchor),这些锚点会协同估计物理环境的形状。在这个真实世界的模型中,ARKit可以识别特定的物体,如座位、窗户、桌子或墙壁。ARKit通过在网格的几何属性中暴露一个或多个ARMeshClassification实例来共享这些信息。

有关演示网格分类的示例应用,请参见Visualizing and Interacting with a Reconstructed Scene.

主题

枚举项:

屋顶、门、地板、无法识别、座椅、桌子、墙壁、窗户

4.2.2.4 var faces: ARGeometryElement

一个包含几何体的面的顶点索引的缓冲区对象。

声明

var faces: ARGeometryElement { get }

讨论

基于缓冲区的数组中的每个元素都是一个三个索引的组合,形成一个独特的三角形,或者说是面。索引指的是该顶点在顶点数组中的位置。这个属性的计数表示面的数量。

下面的代码演示了如何获取特定面的顶点。

extension ARMeshGeometry {
    func vertexIndicesOf(faceWithIndex index: Int) -> [Int] {
        let indicesPerFace = faces.indexCountPerPrimitive
        let facesPointer = faces.buffer.contents()
        var vertexIndices = [Int]()
        for offset in 0..<indicesPerFace {
            let vertexIndexAddress = facesPointer.advanced(by: (index * indicesPerFace + offset) * MemoryLayout<UInt32>.size)
            vertexIndices.append(Int(vertexIndexAddress.assumingMemoryBound(to: UInt32.self).pointee))
        }
        return vertexIndices
    }
}
4.2.2.5 class ARGeometryElement

索引数据的容器,如面的顶点索引等。

声明

class ARGeometryElement : NSObject

概述

ARMeshGeometry使用几何元素来存储面的数据(见)。每个面是由元类型定义的,例如,ARGeometryPrimitiveType.triangle。

为了演示,一个具有两个三角形类型的面的ARMeshGeometry实例会产生以下配置。

主题

访问索引数据

4.2.2.5.1 var buffer: MTLBuffer

保存了元数据的Metal缓冲区


获取索引信息

4.2.2.5.2 var bytesPerIndex: Int

每个索引占用的字节大小

4.2.2.5.3 var count: Int

缓冲区中元数据的数量

4.2.2.5.4 var indexCountPerPrimitive: Int

每个元数据的索引数

4.2.2.5.5 var primitiveType: ARGeometryPrimitiveType

数据的几何类型(三角形或者直线)

声明

enum ARGeometryPrimitiveType : Int

概述

当你在世界追踪配置上启用场景重建(simpleaseReconstruction)时,ARKit会提供一个线框网格,该网格使用一个连接的顶点集合来模拟真实世界的形状。ARKit使用ARGeometryPrimitiveType来指示如何解释该网格的特定属性。例如,网格几何体的面属性指定了几何体中的每个面都是ARGeometryPrimitiveType.triangle类型。

枚举项:直线、三角形

4.2.2.5.6 var normals: ARGeometrySource

定义了每个面的哪个方向是外面的射线