WWDC Quick Look 💓 By SwiftGGTeam
Collaborate on structured 3D models in visionOS

Collaborate on structured 3D models in visionOS

观看原视频

Highlight

visionOS 27 的 RealityKit 新增了 ClippingComponent 和层级化 ManipulationComponent,开发者无需手写 Shader 或物理引擎,就能在 Apple Vision Pro 上实现 3D 模型的拆解、剖切和自动爆炸图交互。

核心内容

从”只能看”到”可以拆”

以前在 visionOS 里展示一个复杂的 3D 模型,比如发动机或建筑 BIM,用户只能绕着它转圈看。想拆开外壳看看里面的零件?开发者得自己写射线检测、算碰撞体、处理手势冲突。想切个剖面展示内部结构?得自己写 Shader 或者用 CSG(构造实体几何)去减模型。这些工业软件里标配的交互,在 spatial computing 里一直是空白。

Apple 这次直接把这套能力做进了 RealityKit。核心思路就一句话:组件在 Entity 树里的位置,决定用户能操控什么。

05:22)演示里,一个 AirPods Pro 模型原本是个整体。点击”拆解”后,外壳、耳机、主板突然变成独立可抓取的零件。一个人可以把主板拿起来端详,另一个人同时旋转耳机观察接口。所有人在同一个 SharePlay 空间里看到完全一致的模型状态。

剖切:让内部结构像剥洋葱一样可见

复杂模型的内部结构一直是个难题。建筑里的管线、设备里的主板、发动机里的活塞 —— 这些东西被外壳包着,2D 屏幕上看不到,3D 空间里也够不着。

08:16ClippingComponent 解决了这个问题。它用一个轴对齐包围盒(AABB)定义保留区域,包围盒外的几何体每帧都被渲染器丢弃。六个面可以变成可拖拽的交互平面,用户伸手一拉,剖切面就移动,内部结构层层展开。

这不是简单的”一刀切”。它有三档状态:.off(不剖切)、.on(按当前包围盒剖切)、.editing(显示六个交互平面,让用户调整剖切范围)。

自动爆炸图:代码自己决定怎么拆

拆解模型时,沿哪个轴展开效果最好?沿 X 轴会把零件挤成一团,沿 Y 轴可能更自然。这个判断以前靠开发者硬编码,现在 RealityKit 用数学帮你算。

18:16)算法叫”体积加权位置方差”(volume-weighted position variance)。每个子零件的位置和体积作为输入,计算三个轴向上的加权方差,方差最大的轴就是最佳展开方向。大零件离得远、体积大,对方向选择的权重就高。结果比拍脑袋硬编码靠谱得多。

详细内容

资产准备:层级结构是一切的前提

02:57)没有层级结构的 3D 模型,代码根本没法决定隐藏什么、操控什么。演示里对比了两个发动机模型:一个导出时把所有网格压平到根节点,零件名字变成 InteriorPart_01InteriorPart_47,代码找不到目标;另一个保留了深层嵌套的层级,每个活塞、每根曲轴都是独立命名的节点,代码可以直接定位。

美术导出 USDZ 时必须保留层级。这是后续所有交互的基础。

拆解与组装:移动组件位置即可

07:09ManipulationComponentInputTargetComponent 挂在哪个节点上,用户就能操控哪个节点。

拆解时,把这两个组件从根节点移除,遍历子节点给每个零件挂上:

func openAssembly() {
    components[ManipulationComponent.self] = nil
    components[InputTargetComponent.self] = nil

    for child in assemblyChildren {
        child.components.set(InputTargetComponent())

        var manipulation = ManipulationComponent()
        manipulation.releaseBehavior = .stay
        child.manipulationComponent = manipulation
    }
}

组装时反向操作,把子节点的组件清掉,重新挂回根节点:

func closeAssembly() {
    for child in assemblyChildren {
        child.manipulationComponent = nil
        child.components[InputTargetComponent.self] = nil
    }

    components.set(InputTargetComponent())
    var manipulation = ManipulationComponent()
    manipulation.releaseBehavior = .stay
    manipulationComponent = manipulation
}

关键点:

  • releaseBehavior = .stay 让零件松手后停在原地,不会弹回原位
  • InputTargetComponent 让实体能接收手势事件,前提是已添加 CollisionComponent
  • 没有额外的状态标志位,没有复杂的动画状态机,改组件位置即改行为

剖切:四坐标系转换与向量投影

09:12ClippingComponent 的核心属性是 bounds,一个实体局部坐标系下的 AABB。超出这个范围的几何体每帧被丢弃。

