Highlight
Object Capture 从 macOS 专属功能变成了 iOS 上的完整端到端体验:用户用 iPhone 或 iPad 扫描物体,系统自动拍摄、实时引导、在设备端重建,几分钟内输出 USDZ 格式的 3D 模型,LiDAR 支持让低纹理物体也能获得高质量重建。
核心内容
以前要做 3D 物体扫描,流程很繁琐:用 iPhone 拍一堆照片,传到 Mac,用 Object Capture API 重建模型。整个过程跨设备、耗时长,普通用户很难上手。
WWDC23 把这一切搬到了 iOS 上。现在拍摄和重建都在同一台设备完成,Apple 还提供了完整的 Sample App 作为起点。
LiDAR 让低纹理物体也能扫描
(03:02)Object Capture 之前对纹理丰富的物体效果最好——比如花纹复杂的花瓶、雕刻精细的木雕。但对低纹理物体(纯色椅子、光滑桌面)效果很差,因为纯视觉算法难以从单调表面提取特征点。
今年加入 LiDAR 点云数据后,情况变了。扫描时系统同时采集 RGB 照片和 LiDAR 点云,两者融合重建。RGB 负责颜色和精细纹理,LiDAR 负责几何形状和深度信息。一把纯色的椅子,以前重建出来可能缺面少角,现在能恢复完整的 3D 形状。
当然,有些物体仍然不适合扫描:反光表面、透明材质、极细结构。这些限制暂时还在。
引导式拍摄
(04:36)手动拍照很容易出问题:角度不够、光线太差、手抖模糊。Guided Capture 把这些麻烦自动化了。
系统自动选择拍摄时机:当画面清晰度、曝光、构图都达标时才按下”快门”。用户只需要拿着设备绕物体转圈,系统会在合适的角度自动采集。
拍摄转盘(Capture Dial)是核心 UI 元素。它显示物体各个角度已经被覆盖的程度,引导用户把转盘填满。遗漏的区域用颜色标识,用户一眼就知道还需要扫哪里。
实时反馈覆盖常见错误场景:
- 光线不足:提醒调整照明,建议使用漫反射光源
- 移动太快:自动暂停拍摄,提醒放慢速度
- 距离不当:太远或太近都会提示
- 物体出框:箭头指示调整方向
翻转策略
(06:45)要获得完整模型,通常需要翻转物体扫描底面。但不是所有物体都适合翻转:
- 刚性物体可以翻转,可变形物体不建议
- 纹理丰富的物体适合翻转,对称或重复纹理的物体不适合
- 低纹理物体翻转后系统难以对齐不同扫描段
系统提供 API 判断物体是否有足够纹理支持翻转扫描。翻转时建议扫描三个方向,每个方向间保持图像重叠。
不能翻转的物体,建议从三个不同高度拍摄。
详细内容
状态机驱动的拍摄流程
(09:30)Object Capture 用状态机管理整个拍摄流程:
initializing → ready → detecting → capturing → finishing → completed
每个状态对应不同的 UI 和操作:
- initializing:session 刚创建
- ready:显示相机画面,等待用户选择物体
- detecting:自动检测物体边界框
- capturing:自动拍摄,显示拍摄转盘
- finishing:保存数据
- completed:可以拆除 session,进入重建阶段
出错时进入 failed 状态,需要重新创建 session。
代码实现
(10:03)创建 session:
import RealityKit
import SwiftUI
var session = ObjectCaptureSession()
(10:25)启动 session:
var configuration = ObjectCaptureSession.Configuration()
configuration.checkpointDirectory = getDocumentsDir().appendingPathComponent("Snapshots/")
session.start(
imagesDirectory: getDocumentsDir().appendingPathComponent("Images/"),
configuration: configuration
)
关键点:
imagesDirectory存放拍摄的照片checkpointDirectory存放检查点数据,加速重建- session 启动后进入 ready 状态
(10:50)创建拍摄视图:
import RealityKit
import SwiftUI
struct CapturePrimaryView: View {
var body: some View {
ZStack {
ObjectCaptureView(session: session)
}
}
}
关键点:
ObjectCaptureView自动根据 session 状态显示对应的 UI- 不包含任何 2D 文字或按钮,方便自定义外观
- 可以嵌入到现有应用的 SwiftUI 界面中
(11:20)状态切换的 UI 控制:
var body: some View {
ZStack {
ObjectCaptureView(session: session)
if case .ready = session.state {
CreateButton(label: "Continue") {
session.startDetecting()
}
} else if case .detecting = session.state {
CreateButton(label: "Start Capture") {
session.startCapturing()
}
}
}
}
关键点:
- ready 状态显示 Continue 按钮,调用
startDetecting() - detecting 状态显示 Start Capture 按钮,调用
startCapturing() - 也可以提供 Reset 按钮回到 ready 状态重新选择物体
(12:50)完成一轮扫描后:
var body: some View {
if session.userCompletedScanPass {
VStack {
CreateButton(label: "Finish") {
session.finish()
}
}
} else {
ZStack {
ObjectCaptureView(session: session)
}
}
}
关键点:
userCompletedScanPass表示拍摄转盘已填满- 可以 Finish 结束拍摄,或继续下一轮扫描
- 建议完成三轮扫描获得最佳效果
点云预览
(15:00)可以用 ObjectCapturePointCloudView 预览已扫描的部分:
var body: some View {
if session.userCompletedScanPass {
VStack {
ObjectCapturePointCloudView(session: session)
CreateButton(label: "Finish") {
session.finish()
}
}
} else {
ZStack {
ObjectCaptureView(session: session)
}
}
}
关键点:
- 点云视图会暂停拍摄,让用户交互式查看
- 可以全屏显示,也可以和按钮组合使用
- 帮助用户判断扫描是否完整
重建 API
(15:50)拍摄完成后,用 PhotogrammetrySession 重建模型:
var body: some View {
ReconstructionProgressView()
.task {
var configuration = PhotogrammetrySession.Configuration()
configuration.checkpointDirectory = getDocumentsDir()
.appendingPathComponent("Snapshots/")
let session = try PhotogrammetrySession(
input: getDocumentsDir().appendingPathComponent("Images/"),
configuration: configuration
)
try session.process(requests: [
.modelFile(url: getDocumentsDir().appendingPathComponent("model.usdz"))
])
for try await output in session.outputs {
switch output {
case .processingComplete:
handleComplete()
// 处理其他输出消息
default:
break
}
}
}
}
关键点:
- 使用与 macOS 相同的异步 API
- iOS 只支持 reduced 细节级别
- 输出包含 diffuse、ambient occlusion 和 normal 贴图
- 重建在设备端完成,不需要网络或 Mac
为 Mac 重建采集更多数据
(17:02)如果想在 Mac 上获得更高质量的重建,可以启用超量采集:
var configuration = ObjectCaptureSession.Configuration()
configuration.isOverCaptureEnabled = true
session.start(
imagesDirectory: getDocumentsDir().appendingPathComponent("Images/"),
configuration: configuration
)
关键点:
isOverCaptureEnabled = true允许采集比 iOS 重建所需更多的照片- 额外的照片存储在 Images 文件夹中
- 可以导入到 Reality Composer Pro 在 Mac 上重建
- 不需要写代码,直接在 Reality Composer Pro 中导入即可
新重建特性
(18:40)今年重建 API 新增两个功能:
Pose 输出:获取每张照片的相机位姿
try session.process(requests: [
.poses,
.modelFile(url: modelURL)
])
for try await output in session.outputs {
switch output {
case .poses(let poses):
handlePoses(poses)
case .processingComplete:
handleComplete()
}
}
关键点:
- 每个 pose 包含相机的位置和朝向
- 在模型生成前就会返回
- 可用于自定义处理流程
自定义细节级别(macOS):可以控制网格简化程度、纹理分辨率、格式和包含哪些贴图。
核心启发
1. 做一个电商商品 3D 展示工具
- 做什么:让商家用 iPhone 扫描商品,自动生成 3D 模型嵌入到商品详情页
- 为什么值得做:Object Capture 让 3D 建模零门槛,不需要专业设备和技能
- 怎么开始:基于 Sample App 修改 UI,扫描后上传 USDZ 到服务器,在网页中用 Quick Look 展示
2. 做一个 AR 家具摆放应用
- 做什么:用户扫描自己的家具,在 AR 中预览摆放效果
- 为什么值得做:LiDAR 支持让低纹理的家具也能获得不错的模型质量
- 怎么开始:集成 Object Capture 扫描流程,用 RealityKit 显示模型,支持缩放和旋转
3. 做一个 3D 资产管理系统
- 做什么:为设计师和开发者管理 3D 模型库,支持扫描、标注、分类、导出
- 为什么值得做:扫描 + 重建 + 预览全在设备端完成,不需要后端
- 怎么开始:用 SwiftData 存储模型元数据,用 Object Capture 扫描,用 Quick Look 预览
4. 做一个教育类的 3D 博物馆应用
- 做什么:学生扫描博物馆展品,在应用中查看 3D 模型并学习相关知识
- 为什么值得做:Guided Capture 的引导让非专业用户也能获得高质量扫描
- 怎么开始:封装 Object Capture 为简单流程,扫描后关联教育内容,支持 AR 查看
关联 Session
- Create 3D models for Quick Look spatial experiences — 为 visionOS Quick Look 创建 3D 内容的最佳实践
- Meet Reality Composer Pro — Apple 的 3D 内容创作工具,支持导入 Object Capture 数据
- Work with Reality Composer Pro content in Xcode — 在 Xcode 中使用 Reality Composer Pro 内容
- Explore object tracking for visionOS — visionOS 上的物体追踪,结合 Object Capture 模型使用
评论
GitHub Issues · utterances