WWDC Quick Look 💓 By SwiftGGTeam
Discover USDKit and what's new in OpenUSD

Discover USDKit and what's new in OpenUSD

Watch original video

Highlight

Apple introduces the USDKit framework, giving Swift developers native APIs to create, edit, and export USD scenes, process 3D content directly in the Mac Preview app, and embed 3D models natively on the web through Safari’s new <model> tag.

Core Ideas

Handling 3D scenes used to be painful

If you have built 3D content on Apple platforms, you have probably hit this problem: USD, or Universal Scene Description, is the de facto industry standard, but the official API is C++. Swift developers either write bridging code or depend on community-maintained SwiftUSD bindings. Scene assembly, hierarchy traversal, and property editing all require dealing with C++ types such as SdfPath and UsdPrim.

Collaboration is even harder. Artists export models from Blender or Maya, developers manually stitch them together in code, and both sides maintain separate scene descriptions. When an artist updates a model position, the developer has to hard-code coordinates again. Without a unified Scene Graph management mechanism, larger projects become harder and harder to maintain.

USDKit makes USD a first-class Swift citizen

USDKit is Apple’s new system framework this year, wrapping core USD concepts in APIs that feel natural in Swift (08:12). You can create scenes, traverse hierarchies, edit properties, and export assets entirely with native Swift syntax.

The design is clear: people who know USD will recognize the concepts, and people who know Swift do not need to learn C++ first. USDStage maps to the stage, USDPrim maps to a scene node, and references.add() creates lightweight references. These API names map directly to USD’s core concepts, so the learning curve is low.

The 3D workflow extends from Mac to Vision Pro

The Preview app in macOS 27 is no longer just an image viewer (04:24). It can directly edit 3D scenes: drag objects, adjust properties, modify lighting, and convert or compress assets. Behind the scenes there are three renderer choices: RealityKit for cross-platform consistency, Storm for existing production pipelines, and the new Raytracer for physically correct ray-traced results.

Through the Spatial Preview framework, changes on the Mac can synchronize in real time to Quick Look on Vision Pro (05:42). Teams can use SharePlay to enter the same spatial scene and walk around while evaluating lighting and composition. This workflow used to require professional DCC software and complicated export steps. Now a single Mac can handle it.

Safari supports 3D content natively

Safari adds a <model> tag that embeds a 3D model the same way you embed an image (06:25). On macOS and iOS, users can inspect the model interactively in the browser. On visionOS, the model can even break out of the web page and enter the user’s space. For commerce showcases, product configurators, education content, and similar experiences, you no longer need Three.js or Babylon.js. One line of HTML can be enough.

Details

Opening and traversing a USD Stage

The entry point to USDKit is USDStage (08:12). You can create an empty in-memory stage or open one from a file on disk.

import USDKit

// Create a new empty in-memory stage
let stage = USDStage()

// Open a stage from a disk file
let url = URL(fileURLWithPath: "/ALab/entry.usda")
let stage = try USDStage.open(url)

Key points:

  • USDStage() creates an empty in-memory stage, which is useful for programmatic scene generation.
  • USDStage.open(url) loads from a .usda, .usdc, or .usdz file. It performs file IO, so it requires try.
  • After loading succeeds, the scene is ready immediately; no additional asynchronous callback is required.

Traverse the scene hierarchy to find a specific node (08:44):

// Traverse all descendant nodes and find the instrument named scope
for prim in stage.descendants {
    if prim.name == "scope" {
        // Found it
    }
}

// If it was not found, define a new Xform node at the specified path
let scope = stage.definePrim(at: "/World/scope", type: "Xform")

// Add a file reference without copying data
try scope.references.add("/ALab/assets/scope.usda")

Key points:

  • stage.descendants provides lazy traversal and visits all descendant nodes in depth-first order.
  • definePrim(at:type:) creates a node at a specified path, which is the unique identifier in USD.
  • references.add() is a core USD Composition mechanism: it references an external file without embedding the data. When upstream files change, reloading the stage picks them up automatically.

Moving objects with Transform Operations

USDKit wraps USD transform operations in Swift-friendly APIs (09:36):

// Create a translate transform operation and automatically update xformOpOrder
scope.addTransformOperation(type: .translate)

// Set the translation value
scope["xformOp:translate", as: USDValue.Vec3d.self] = [2.5, 0.0, -1.0]

