Reputation: 13
I just follow the WWDC sessions about realitykit(session url),
and make a portal to a seperate world, which is child of a AnchorEntity finding for a vertical wall. But the portal
Entity not shows, and the sun
Entity shows, do my code has some mistakes?
The code is as follows:
struct ImmersiveView: View {
var addToAnchor = true
var body: some View {
RealityView { content in
let world = makeWorld()
let portal = makePortal(world)
content.add(world)
let anchor = AnchorEntity(.plane(.vertical, classification: .wall,
minimumBounds: [1, 1]))
content.add(anchor)
content.subscribe(to: SceneEvents.AnchoredStateChanged.self, on: anchor, componentType: nil) { event in
print("AnchoredStateChanged")
}
// the portal not shows
anchor.addChild(portal)
let sun = try! await Entity(named: "Sun", in: realityKitContentBundle)
// the sun shows
anchor.addChild(sun)
}
}
@MainActor
func makeWorld() -> Entity {
let world = Entity()
world.components[WorldComponent.self] = .init()
let earth = try! Entity.load(named: "Earth", in: realityKitContentBundle)
let sun = try! Entity.load(named: "Sun", in: realityKitContentBundle)
earth.position = .init(x: -0.5, y: 1.5, z: -2)
sun.position = .init(x: 0.5, y: 1.5, z: -2)
world.addChild(earth)
world.addChild(sun)
let resource = try! TextureResource.load(named: "Starfield")
var material = UnlitMaterial()
material.color = .init(texture: .init(resource))
// Attach the material to a large sphere.
let background = Entity()
background.components.set(ModelComponent(
mesh: .generateSphere(radius: 1000),
materials: [material]
))
// Ensure the texture image points inward at the viewer.
background.scale *= .init(x: -1, y: 1, z: 1)
//world.addChild(background)
return world
}
@MainActor
func makePortal(_ world: Entity) -> Entity {
let portal = Entity()
portal.components[ModelComponent.self] = .init(mesh: .generatePlane(width: 1,
height: 1,
cornerRadius: 0.5),
materials: [PortalMaterial()])
portal.components[PortalComponent.self] = .init(target: world)
return portal
}
}
I also tried to put the portal directly in space, and it shows perfectly: Picture
Upvotes: 1
Views: 568
Reputation: 58553
It's not an anchoring problem. Your code works fine. All you have to do is to rotate the portal 90 degrees clockwise around the X-axis, because the portal faces down: that's why you didn't see it on the screen (in RealityKit materials are single-sided, rather than double-sided as in SceneKit). Besides, I slightly fixed your code, so that all objects were clearly visible. Alternatively, if you don't want to rotate your portal, use the .generatePlane(width:depth:)
method instead.
(rkcb
is realityKitContentBundle
here)
When a vertical plane is detected, an anchor with the positive Z-axis pointing down is placed in the scene (imagine that the entity is rotated around the X-axis by 90 degrees CCW). Anchor's parental transform is passed to the portal entity. The width (X) and height (Y) of the generated portal plane fully correspond to XY-plane of the anchor on the wall. To compensate for the portal's orientation, a 90-degree clockwise X-rotation is required.
import SwiftUI
import RealityKit
import RealityKitContent
struct ImmersiveView : View {
var body: some View {
RealityView { content in
let world = makeWorld()
let portal = makePortal(world)
let anchor = AnchorEntity(.plane(.vertical,
classification: .wall,
minimumBounds: [1, 1]))
anchor.addChild(portal)
content.add(world)
content.add(anchor)
let _ = content.subscribe(to: SceneEvents.AnchoredStateChanged.self,
on: anchor) { event in
print("Anchored State Changed")
}
}
}
@MainActor func makePortal(_ world: Entity) -> Entity {
let portal = Entity()
portal.orientation = simd_quatf(angle: -.pi/2, axis: [1,0,0]) // rotate CW
portal.components[ModelComponent.self] = .init(mesh: .generatePlane(
width: 3,
height: 3,
cornerRadius: 1.5),
materials: [PortalMaterial()])
portal.components[PortalComponent.self] = .init(target: world)
return portal
}
@MainActor func makeWorld() -> Entity {
let world = Entity()
world.components[WorldComponent.self] = .init()
let earth = try! Entity.load(named: "Earth", in: rkcb)
let sun = try! Entity.load(named: "Sun", in: rkcb)
earth.scale *= 3
sun.scale *= 3
earth.position = .init(x: -0.5, y: 1.5, z: -3)
sun.position = .init(x: 0.5, y: 1.5, z: -3)
world.addChild(earth)
world.addChild(sun)
let resource = try! TextureResource.load(named: "Starfield")
var material = UnlitMaterial()
material.color = .init(texture: .init(resource))
let background = Entity()
background.components.set(ModelComponent(
mesh: .generateSphere(radius: 1000),
materials: [material]))
background.scale.x *= -1
world.addChild(background)
return world
}
}
To see anchor's orientation, turn on Anchoring in Debug Visualizations
menu:
Upvotes: 0