var clipping = ClippingComponent()
clipping.bounds = bounds
clipping.shouldClipChildren = true
clipping.shouldClipSelf = true
entity.components.set(clipping)

关键点:

  • bounds 必须在实体局部坐标系(local space)下定义
  • shouldClipChildren 默认 false,子节点默认不被剖切,必须显式设为 true
  • shouldClipSelf 默认 true,控制实体自身几何体是否被裁剪

11:12)剖切的难点在于坐标系转换。用户拖拽剖切面的手势发生在 Clipping Plane 坐标系,但 ClippingComponentbounds 更新需要在 Model 坐标系下进行。整个链路涉及四个坐标系:

  1. World:世界坐标系,一切的基础
  2. Model:模型坐标系,ClippingComponent 操作的空间
  3. Clipping Control:放置六个交互平面的空间
  4. Clipping Plane:手势事件表达的空间

转换链路:手势 delta(Clipping Plane)→ World → Model → 约束到法线方向 → 更新 bounds。同时,约束后的 delta 还要转回 Clipping Plane 坐标系,更新交互平面的位置。

15:44)约束用到向量投影:把拖拽 delta 投影到剖切面法线方向(如 +x 轴的 {1, 0, 0}),只保留该方向上的分量。这保证了用户斜着拖拽时,剖切面只沿法线移动,手感自然。

投影的数学:先求方向向量的单位向量,再与拖拽 delta 做点积得到标量长度,最后乘以方向向量得到约束后的向量。

自动爆炸图:体积加权方差选轴

19:46)展开方向的选择基于统计学中的方差概念。方差衡量一组值偏离平均值的程度 —— 方差大表示值分散,方差小表示值集中。

加权方差给每个值赋予一个权重。这里用每个子零件的体积作为权重,计算三个轴向上的”体积加权位置方差”:

weighted_variance = sum(weight * (position - average)^2) / count

方差最大的轴被选为展开方向。大零件离平均位置远,体积又大,对方向选择的拉动作用就强。AirPods Pro 的演示中,Y 轴方差最大,因为外壳和耳机在 Y 方向上分布最开,且体积大、权重高。

23:35)确定方向后,用 FromToBy 动画把子零件沿该轴移动到展开位置。

核心启发

1. 工业设计评审 App

做什么:做一个让工程师团队在 Apple Vision Pro 里共同审查机械零件的 App。

为什么值得做:ManipulationComponent 的层级传递让”整体查看 → 拆解零件 → 单独讨论 → 组装回去”的流程零代码实现。SharePlay 保证远程团队看到同一状态。

怎么开始:准备一个带层级结构的 USDZ 模型,给根节点挂 ManipulationComponent,写两个按钮调用 openAssembly()closeAssembly()

2. 建筑 BIM 剖切查看器

做什么:让建筑师和业主在 visionOS 里走进一栋虚拟建筑,实时剖切墙体查看管线和结构。

为什么值得做:ClippingComponent.editing 状态让非技术用户也能直观调整剖切面。六个彩色平面就是交互手柄,学习成本接近零。

怎么开始:给建筑模型添加 ClippingComponent,设置初始 bounds 为模型全尺寸,进入 .editing 状态让用户拖拽六个剖切面。

3. 医疗设备 3D 教学工具

做什么:医学院或设备厂商用来展示人体器官或医疗器械内部结构的教学 App。

为什么值得做:自动爆炸图算法让复杂模型的拆解方向总是最自然的,不需要为每个模型手动调参。体积加权保证心脏、肺叶等大器官主导展开方向。

怎么开始:加载 USDZ 模型后,计算每个子零件的体积和位置,跑体积加权方差算法选轴,然后用 FromToBy 动画展开。

4. 电商产品拆解展示

做什么:让用户在 visionOS 里”拆开”想买的电子产品,看看内部做工和零件布局。

为什么值得做:以前这种交互只有厂商宣传视频能做到,现在用户自己用手就能拆。releaseBehavior = .stay 让零件悬停在半空,用户可以 360 度端详。

怎么开始:用带层级结构的 USDZ 模型,拆解时给每个零件挂 ManipulationComponentCollisionComponent

5. 城市基础设施可视化

做什么:展示地下管网、地铁隧道、电缆布局的城市规划工具。

为什么值得做:剖切 + 爆炸图的组合,让埋在地面下的复杂基础设施第一次以直观的方式呈现。地面以上正常显示,地面以下用剖切面切掉土层直接暴露管线。

怎么开始:把地面和地下设施分层建模,用 ClippingComponent 切掉地面层,地下部分用自动爆炸图展开。

关联 Session

评论

GitHub Issues · utterances