大多数浏览器和
Developer App 均支持流媒体播放。
-
使用 ARKit 打造更出色的空间计算体验
了解如何利用 ARKit 的最新功能打造引人入胜的沉浸式体验。探索如何使用空间跟踪和对象追踪来进一步提升与周围环境的互动体验。我们还将介绍如何让 App 在这个平台上对环境中的光线变化做出响应。探索手势跟踪和平面检测方面的改进,借此让你的空间体验更直观。
章节
- 0:00 - Introduction
- 2:30 - Room tracking
- 5:46 - Plane detection
- 6:46 - Object tracking
- 9:34 - World tracking
- 11:38 - Hand tracking
资源
相关视频
WWDC24
WWDC23
-
下载
大家好我叫 Divyesh 在这个讲座中你将了解 visionOS 的 ARKit 即将推出的一些精彩更新 去年我们推出了 ARKit 其中包含 为整个操作系统提供支持的 核心实时算法 大家使用 ARKit 的追踪和 场景理解功能打造出 非同凡响的空间体验 让我们惊叹不已 以“Blackbox”为例 它利用 ARKit 来检测 解开引人入胜的谜题 所需的手势 “Super Fruit Ninja”还运用手势 追踪来切水果并运用场景理解功能来 逼真呈现果肉果汁满地飞溅的效果 根据大家的反馈 我们在过去一年中 开发了一些新功能 旨在帮助大家的 App 进一步理解周围环境并与之互动 我们来了解一些相关改进 我首先要介绍场景理解方面的 一些改进 我们新增了房间追踪功能 还更新了平面检测功能 有助于 根据所在的房间提供个性化体验 我还将介绍新的对象追踪功能 可以用它为现实世界中的物品 创建交互式可视化效果 随后我会讲解 ARKit 的现实场景 追踪功能如何在各种光线条件下 变得更加稳定可靠 最后我会介绍一下手势追踪 方面的最新改进能为你的 App 带来哪些好处 在深入探讨之前 我们先来 快速回顾一下 visionOS 上的 ARKit 总结一下 当 visionOS App 呈现全空间时 它能够以锚点形式接收 来自 ARKit 的数据
锚点表示三维空间中的位置和方向 例如平面检测数据以 PlaneAnchor 的形式提供 其中包含有关 在现实世界中检测到的 各个表面的信息
ARKit 会通过数据提供程序 将锚点提供给 App 数据提供程序是用于配置单项 ARKit 功能以及接收其数据的接口 PlaneDetectionProvider 是 用于接收 PlaneAnchor 的接口
你可以通过提供需要在用户体验中 一起使用的一组数据提供程序来 运行 ARKitSession 如果你刚刚接触 ARKit API 或希望了解更多背景信息 强烈建议你观看去年的“了解 用于空间计算 的 ARKit”讲座 接下来我们来了解 第一项新功能:房间追踪 visionOS 上许多 App 的使用场景 都设在用户所在的房间内 借助网格和平面锚点数据 你已经 可以使用以逼真方式放置的虚拟内容 来增强场景 现在你可以将互动体验 提升至全新境界 试想一下当你走进卧室时 会有一只虚拟宠物迎接你 借助房间追踪功能 你可以为进入 的每个空间量身定制独一无二的体验
当你环顾四周时 ARKit 可以识别出 当前所在房间的边界 它会利用这些信息来计算与检测到的 墙壁和地面精确匹配的几何图形 此外 ARKit 可以识别 不同房间之间的转换 当你进入一个新区域时 它会切换为 提供你当前所处空间的数据 这有助于 App 根据所在房间 展现不同的体验
所有这些信息都通过新的房间 追踪数据提供程序呈现 这需要获得现实场景感知授权
RoomTrackingProvider 可以提供 你曾去过的房间的相关信息 如果 ARKit 确定你处于受限空间中 则可以通过此接口 来访问当前房间的锚点 你可以使用当前房间锚点 根据这一室内布局来塑造用户体验
你的 App 还可以侦听 异步房间追踪更新 其方式类似于从我们的其他 数据提供程序接收锚点 这种方式便于接收当前所在空间的 最新信息 尤其在跨房间转换时
请注意 RoomTrackingProvider 只会更新当前所在房间的锚点数据
我们来看看提供的数据 每个 RoomAnchor 都包含 有关特定受限空间的空间信息
此锚点可以指示它是不是 为当前房间建模 当你希望特定内容只出现在 当前所在的空间中时 这会很有用
每个 RoomAnchor 还包含了 四周墙壁和地面的几何图形 它由定义房间形状的一系列 顶点、边和三角面组成 请注意 与网格锚点和平面锚点 呈现的几何图形相比 此网格与房间边界更加贴合
你还可以选择获取由一组不相交的 几何图形构成的网格 其中每个几何图形对应 一整面墙壁或一整片地面 在遮挡放置在房间外的虚拟内容 或者实现沿整面墙打开虚拟传送门 等增强效果时 这些几何 图形可能会非常有用 你还可以测试给定的三维点 是不是存在于房间边界内 与现实场景追踪功能配合使用时 你可以创造出神奇的体验 在进入特定房间时 让虚拟物体变得鲜活起来
最后 这个新的锚点能够提供与房间 关联的平面锚点 ID 和网格锚点 ID 这些数据与其他场景理解功能 结合使用时 有助于优化 App 例如你可能希望避免对当前房间之外 的平面和网格执行开销较大的操作 利用房间追踪功能改进 App 的方法有很多 前面只列举了其中的几种方法 非常期待看到大家能解锁更多方法! 接下来我们来谈谈 平面检测功能的一项更新 ARKit 会检测周围环境中的平面表面 因此能够以 PlaneAnchor 的形式 提供这些表面的相关信息 在各个表面放置虚拟内容时 例如 在桌面上放置棋盘游戏或在墙上放置 虚拟海报 这些平面锚点非常有用 PlaneDetectionProvider 会告知 App 检测到了水平表面和垂直表面
今年我们将推出全新的倾斜平面 对齐功能 用于检测成角度的表面
App 将继续获得水平对齐和垂直对齐 的平面锚点 这些锚点不会发生 任何变化 如果你还希望获得倾斜平面锚点 只需进行一项更改就能轻松实现 只需更新 在 PlaneDetectionProvider 中 配置的对齐方式即可
只需添加新的倾斜对齐 就是这么简单!
接下来我们看看对象追踪 这是 visionOS 的新增功能 ARKit 现在可以追踪静态 放置在环境中的现实世界物体 借助对象追踪功能 你可以获得各个 物品的位置和方向 以便将虚拟内容 锚定在这些物品上 例如教育类 App 可以为观察特定 仪器的用户展现 3D 可视化效果 要让 ARKit 追踪这些物品 你需要提供一组 ReferenceObject 参考对象会对已知现实世界物品的 空间特征进行编码 要创建 ReferenceObject 首先需要 USDZ 格式的待追踪物品 3D 模型
然后可以使用 CreateML 全新的 空间对象追踪功能 以根据素材 生成 ReferenceObject
最后可以使用 ReferenceObject 来通过 ARKit 进行追踪
要进一步了解如何创建 ReferenceObject 请观看今年的讲座 “探索适用于 visionOS 的对象追踪”
在这个讲座中 我们将重点介绍 在创建 ReferenceObject 后 通过 ARKit 追踪 实体物品的最后一步
我们来看看新的 API 让这一操作变得多么简单
ReferenceObject 可在运行时 通过文件 URL 或套装载入
在本例中我们通过 URL 载入 一个地球仪 ReferenceObject
成功载入参考对象后可以使用该对象 配置新的 ObjectTrackingProvider
接下来可以在 ARKitSession 上 运行新的 ObjectTrackingProvider
数据提供程序进入运行状态后 即可开始处理传入的追踪结果
这些追踪结果将以 ObjectAnchor 的形式提供 每个 ObjectAnchor 代表追踪的一个物品
ObjectAnchor 包含检测到的 对象的轴对齐边界框 你可以获取边界框的中心和范围 及其最小和最大 3D 坐标点
这个锚点还包含其对应的 ReferenceObject 如果 ReferenceObject 包含基础 USDZ 文件路径 则可以从这个锚点 访问这一路径
和其他数据提供程序类似 你也可以侦听 ObjectAnchor 更新 然后可以利用最新的追踪功能更新 为对象增添富有感染力的虚拟内容 例如你可以为地球仪添加具有 逼真阴影效果的绕行天体 甚至可以让人窥探地核的奥秘!
此外我们还将发布一些示例 App 可供你下载并在自己的设备上试用 请记得稍后来查看这些 App 了解更多详细信息 接下来我要介绍现实场景追踪功能的 一些改进 这项功能在这个平台中 发挥着基础作用 ARKit 依靠多种摄像头和传感器来运 行诸如现实场景追踪之类的复杂算法 如果用户所在的实际位置光线不足 就会影响传感器数据 并且可能会 导致算法无法流畅运行 例如身处无光线的黑暗房间可能会影 响使用者体验到的现实场景追踪质量
今年我们添加了一项机制 来对这类光线变化做出响应 如果系统检测到由于光线条件不佳或 其他物理因素导致追踪受限 则会 只追踪对象方向的变化 而不追踪其在空间中的位置
这种情况下你的 App 将受益于 在系统级别实现的基于方向的追踪 这意味着即使在具有挑战性的环境中 也不必担心会由于光线原因而完全 丧失追踪能力
如果你想做好充分准备来应对这类 情况 可以使用我们提供的多个 API 这些 API 可以告知你追踪功能出现 了相应变化以便你相应调整用户体验 例如你可能需要在不更新锚定位置的 情况下 适当重新排列已放置的内容 如果你的 App 确实依赖于完整的 现实场景追踪 则你可能需要让用户 向更加明亮的环境移动 以便恢复正常的体验
如果你使用的是 SwiftUI 则可通过新的“现实场景追踪限制” 环境值来提供这一指示 例如你可以侦听这个值的变化 以便 在无法使用位置追踪时重新排列内容
如果你使用的是 ARKit 我们还扩展了DeviceAnchor 现在它包含“.trackingState”属性 该属性会指示追踪功能完全正常 还是仅限基于方向的追踪 如果系统切换为基于方向的追踪 则现有的现实场景锚点 可能会标记为“未追踪” 等到现实场景追踪恢复正常后 持久性锚点的追踪状态将会恢复
最后我要介绍手势追踪方面的 一些改进 手势追踪是这个平台上的 主要输入方式 我们在推出 visionOS 时添加了 追踪使用者手部和手指的功能 App 可以使用这些信息来检测手势 并将虚拟内容锚定到手部
去年我们确立了以 HandAnchor 的 形式获取这一信息的两种途径 你可以轮询 HandTrackingProvider 以获取最新更新 也可以 在 HandAnchor 可用时 以异步方式接收更新 我们很高兴地宣布 HandTrackingProvider 现在能够 以显示速率提供这些数据了! 异步 HandAnchor 更新会存在 一些延迟 但如果采用更快速的 与显示同步的频率来提供这些数据 更新会更加流畅 佩戴 Apple Vision Pro 时 这种效果尤其显而易见 如果你希望将手势追踪结果的延迟 降至最低 ARKit 现在可以预测 有望在不久之后某个给定时间 存在的 HandAnchor 无论 App 使用 Compositor Services 还是 RealityKit 进行渲染 你都可以利用新的手部预测 API 更快地获得追踪结果
我们来看一个例子 如果使用的是 Compositor Services 则应以“可追踪的锚点时间”为目标 这是 visionOS 的新增功能 基于这个时间戳来预测 HandAnchor 可以帮助你实现最佳内容配准效果
你可以将该时间戳转换为秒并将其提 供给 ARKit 以进行复杂的前瞻预测 这里展示的 App 使用Compositor Services 来渲染一个虚拟茶壶 通过使用预测的 HandAnchor 锚定的茶壶会始终固定在这只手上 即使这只手来回移动也是如此 请注意由于这是低延迟预测 因此可能会牺牲一定程度的准确性 要详细了解如何使用 Compositor Services 进行渲染 建议观看今年的讲座“在 visionOS 中使用透视功能渲染 Metal” 你可能还需要回顾一下去年的讲座 “了解用于空间计算的 ARKit” 中展示的示例
手势追踪功能的这两项改进 在不同的用例中各有千秋 与显示同步的 HandAnchor 更新非常 适合在对延迟没有严格要求的体验中 进行手势检测和绘制流畅的笔触 如果你希望内容尽可能贴合手部 而流畅度不太重要 那么手部预测 就会非常有用
在 RealityKit 这边 我们还提供了手部 AnchorEntities 方面的这些改进
如果使用 RealityKit 在双手附近附加内容 可以根据需要选择 “连续”或“预测”手部追踪
如需查看详细示例 请观看新的讲座 “使用 RealityKit 构建 空间绘画 App” 以上就是今年 ARKit 的新功能 总结一下 我介绍了我们的最新改进 这些改进有助于提升空间计算体验
大家还了解了新的房间追踪和 对象追踪功能 这些功能有助于 进一步激发你的创造力 我们还举办了更多精彩讲座 供你探索新的 visionOS 我和整个团队万分期待看到大家 使用最新 ARKit 实现的精彩体验! 谢谢观看!
-
-
3:35 - RoomTrackingProvider
// RoomTrackingProvider @available(visionOS, introduced: 2.0) public final class RoomTrackingProvider: DataProvider, Sendable { /// The room which a person is currently in, if any. public var currentRoomAnchor: RoomAnchor? { get } /// An async sequence of all anchor updates. public var anchorUpdates: AnchorUpdateSequence<RoomAnchor> { get } ... }
-
4:20 - RoomAnchor
@available(visionOS, introduced: 2.0) public struct RoomAnchor: Anchor, Sendable, Equatable { /// True if this is the room which a person is currently in. public var isCurrentRoom: Bool { get } /// Get the geometry of the mesh in the anchor's coordinate system. public var geometry: MeshAnchor.Geometry { get } /// Get disjoint mesh geometries of a given classification. public func geometries(of classification: MeshAnchor.MeshClassification) -> [MeshAnchor.Geometry] /// True if this room contains the given point. public func contains(_ point: SIMD3<Float>) -> Bool /// Get the IDs of the plane anchors associated with this room. public var planeAnchorIDs: [UUID] { get } /// Get the IDs of the mesh anchors associated with this room. public var meshAnchorIDs: [UUID] { get } }
-
8:06 - Load Object Tracking referenceobject
// Object tracking Task { do { let url = URL(fileURLWithPath: "/path/to/globe.referenceobject") let referenceObject = try await ReferenceObject(from: url) let objectTracking = ObjectTrackingProvider(referenceObjects: [referenceObject]) } catch { // Handle reference object loading error. } ... }
-
8:27 - Run ARKitSession with ObjectTracking provider
let session = ARKitSession() Task { do { try await session.run([objectTracking]) } catch { // Handle session run error. } for await event in session.events { switch event { case .dataProviderStateChanged(_, newState: let newState, _): if newState == .running { // Ready to start processing anchor updates. } ... } } }
-
8:43 - ObjectAnchor
// ObjectAnchor @available(visionOS, introduced: 2.0) public struct ObjectAnchor: TrackableAnchor, Sendable, Equatable { /// An axis-aligned bounding box. public struct AxisAlignedBoundingBox: Sendable, Equatable { ... } /// The bounding box of this anchor. public var boundingBox: AxisAlignedBoundingBox { get } /// The reference object which this anchor corresponds to. public var referenceObject: ReferenceObject { get } }
-
11:03 - World Tracking - reacting to changes in lighting conditions
struct WellPreparedView: View { @Environment(\.worldTrackingLimitations) var worldTrackingLimitations var body: some View { ... .onChange(of: worldTrackingLimitations) { if worldTrackingLimitations.contains(.translation) { // Rearrange content when anchored positions are unavailable. } } } }
-
12:51 - Hands prediction
// Hands prediction func submitFrame(_ frame: LayerRenderer.Frame) { ... guard let drawable = frame.queryDrawable() else { return } // Get the trackable anchor time to target. let trackableAnchorTime = drawable.frameTiming.trackableAnchorTime // Convert the timestamp into units of seconds. let anchorPredictionTime = LayerRenderer.Clock.Instant.epoch.duration(to: trackableAnchorTime).timeInterval // Predict hand anchors for the time that provides best content registration. let (leftHand, rightHand) = handTracking.handAnchors(at: anchorPredictionTime) ... }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。