Generating interactive geometry with RealityKit
At a glance
| Item | Summary |
|---|---|
| Purpose | Create an interactive mesh with low-level mesh and low-level texture. |
| App architecture | GeneratingInteractiveGeometrySampleApp presents a height-map view; a compute component carries dispatch state and ComputeSystem runs Metal work that updates interactive RealityKit geometry. |
| Main patterns | SwiftUI scene composition, UI–RealityKit bridge, Entity-component-system, Protocol capability boundary, Compute component-system pipeline |
| Project style | Code-rich sample with 23 scanned C/Objective-C header, Metal, Swift file(s) and 1438 implementation line(s). |
Project structure
Source bundle/
└── GeneratingInteractiveGeometry/
└── GeneratingInteractiveGeometry/
├── Compute/
│ └── ComputeSystem.swift # ComputeUpdateContext, ComputeSystem, ComputeSystemComponent
├── HeightMapMeshView.swift # HeightMapMeshView, Generator
├── GeneratingInteractiveGeometrySampleApp.swift # GeneratingInteractiveGeometrySampleApp
├── HeightMapMesh/
│ ├── HeightMapGenerator.swift # HeightMapGenerator
│ └── HeightMapMesh.swift # HeightMapComputeParams, HeightMapMesh
├── Sine Wave/
│ └── SineWaveHeightMapGenerator.swift # SineWaveHeightMapGenerator
└── Terrain/
└── TerrainHeightMapGenerator.swift # TerrainHeightMapGenerator
Structure observations
- The runtime boundary is WindowGroup + volumetric window; the tree is pruned to lifecycle, state, framework, rendering, and ECS files.
- The source is C/Objective-C header, Metal, Swift; role-named types and feature folders separate the major responsibilities.
Overall architecture
flowchart LR
GeneratingInteractiveGeometrySampleApp_1["GeneratingInteractiveGeometrySampleApp"]
WindowGroup___volumetric_window_2["WindowGroup + volumetric window"]
HeightMapMeshView_3["HeightMapMeshView"]
ComputeSystem_4["ComputeSystem"]
RealityKit_entity_graph_5["RealityKit entity graph"]
Metal_compute___RealityKit_geometry_6["Metal compute + RealityKit geometry"]
GeneratingInteractiveGeometrySampleApp_1 --> WindowGroup___volumetric_window_2
WindowGroup___volumetric_window_2 --> HeightMapMeshView_3
HeightMapMeshView_3 --> ComputeSystem_4
ComputeSystem_4 --> RealityKit_entity_graph_5
RealityKit_entity_graph_5 --> Metal_compute___RealityKit_geometry_6
Reference code
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/GeneratingInteractiveGeometrySampleApp.swift:11 — executable or app-lifecycle anchor.
struct GeneratingInteractiveGeometrySampleApp: App {
// ...
}The diagram is a responsibility flow, not a claim that every adjacent node directly calls the next. It separates lifecycle, presentation, stable state, framework/session work, and the RealityKit entity graph.
Ownership and state
classDiagram
HeightMapMeshView *-- Entity : sceneContainer
HeightMapMeshView --> HeightMapMeshEntity : heightMapMeshEntity
HeightMapMeshView *-- Entity : defaultPlaneContainer
HeightMapMeshView *-- SimpleMaterial : sineWaveMaterial
Ownership evidence
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMeshView.swift:18 — representative stored state or nearest verified lifecycle anchor.
private var sceneContainer: Entity = Entity()
/// The entity that contains the default plane mesh.
private let defaultPlaneContainer: Entity = Entity()
/// The height map mesh entity.
private let heightMapMeshEntity: HeightMapMeshEntity
private let sineWaveMaterial: SimpleMaterial = SimpleMaterial(color: #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1), roughness: 0.85, isMetallic: false)
private let terrainMaterial: SimpleMaterial = SimpleMaterial(color: #colorLiteral(red: 0.5058823824, green: 0.3372549117, blue: 0.06666667014, alpha: 1), roughness: 0.25, isMetallic: false)| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
HeightMapMeshView |
Entity as sceneContainer |
creates and retains | The declaring type controls writes |
HeightMapMeshView |
HeightMapMeshEntity as heightMapMeshEntity |
stores and coordinates | The declaring type controls writes |
HeightMapMeshView |
Entity as defaultPlaneContainer |
creates and retains | The declaring type controls writes |
HeightMapMeshView |
SimpleMaterial as sineWaveMaterial |
creates and retains | The declaring type controls writes |
Ownership is intentionally narrow: environment, bindings, observed objects, weak links, and delegate callbacks do not prove lifetime ownership. Initialized stored services and wrapper-managed state do; entities added inside a RealityKit content closure belong to that entity graph.
Class and protocol design
| Type | Responsibility | Depends on or conforms to |
|---|---|---|
GeneratingInteractiveGeometrySampleApp (GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/GeneratingInteractiveGeometrySampleApp.swift:11) |
Declares app lifecycle and top-level dependency lifetime. | App |
HeightMapMeshView (GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMeshView.swift:11) |
Presents UI and forwards gestures or lifecycle events. | View |
ComputeSystem (GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/Compute/ComputeSystem.swift:22) |
Declares a replaceable capability or collaboration contract. | Concrete framework collaborators |
HeightMapGenerator (GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMesh/HeightMapGenerator.swift:12) |
Declares a replaceable capability or collaboration contract. | Concrete framework collaborators |
ComputeSystemComponent (GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/Compute/ComputeSystem.swift:28) |
Stores RealityKit entity data. | Component |
ComputeDispatchSystem (GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/Compute/ComputeSystem.swift:33) |
Updates entities matching a RealityKit component query. | System |
HeightMapMesh (GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMesh/HeightMapMesh.swift:30) |
Updates entities matching a RealityKit component query. | ComputeSystem |
Verified protocol-oriented seams: HeightMapMesh → ComputeSystem, SineWaveHeightMapGenerator → HeightMapGenerator, TerrainHeightMapGenerator → HeightMapGenerator, WaterSurfaceHeightMapGenerator → HeightMapGenerator. Framework conformances remain adapters, not proof of an app-wide protocol architecture.
Access control
| Symbol | Access | Verified effect | Likely rationale |
|---|---|---|---|
private let deriveNormalsPipeline: MTLComputePipelineState = makeComput... (GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMesh/HeightMap.swift:16) |
private |
Use stays inside the declaration and same-file extensions permitted by Swift. | Inference: Hide lifecycle-sensitive state or an implementation step. |
No reviewed Swift access example uses fileprivate, private(set), public, open; declarations without a modifier are internal.
Objective-C/C header and implementation visibility is documented separately from Swift lexical access control.
Reference code
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMesh/HeightMap.swift:16 — representative visibility boundary.
@MainActor
struct HeightMap {
// ...
private let deriveNormalsPipeline: MTLComputePipelineState = makeComputePipeline(named: "deriveNormalsFromHeightMap")!
// ...
}Logic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Application/command lifecycle | GeneratingInteractiveGeometrySampleApp |
The executable boundary determines app, controller, scene, or command lifetime. |
| Presentation and user intent | HeightMapMeshView |
The view/controller forwards input and owns only presentation-local work. |
| Framework/session/render coordination | ComputeSystem |
The role-named collaborator isolates long-lived or per-frame work from presentation code. |
| Per-entity data and repeated behavior | GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/Compute/ComputeSystem.swift:33 |
Components carry data; the system queries and updates matching entities. |
| GPU and low-level resource work | GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMesh/HeightMapGenerator.swift:18 |
Buffer, texture, shader, or frame-resource mutation stays in a rendering/compute boundary. |
Design patterns
| Pattern | Source evidence | Purpose or tradeoff |
|---|---|---|
| SwiftUI scene composition | GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/GeneratingInteractiveGeometrySampleApp.swift:11 |
Keeps windows, volumes, and immersive presentation visible at the app boundary. |
| UI–RealityKit bridge | GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMeshView.swift:131 |
Builds or hosts the RealityKit entity graph from SwiftUI or a platform view/controller lifecycle. |
| Entity-component-system | GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/Compute/ComputeSystem.swift:33 |
Stores per-entity data in components and advances repeated behavior in registered systems. |
| Protocol capability boundary | GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMesh/HeightMapMesh.swift:30 |
Defines a local capability with concrete conformers; this is the verified protocol-oriented seam. |
| Compute component-system pipeline | GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/Compute/ComputeSystem.swift:11 |
Carries per-entity compute work as component data and dispatches Metal updates from a RealityKit system. |
Naming conventions
- Role suffixes are evidence, not decoration: App:
GeneratingInteractiveGeometrySampleApp; System:ComputeDispatchSystem,ComputeSystem; Component:ComputeSystemComponent; View:HeightMapMeshView. - ECS names pair data and behavior: components
ComputeSystemComponent; systemsComputeDispatchSystem,HeightMapMesh. - Protocols:
ComputeSystem,HeightMapGenerator. - Commands use verb-led methods:
update,setHeightMapGenerator,createScene,reset,generateHeightMap,updateVertices. - Files and folders use primary-type or responsibility names such as
Views,Models,Rendering,Components,Systems,Packages, or feature names where those boundaries exist.
Architecture takeaways
- Treat
GeneratingInteractiveGeometrySampleAppas the owner of executable or scene lifecycle, not automatically as the owner of every entity created later. - Keep view/controller input near presentation, but move sessions, reconstruction, capture, rendering, shared game state, or documents into stable owners when their lifetime exceeds one callback or render pass.
- Use components for per-entity data and systems for repeated simulation instead of centralizing every update in a view model or controller.
Source map
| Source file | Relevant symbols |
|---|---|
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/Compute/ComputeSystem.swift:12 |
ComputeUpdateContext, ComputeSystem, ComputeSystemComponent, ComputeDispatchSystem |
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMeshView.swift:11 |
HeightMapMeshView, Generator |
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/GeneratingInteractiveGeometrySampleApp.swift:11 |
GeneratingInteractiveGeometrySampleApp |
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMesh/HeightMapGenerator.swift:12 |
HeightMapGenerator |
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/HeightMapMesh/HeightMapMesh.swift:12 |
HeightMapComputeParams, HeightMapMesh |
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/Sine Wave/SineWaveHeightMapGenerator.swift:12 |
SineWaveHeightMapGenerator |
GeneratingInteractiveGeometry/GeneratingInteractiveGeometry/Terrain/TerrainHeightMapGenerator.swift:13 |
TerrainHeightMapGenerator |