Post

Replies

Boosts

Views

Activity

Reply to Rotating ModelEntities (without Gestures) Help
Thank you for the response! I'm new to Swift so I would definitely like assistance adapting the code. I see how it fits into the make closure of my RealityView. How can I provide the planeEntity and cubeEntity created in appModel.updatePlane to the DidAddEntity subscriber? Is it just as easy as adding the plane and cube entities to variables in appModel - appModel.currentPlaneRendered for example? This is my ImmersiveView View: struct ImmersiveView: View { @Environment(AppModel.self) var appModel @State private var updateFacingPlaneTaskWorking: Task<Void, Never>? = nil var body: some View { RealityView { content in content.add(appModel.setupContentEntity()) // Add the initial RealityKit content if let immersiveContentEntity = try? await Entity(named: "Immersive", in: realityKitContentBundle) { content.add(immersiveContentEntity) } // Updates and renders the horizontal plane in front of the person at 10 Hz. updateFacingPlaneTaskWorking = run(appModel.updateFacingPlaneWorking, withFrequency: 10) // New content subscriber to the creation of a cubeEntity to rotate it after animation becomes available _ = content.subscribe(to: SceneEvents.DidAddEntity.self, on: cubeEntity) { event in let rotationY = simd_quatf(angle: Float(45.0 * .pi/180.0), axis: SIMD3(x: 0, y: 1, z: 0)) let cubeTransform = Transform(rotation: rotationY) event.entity.move(to: cubeTransform, relativeTo: planeEntity, duration: TimeInterval(10), timingFunction: .easeInOut) } } .onDisappear { updateFacingPlaneTaskWorking?.cancel() } .task { await appModel.runARKitSession() } .task { await appModel.processPlaneDetectionUpdates() } } } I've adapted the code from the Room Tracking example for wall tracking into horizontal plane tracking with the PlaneDetectionProvider. The planeEntity and cubeEntity creation occurs in the task where I call await appModel.processPlaneDetectionUpdates(). In appModel I have the following functions: func processPlaneDetectionUpdates() async { for await anchorUpdate in planeData.anchorUpdates { switch anchorUpdate.event { case .added, .updated: await updatePlane(anchorUpdate.anchor) case .removed: await removePlane(anchorUpdate.anchor) } } } @MainActor func updatePlane(_ anchor: PlaneAnchor) async { // Get the transform matrix of the anchor let anchorTransform = anchor.originFromAnchorTransform // Convert the matrix into a RealityKit Transform var transform = Transform(matrix: anchorTransform) // Add 6 inches twice (0.1524 meters) to the y-axis transform.translation.y += 0.1524 entityMap[anchor.id]?.transform = transform // getting anchor geometry let anchorGeometry = anchor.geometry guard let planeMeshResource = anchorGeometry.asMeshResource() else { return } let planeEntity = ModelEntity(mesh: planeMeshResource, materials: [whiteMaterial]) planeEntity.transform = Transform(matrix: anchor.originFromAnchorTransform) planeEntity.name = anchor.classification.description // adding a collision component with a shape guard let shape = try? await ShapeResource.generateStaticMesh(from: planeMeshResource) else { logger.error("Failed to create ShapeResource from planeEntity geometry.") return } planeEntity.collision = CollisionComponent(shapes: [shape], isStatic: true) planeEntity.components.set(InputTargetComponent()) planeEntity.components.set(HoverEffectComponent()) if let planeCentroid = planeEntity.centroid { // Create a cube at the centroid let cubeMesh = MeshResource.generateBox(size: 0.1) // Create a cube with side length of 0.1 meters let cubeMaterial = SimpleMaterial(color: .blue, isMetallic: false) let cubeEntity = ModelEntity(mesh: cubeMesh, materials: [cubeMaterial]) // Add a collision component to the cube let cubeShape = ShapeResource.generateBox(size: [0.1, 0.1, 0.1]) cubeEntity.collision = CollisionComponent(shapes: [cubeShape]) cubeEntity.position = planeCentroid // cubeEntity.position.y += 0.3048 planeEntity.addChild(cubeEntity) // Check if the cube intersects the plane using bounding boxes if checkBoundingBoxOverlap(planeEntity: planeEntity, cubeEntity: cubeEntity) { print("Cube intersects with the plane!") } else { print("No intersection detected.") } // add plane classification text let font = UIFont.systemFont(ofSize: 0.2) // Adjust the font size to control text appearance let textMesh = MeshResource.generateText( anchor.classification.description, extrusionDepth: 0.06, // Adjust depth to control thickness font: font ) let textEntity = ModelEntity(mesh: textMesh) textEntity.name = anchor.classification.description // Add white color material to the text textEntity.model?.materials = [whiteMaterial] // Add the BillboardComponent to the entity textEntity.components.set(BillboardComponent()) textEntity.components.set(HoverEffectComponent()) // Calculate the bounding box of the text mesh if let bounds = textEntity.model?.mesh.bounds { // Offset the text position to center it let offset = (bounds.max + bounds.min) / 2 textEntity.position = planeCentroid + offset } planeEntity.addChild(textEntity) } colliderPlanesRoot.addChild(planeEntity) }
Nov ’24