Key points:

  • addTransformOperation(type:) automatically creates the xformOp:translate property and maintains xformOpOrder, so developers do not manage transform order manually.
  • Subscript syntax scope[key, as: Type.self] is USDKit’s unified way to read and write properties. It is type-safe and feels natural in Swift.
  • USDValue.Vec3d maps to a three-dimensional double-precision vector, suitable for scene-level coordinates.

Adding accessibility information to 3D objects

Apple is pushing standardized accessibility metadata down into USD so VoiceOver users can understand objects in 3D scenes (10:42):

// Apply the AccessibilityAPI schema with the instance name "default"
try scope.applyAPISchema("AccessibilityAPI", instanceName: "default")

// Create label and description attributes
scope.makeAttribute(named: "accessibility:default:label", as: .string)
scope.makeAttribute(named: "accessibility:default:description", as: .string)

// Set attribute values
scope["accessibility:default:label", as: String.self] = "Oscilloscope"
scope["accessibility:default:description", as: String.self] =
    "Vintage signal analyzer with a 3D wireframe display, topped by a color bar test monitor"

Key points:

  • applyAPISchema(_:instanceName:) attaches a schema to the node, declaring that it supports the accessibility API.
  • Attribute names follow the accessibility:{instanceName}:{property} convention. Here that becomes accessibility:default:label.
  • makeAttribute(named:as:) creates an attribute, and as: .string specifies the attribute type.
  • The label should be concise, while the description should be richer. Together they let assistive technologies accurately describe the object.
  • Apple already supports this standard directly in Blender and Maya, so artists can write accessibility data during modeling.

Exporting compressed USDZ

Production USD scenes can easily reach several gigabytes, so USDKit includes mesh and texture compression (12:05):

let output = URL(fileURLWithPath: "/ALab/alab_compressed.usdz")

// Export as a USDZ package
try stage.exportPackage(
    to: output,
    options: [
        .preferSmallTextureFiles(quality: .standard),   // AVIF texture compression
        .preferSmallMeshFiles                           // Mesh geometry compression
    ]
)

Key points:

  • exportPackage(to:options:) exports the stage as .usdz, the recommended package format on Apple platforms.
  • .preferSmallTextureFiles(quality:) compresses textures with AVIF. .standard balances file size and image quality.
  • .preferSmallMeshFiles enables mesh compression. With the new Alliance for Open Media encoding, mesh size can be reduced by up to 90%.
  • Together, these options reduce average asset size to about one seventh of the original.
  • If you do not want to write code, the Mac Preview app and the usdcrush command-line tool can perform the same compression.

Key Takeaways

1. Build a real-time collaborative 3D asset review tool

Load scenes with USDKit and send them to Vision Pro through the Spatial Preview framework. Team members can wear headsets, walk through the same space, and use SharePlay to synchronize viewpoints. The entry APIs are USDStage.open() and Spatial Preview’s real-time synchronization mechanism.

2. Add native 3D product displays to commerce apps

Use USDKit to assemble product variants such as colors and accessory combinations, export compressed USDZ, and embed it on the web with the <model> tag. visionOS users can pull the product into physical space for inspection. The core APIs are exportPackage(options:) and Safari’s <model> tag.

3. Add accessibility support to existing 3D content in bulk

Traverse every USDPrim in a scene, infer label and description from node names or types, and write them with the AccessibilityAPI schema. This lets VoiceOver users explore your 3D content. Start with stage.descendants and applyAPISchema(_:instanceName:).

4. Build a lightweight USD scene editor

Use USDKit’s definePrim, references.add, and addTransformOperation to build a node editor that lets users drag in 3D assets, compose them, adjust positions, and export compressed packages. It is lighter than Blender and more flexible than pure code.

5. Mix Gaussian Splats with traditional models

OpenUSD adds Particle Fields as a foundation type this year, enabling Gaussian Splats. Use USDKit to create a scene that contains both traditional meshes and particle fields, then render it in RealityKit. This is useful for applications that combine real-world scans with virtual objects.

  • Spatial Preview - Learn how to integrate the Spatial Preview framework into Mac apps for real-time 3D preview from Mac to Vision Pro
  • RealityKit - USDKit integrates deeply with RealityKit; learn how to render scenes assembled with USDKit in RealityKit
  • Reality Composer Pro 3 - A visual 3D content creation tool that forms a code-plus-tools workflow alongside USDKit
  • Immersive Web - Deep technical details of Safari’s <model> tag and more possibilities for 3D content on the web
  • 3D Models - Learn best practices and optimization strategies for USD models on Apple platforms

Comments

GitHub Issues · utterances