Hi @tomires
It was great connecting with you on Wednesday.
If I understand correctly, you want to transition from mixed immersion to full immersion while maintaining the real-world position of an AR anchor.
This is possible. Here's how.
- Instead of closing the old space then opening the new one, conditionally render views in a single immersive space. The former changes the scene's origin and the latter does not.
- Use a state variable to change the immersion style of the current immersive space.
Here's a code snippet. To create and run the app, create a new project then replace the generated code with the snippets below.
AppModel.swift
// Define an enum with entries for each immersive scene.
enum Scenes : String, CaseIterable, Identifiable {
case red
case green
var id: Self { self }
}
//...
class AppModel {
// Add a variable to store the current scene.
var currentScene = Scenes.red
}
<YourAppName>App.swift
//...
// Set the immersion style based on the current scene.
let immersionStyle:ImmersionStyle = appModel.currentScene == .red ? .mixed : .full
ImmersiveSpace(id: appModel.immersiveSpaceID) {
ImmersiveView()
//...
}
.immersionStyle(selection: .constant(immersionStyle), in: .mixed, .full)
ContentView.swift
// Display a picker to transition between scenes.
struct ContentView: View {
@Environment(AppModel.self) private var appModel
var body: some View {
@Bindable var appModel = appModel
VStack {
Picker("Scene", selection: $appModel.currentScene) {
ForEach(Scenes.allCases) {
Text($0.rawValue)
}
}
ToggleImmersiveSpaceButton()
}
.padding()
}
}
ImmersiveView.swift
struct ImmersiveView: View {
@Environment(AppModel.self) private var appModel
@State private var session = ARKitSession()
@State private var anchorTransform:Transform?
var body: some View {
@Bindable var appModel = appModel
VStack {
// Render the view for the current scene and pass it the anchor's transform.
if let anchorTransform {
switch appModel.currentScene {
case .red:
RedView(anchorTransform: anchorTransform)
case .green:
GreenView(anchorTransform: anchorTransform)
}
}
}
.task {
guard ImageTrackingProvider.isSupported else {
print("Image tracking is not supported.")
return
}
let referenceImages = ReferenceImage.loadReferenceImages(inGroupNamed: "AR Resources")
let imageTrackingProvider = ImageTrackingProvider(referenceImages: referenceImages)
try? await session.run([imageTrackingProvider])
for await update in imageTrackingProvider.anchorUpdates {
if update.event == .added || update.event == .removed {
anchorTransform = Transform(matrix: update.anchor.originFromAnchorTransform)
}
// TODO handle remove
}
}
}
}
struct RedView: View {
let anchorTransform:Transform
var body: some View {
RealityView { content in
let entity = ModelEntity(mesh: .generateSphere(radius: 0.2), materials: [SimpleMaterial(color: .red, isMetallic: false)])
entity.transform = anchorTransform
content.add(entity)
}
}
}
struct GreenView: View {
let anchorTransform:Transform
var body: some View {
RealityView { content in
let entity = ModelEntity(mesh: .generateSphere(radius: 0.2), materials: [SimpleMaterial(color: .green, isMetallic: false)])
entity.transform = anchorTransform
content.add(entity)
}
}
}