Highlight
Apple 原型设计团队的 Praveen 和视频工程团队的 Kai 联合介绍了全新的 RoomPlan 框架。RoomPlan 使用 ARKit 和机器学习算法,在配备 LiDAR 的设备上扫描房间,自动检测墙壁、窗户、开口、门以及房间内的重要物体(壁炉、沙发、桌子、柜子等)。
核心内容
做室内设计、房产展示或家具预览时,开发者经常需要一份房间模型。以前,这通常意味着自己处理相机、深度数据、几何重建、物体识别和 3D 导出。每一步都需要专门的机器学习或计算机视觉能力。
RoomPlan 把这个流程收进一个框架里。它运行在配备 LiDAR 的 iPhone 或 iPad 上,用 ARKit 提供的空间理解能力和机器学习模型,生成房间的参数化 3D 模型。(01:01)
参数化是这场演讲的关键词。RoomPlan 的输出包含语义化结构,而非一团难以理解的网格。它会识别墙、门、窗、开口,以及沙发、桌子、床、柜子等房间定义对象,并把它们组织成 CapturedRoom 结构。(01:21)
Apple 提供了两层入口。(02:57)
第一层是 RoomCaptureView。它是开箱即用的扫描界面,负责实时轮廓线、底部 3D 预览和文字引导。适合想快速接入扫描体验的 App。
第二层是 RoomCaptureSession。它暴露实时参数化数据和用户指令。适合需要自定义 AR 界面、把扫描结果叠加到自家可视化系统里的 App。
详细内容
用 RoomCaptureView 快速接入扫描
(03:30)RoomCaptureView 是一个 UIView 子类。它处理世界空间中的扫描反馈、实时房间模型生成、coaching(引导)和用户提示。
接入扫描只需要保留一个 view 引用和一份 session 配置,然后启动或停止 capture session。(04:36)
import UIKit
import RoomPlan
class RoomCaptureViewController: UIViewController {
var roomCaptureView: RoomCaptureView
var captureSessionConfig: RoomCaptureSession.Configuration
private func startSession() {
roomCaptureView.captureSession.run(configuration: captureSessionConfig)
}
private func stopSession() {
roomCaptureView.captureSession.stop()
}
}
关键点:
import RoomPlan引入 RoomPlan 框架。RoomCaptureView承载 Apple 提供的扫描界面。RoomCaptureSession.Configuration保存本次扫描的配置。run(configuration:)开始扫描,并把配置传给内部 capture session。stop()结束扫描,之后框架可以进入处理和结果展示阶段。
这段代码背后的价值在于少写一整套扫描 UI。RoomCaptureView 会在扫描过程中显示检测到的墙、窗、门、开口和物体轮廓,还会用底部 3D 模型显示扫描进度。(04:01)
处理扫描结果并导出 USDZ
(05:00)如果 App 需要接管结果处理,可以实现 RoomCaptureViewDelegate。演讲展示了两个回调:一个决定是否展示后处理结果,一个拿到最终 CapturedRoom。
import UIKit
import RoomPlan
class RoomCaptureViewController: UIViewController {
func captureView(shouldPresent roomDataForProcessing: CapturedRoomData, error: Error?) -> Bool {
// Optionally opt out of post processed scan results.
return false
}
func captureView(didPresent processedResult: CapturedRoom, error: Error?) {
// Handle final, post processed results and optional error.
// Export processedResults
try? processedResult.export(to: destinationURL)
}
}
关键点:
CapturedRoomData是扫描得到、等待后处理的数据。captureView(shouldPresent:error:)返回false时,App 可以选择不展示框架提供的后处理结果界面。CapturedRoom是后处理后的参数化房间模型。export(to:)把结果导出到指定 URL,可用于 USDZ 工作流。- 代码中的
destinationURL需要由 App 自己准备,例如写入应用沙盒中的文件路径。
这一步让 RoomPlan 可以进入现有 3D 工具链。演讲后半段提到,导出的 USD 或 USDZ 可以在 Cinema 4D 这类工具中查看层级、尺寸和位置,也可以进入房产、电商、工具和室内设计应用的渲染流程。(12:12)
用 RoomCaptureSession 自定义扫描体验
(05:40)需要自定义视觉呈现时,可以直接使用 Data API。这个流程分为 scan、process、export 三步。
扫描阶段使用 RoomCaptureSession。它还提供底层 ARSession,让 App 可以在自己的 ARView 中绘制平面和物体边界框。(06:50)
import UIKit
import RealityKit
import RoomPlan
import ARKit
class ViewController: UIViewController {
@IBOutlet weak var arView: ARView!
var previewVisualizer: Visualizer!
lazy var captureSession: RoomCaptureSession = {
let captureSession = RoomCaptureSession()
arView.session = captureSession.arSession
return captureSession
}()
override func viewDidLoad() {
super.viewDidLoad()
captureSession.delegate = self
// set up previewVisualizer
}
}
关键点:
RealityKit提供ARView,用于承载自定义 AR 画面。RoomCaptureSession()创建底层扫描会话。captureSession.arSession暴露 RoomPlan 使用的 AR session。arView.session = captureSession.arSession让自定义 ARView 使用同一个 AR session。captureSession.delegate = self让当前控制器接收实时房间更新和扫描指令。
这里的核心区别是控制权。RoomCaptureView 给你完整界面;RoomCaptureSession 给你数据和事件。自定义 App 可以把 RoomPlan 的实时结果画成自己的品牌界面,也可以把它和已有 AR 内容放在同一个场景里。
接收实时房间模型和扫描指令
(07:40)RoomCaptureSessionDelegate 提供两类实时反馈:CapturedRoom 更新和 Instruction 指令。
extension ViewController: RoomCaptureSessionDelegate {
func captureSession(_ session: RoomCaptureSession,
didUpdate room: CapturedRoom) {
previewVisualizer.update(model: room)
}
func captureSession(_ session: RoomCaptureSession,
didProvide instruction: Instruction) {
previewVisualizer.provide(instruction)
}
}
关键点:
didUpdate room:在检测到房间变化时调用。CapturedRoom是实时的参数化房间数据,可用于更新预览模型。previewVisualizer.update(model:)代表 App 自己的可视化逻辑。didProvide instruction:在扫描过程中提供用户引导。Instruction覆盖距离、扫描速度、光照调整,以及需要关注的纹理区域。
指令很重要。RoomPlan 的扫描质量和人的移动方式、距离、速度、光线有关。框架把这些反馈暴露出来,开发者可以把它们变成 UI 文案、图标或语音提示。(08:33)
用 RoomBuilder 生成最终模型
(09:04)扫描结束后,RoomBuilder 负责处理 CapturedRoomData,生成最终 CapturedRoom。演讲示例使用了 .beautifyObjects 选项。
import UIKit
import RealityKit
import RoomPlan
import ARKit
class ViewController: UIViewController {
@IBOutlet weak var arView: ARView!
var previewVisualizer: Visualizer!
// set up RoomBuilder
var roomBuilder = RoomBuilder(options: [.beautifyObjects])
}
关键点:
RoomBuilder是扫描数据后处理入口。options: [.beautifyObjects]使用 RoomPlan 提供的对象美化选项。RoomBuilder通常和RoomCaptureSession配合使用。previewVisualizer继续负责展示处理后的最终模型。
当 RoomCaptureSession 停止或发生错误时,delegate 会收到 CapturedRoomData 和可选错误。随后可以用 Swift concurrency 异步生成最终房间模型。(09:30)
extension ViewController: RoomCaptureSessionDelegate {
func captureSession(_ session: RoomCaptureSession,
didEndWith data: CapturedRoomData, error: Error?) {
if let error = error {
print("Error: \(error)")
}
Task {
let finalRoom = try! await roomBuilder.capturedRoom(from: data)
previewVisualizer.update(model: finalRoom)
}
}
}
关键点:
didEndWith data:在扫描停止或出错时触发。CapturedRoomData保存传感器扫描数据,供后处理使用。Task创建异步上下文。await roomBuilder.capturedRoom(from: data)异步处理扫描数据。finalRoom是最终CapturedRoom,可用于展示、分析或导出。
演讲中说明,这个处理过程通常只需要几秒钟。它使用 Swift async/await,因此不会把后处理写成阻塞 UI 的同步流程。(09:45)
理解 CapturedRoom 的结构
(10:17)RoomPlan 的输出是参数化结构。顶层 CapturedRoom 由 Surface 和 Object 组成。
public struct CapturedRoom: Codable, Sendable {
public let walls: [Surface]
public let doors: [Surface]
public let windows: [Surface]
public let openings: [Surface]
public let objects: [Object]
public func export(to url: URL) throws
// Surface definitions ...
// Object definitions ...
}
关键点:
CapturedRoom遵循Codable,方便编码和持久化。Sendable表示它可以安全地跨并发边界传递。walls、doors、windows、openings都是Surface数组。objects保存房间内的 3D 对象,演讲中描述为 cuboids(长方体)。export(to:)把参数化结果导出为 USD 或 USDZ 数据。
Surface 包含墙、门、窗、开口等建筑元素。演讲提到它有曲面相关属性,例如半径、起止角度和四条边;还有尺寸、置信度、3D transform matrix 和唯一标识符。(10:26)
Object 表示家具类别,例如 table、bed、sofa。它也带有尺寸、置信度、3D transform matrix 和唯一标识符。(10:49)
扫描条件会影响结果
(13:09)RoomPlan 最适合单个住宅房间。演讲给出的房间上限是 30 英尺乘 30 英尺,约 9 米乘 9 米。
光线也会影响扫描。Apple 建议至少 50 lux,这相当于家庭客厅夜晚的典型亮度。硬件方面,RoomPlan 支持所有配备 LiDAR 的 iPhone 和 iPad Pro 机型。(13:38)
有些环境会带来挑战:全高镜子、玻璃、高天花板和很暗的表面。原因分别来自 LiDAR 预期输出、LiDAR 扫描距离和视频流质量。(14:02)
扫描前也可以准备房间。打开窗帘能增加自然光并减少窗户遮挡;关门能减少扫描到房间外区域的概率。高精度场景应该把这些准备步骤放进扫描前提示里。(14:27)
最后是电量和散热。Apple 建议避免重复扫描,或超过 5 分钟的单次长扫描。长时间扫描会造成疲劳、耗电和热问题,进而影响 App 体验。(15:16)
核心启发
-
做什么:给室内设计 App 增加自动房间建模入口。 为什么值得做:RoomPlan 会识别墙、窗、门、开口和主要家具,设计工具可以直接基于
CapturedRoom做墙面改色、面积估算和布局预览。 怎么开始:先用RoomCaptureView完成扫描闭环,再在captureView(didPresent:error:)中读取CapturedRoom。 -
做什么:为房产经纪工具生成房间 3D 模型和 USDZ 文件。 为什么值得做:演讲明确提到 real estate apps 可以让经纪人捕获 listing 的 floor plans 和 3D models。 怎么开始:扫描结束后调用
CapturedRoom.export(to:),把结果保存到 App 文件目录,再上传到业务后台或本地预览。 -
做什么:做一个自定义扫描引导界面。 为什么值得做:
Instruction会给出距离、速度、光照和纹理区域反馈,App 可以把它转成更贴合产品语气的引导。 怎么开始:使用RoomCaptureSessionDelegate,在didProvide instruction:中更新自己的提示组件。 -
做什么:把电商家具预览和真实房间结构结合起来。 为什么值得做:RoomPlan 输出的墙面、开口和家具位置能给商品摆放提供空间上下文。 怎么开始:用
RoomCaptureSession获取实时CapturedRoom,在 RealityKit 场景里把商品模型放入扫描得到的房间结构中。 -
做什么:为高精度扫描设计房间准备流程。 为什么值得做:演讲给出了光照、镜子、玻璃、门和扫描时长等限制。提前引导能减少失败扫描。 怎么开始:在启动
run(configuration:)前加入检查清单:打开窗帘、关闭房门、提示避开镜面和玻璃、提醒单次扫描控制在 5 分钟内。
关联 Session
- Discover ARKit 6 — ARKit 6 增强相机、追踪和平面能力,补充 RoomPlan 背后的 AR 基础。
- Bring your world into augmented reality — Object Capture 与 RealityKit 展示另一条把现实物体带入 AR 的路径。
- Understand USD fundamentals — RoomPlan 可以导出 USD 或 USDZ,这场演讲解释 USD 的基础概念和内容管线。
- Qualities of great AR experiences — RoomPlan 的扫描体验需要清晰引导和环境反馈,这场演讲补充 AR 设计原则。
评论
GitHub Issues · utterances