Gaussian splats on visionOS
At a glance
| Item | Summary |
|---|---|
| Purpose | Use the new Gaussian splat APIs available in RealityKit in visionOS 27. |
| App architecture | GaussianSplatsOnVisionOSApp composes WindowGroup + ImmersiveSpace around ContentView; AppModel coordinates scene-reconstruction updates while a dedicated coordinator/renderer owns Gaussian-splat resources. |
| Main patterns | SwiftUI scene composition, SwiftUI–RealityKit bridge, Explicit immersive-space lifecycle, Observable state owner, Provider session boundary, Low-level render-buffer builder |
| Project style | Code-rich sample with 9 scanned Swift file(s) and 1151 Swift line(s); resources and generated assets are excluded from those counts. |
Project structure
Source bundle/
└── GaussianSplatsOnVisionOS/
├── GaussianSplatsOnVisionOSApp.swift # GaussianSplatsOnVisionOSApp
├── AppModel.swift # AppModel, ImmersiveSpaceState, LoadedAsset
├── SplatView.swift # SplatViewCoordinator, SplatView, SnapOffset
├── SplatEntityBuilder.swift # GaussianSplatBuffers, GaussianSplatError
├── ContentView.swift # ContentView
├── SceneReconstructionManager.swift # SceneReconstructionManager
├── PLYParser.swift # PLYProperty, GaussianSplatData, PLYHeader
└── USDLoader.swift # SplatAttributes
Structure observations
- The runtime boundary is WindowGroup + ImmersiveSpace; the pruned tree lists only files that explain lifecycle, state, or framework integration.
- App code is split into role-named views, models, managers, providers, components, or systems.
Overall architecture
flowchart LR
GaussianSplatsOnVisionOSApp_1["GaussianSplatsOnVisionOSApp"]
WindowGroup___ImmersiveSpace_2["WindowGroup + ImmersiveSpace"]
ContentView_3["ContentView"]
AppModel_4["AppModel"]
RealityView_entity_graph_5["RealityView entity graph"]
ARKit_mesh_updates___Gaussian_splat_renderer_6["ARKit mesh updates + Gaussian-splat renderer"]
GaussianSplatsOnVisionOSApp_1 --> WindowGroup___ImmersiveSpace_2
WindowGroup___ImmersiveSpace_2 --> ContentView_3
ContentView_3 --> AppModel_4
AppModel_4 --> RealityView_entity_graph_5
RealityView_entity_graph_5 --> ARKit_mesh_updates___Gaussian_splat_renderer_6
Reference code
GaussianSplatsOnVisionOS/GaussianSplatsOnVisionOSApp.swift:11 — the app or executable entry declares the outer scene lifecycle.
struct GaussianSplatsOnVisionOSApp: App {
// ...
}The diagram is a responsibility flow, not a claim that every adjacent node directly calls the next. It keeps scene ownership, shared state, RealityKit content, and framework-provider work at separate levels.
Ownership and state
classDiagram
GaussianSplatsOnVisionOSApp *-- AppModel : appModel
ContentView o-- AppModel : appModel
SceneReconstructionManager *-- ARKitSession : session
SplatView *-- SplatViewCoordinator : coordinator
Ownership evidence
GaussianSplatsOnVisionOS/GaussianSplatsOnVisionOSApp.swift:12 — representative stored state or the nearest verified lifecycle anchor.
@State private var appModel = AppModel()| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
GaussianSplatsOnVisionOSApp |
AppModel as appModel |
creates and retains | Only the declaring scope writes |
ContentView |
AppModel as appModel |
receives a shared/non-owning reference | The upstream owner controls lifetime; this scope may invoke its mutable API |
SceneReconstructionManager |
ARKitSession as session |
creates and retains | Only the declaring scope writes |
SplatView |
SplatViewCoordinator as coordinator |
creates and retains | Only the declaring scope writes |
Ownership here is deliberately narrow: @Environment and weak references are shared links, initialized @State or stored services are lifecycle ownership, and a RealityView content closure owns additions to its entity graph without making the SwiftUI view a reference-type owner.
Class and protocol design
| Type | Responsibility | Depends on or conforms to |
|---|---|---|
GaussianSplatsOnVisionOSApp (GaussianSplatsOnVisionOS/GaussianSplatsOnVisionOSApp.swift:11) |
Declares app scenes and top-level dependency lifetime. | App |
ContentView (GaussianSplatsOnVisionOS/ContentView.swift:10) |
Presents UI and forwards gestures or lifecycle events. | View |
AppModel (GaussianSplatsOnVisionOS/AppModel.swift:13) |
Owns observable feature state and domain transitions. | Concrete framework collaborators |
SplatViewCoordinator (GaussianSplatsOnVisionOS/SplatView.swift:34) |
Coordinates long-lived framework or cross-view work. | Concrete framework collaborators |
SceneReconstructionManager (GaussianSplatsOnVisionOS/SceneReconstructionManager.swift:24) |
Coordinates long-lived framework or cross-view work. | Concrete framework collaborators |
SplatView (GaussianSplatsOnVisionOS/SplatView.swift:75) |
Presents UI and forwards gestures or lifecycle events. | View |
The source defines no local substitution protocol in the reviewed boundary. Its protocol use is framework-facing (App, View, RealityKit/ARKit protocols, or platform adapters), so this document does not label the whole app protocol-oriented.
Access control
| Symbol | Access | Verified effect | Likely rationale |
|---|---|---|---|
@Environment(AppModel.self) private var appModel (GaussianSplatsOnVisionOS/ContentView.swift:11) |
private |
Use is restricted to the declaration and same-file extensions permitted by Swift. | Inference: Hide implementation details and lifecycle-sensitive state. |
No reviewed declaration uses fileprivate, private(set), public, open; unmodified Swift declarations are internal.
Reference code
GaussianSplatsOnVisionOS/ContentView.swift:11 — representative visibility boundary.
@Environment(AppModel.self) private var appModelLogic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Scene declaration and dependency lifetime | GaussianSplatsOnVisionOSApp |
The App/entry boundary determines window, volume, and immersive-space lifetime. |
| Presentation, attachments, and gestures | ContentView |
SwiftUI view code forwards user intent and RealityView lifecycle events. |
| Shared feature state and commands | AppModel |
A role-named owner prevents sibling views from duplicating transitions. |
| Tracking authorization and update streams | GaussianSplatsOnVisionOS/SceneReconstructionManager.swift:32 |
Provider lifetime and async updates remain outside render-only view code. |
Design patterns
| Pattern | Source evidence | Purpose or tradeoff |
|---|---|---|
| SwiftUI scene composition | GaussianSplatsOnVisionOS/GaussianSplatsOnVisionOSApp.swift:11 |
Keeps windows, volumes, and immersive-space lifecycle visible at the app boundary. |
| SwiftUI–RealityKit bridge | GaussianSplatsOnVisionOS/SplatView.swift:88 |
Builds and updates a RealityKit entity graph from SwiftUI lifecycle closures. |
| Explicit immersive-space lifecycle | GaussianSplatsOnVisionOS/GaussianSplatsOnVisionOSApp.swift:21 |
Makes immersive presentation a scene transition rather than hidden global state. |
| Observable state owner | GaussianSplatsOnVisionOS/AppModel.swift:13 |
Shares feature state across multiple views without moving framework resources into view values. |
| Provider session boundary | GaussianSplatsOnVisionOS/SceneReconstructionManager.swift:32 |
Owns provider lifetime separately from the SwiftUI view tree. |
| Low-level render-buffer builder | GaussianSplatsOnVisionOS/SplatEntityBuilder.swift:17 |
Parses asset fields into GPU-oriented buffers before the coordinator installs the splat entity. |
Naming conventions
- Role suffixes are evidence, not decoration: App:
GaussianSplatsOnVisionOSApp; Model:AppModel; Coordinator:SplatViewCoordinator; Manager:SceneReconstructionManager. - Protocols: no app-defined protocol in the reviewed source.
- Commands use verb-led methods:
configureSpotLight,syncSplat,loadAsset,configureManipulableObject,snapToNearestSurface,makeSplatEntity,makeDescriptor,makeSHDescriptor. - Files generally match their primary type;
Views,Models,Managers,Providers,Components,Systems, andPackagesfolders describe architectural roles where present.
Architecture takeaways
- Treat
GaussianSplatsOnVisionOSAppas the owner of scene declarations, not as the owner of every RealityKit entity created later. - Keep view-local interaction in SwiftUI, but move provider sessions, playback resources, shared game state, or transport state into a stable owner when their lifetime exceeds one render pass.
- Run ARKit providers for the scene lifetime and consume their asynchronous updates in cancellable tasks; map anchors to entities at the boundary.
- Model immersive-space open, transition, and close states explicitly so windows and immersive content cannot drift apart.
Source map
| Source file | Relevant symbols |
|---|---|
GaussianSplatsOnVisionOS/GaussianSplatsOnVisionOSApp.swift:11 |
GaussianSplatsOnVisionOSApp |
GaussianSplatsOnVisionOS/AppModel.swift:13 |
AppModel, ImmersiveSpaceState, LoadedAsset |
GaussianSplatsOnVisionOS/SplatView.swift:34 |
SplatViewCoordinator, SplatView, SnapOffset |
GaussianSplatsOnVisionOS/SplatEntityBuilder.swift:21 |
GaussianSplatBuffers, GaussianSplatError |
GaussianSplatsOnVisionOS/ContentView.swift:10 |
ContentView |
GaussianSplatsOnVisionOS/SceneReconstructionManager.swift:24 |
SceneReconstructionManager |
GaussianSplatsOnVisionOS/PLYParser.swift:34 |
PLYProperty, GaussianSplatData, PLYHeader, ElementInfo |
GaussianSplatsOnVisionOS/USDLoader.swift:58 |
SplatAttributes |