기본 개념
VisionOS에서는 ARKit을 통해 다양한 지각 기능에 액세스할 수 있습니다.
평면 감지: 주변 환경의 수평면과 수직면을 감지하여 콘텐츠를 고정하는 데 사용합니다.
월드 트래킹: 주변 환경에 대한 디바이스의 위치와 방향을 결정하고 월드 앵커를 추가하여 콘텐츠를 배치합니다.
손 추적: 사람의 손과 손가락 위치를 사용자 지정 제스처 및 상호작용을 위한 입력으로 사용합니다.
씬 재구성: 사람 주변의 물리적 환경을 메시로 구성하고 이를 몰입형 공간에 통합하여 상호 작용을 지원합니다.
이미지 추적: 사용자 주변에서 알려진 이미지를 찾아 사용자 지정 콘텐츠의 앵커로 사용합니다.
현재 비전OS 에뮬레이터에서는 월드 트래킹만 지원되며 다른 기능은 지원되지 않습니다.
이러한 지각 기능을 통해 카메라를 향하게 하거나 카메라를 따라가는 등의 기능을 구현할 수 있으며, 이 논문에서는 물체가 항상 카메라를 향하게 하는 구현을 보여줍니다.
기본 구현
- ARKitSession을
WorldTrackingProvider디바이스의 실시간 포즈를 가져오는 일을 주로 담당하는 ARKitSessionManager를 정의합니다.
import SwiftUI
import ARKit
@MainActor
class ARKitSessionManager: ObservableObject {
let session = ARKitSession()
let worldTracking = WorldTrackingProvider()
func startSession() async {
if WorldTrackingProvider.isSupported {
do {
try await session.run([worldTracking])
} catch {
assertionFailure("Failed to run session: (error)")
}
}
}
func getOriginFromDeviceTransform() -> simd_float4x4 {
guard let pose = worldTracking.queryDeviceAnchor(atTimestamp: CACurrentMediaTime()) else {
return simd_float4x4()
}
return pose.originFromAnchorTransform
}
}
- 대상 오브젝트가 항상 카메라를 향하는 특성을 갖도록 하려면 섹션 6에서 소개한 ECS 모드에 따라 해당 컴포넌트 및 시스템을 정의해야 합니다.
- 컴포넌트는 엔티티 상태 데이터를 기록합니다.
- 시스템 제어 엔티티 동작
여기서 페이스 컴포넌트에는 많은 상태가 없으며, 시스템이 카메라 정보를 가져올 수 있도록 시스템이 사용할 해당 ARKitSessionManager를 기록할 뿐입니다.
import RealityKit
public struct FaceComponent: Component {
let manager: ARKitSessionManager?
}
팔로우시스템에서.
followEntity.manager!.getOriginFromDeviceTransform()통해 장치 트랜스폼을 가져와서 위치 좌표를 추출합니다.entity.transform.translation통해 엔티티 위치 좌표를 가져옵니다.
매우 사용하기 쉬운 기능 look(at:from:upVector:relativeTo:) 엔티티에서 주어진 위치에서 대상을 바라보도록 엔티티의 위치 및 방향을 지정하는 데 제공됩니다. 이 기능은 모든 엔티티에서 사용할 수 있지만, 특히 카메라와 조명이 공간의 특정 지점을 조준하도록 위치를 지정하는 데 유용합니다.
import RealityKit
public struct FaceSystem: System {
static let faceQuery = EntityQuery(where: .has(FaceComponent.self))
public init(scene: Scene) {
}
public func update(context: SceneUpdateContext) {
let entities = context.scene.performQuery(Self.faceQuery)
for entity in entities {
guard let followEntity = entity.components[FaceComponent.self] else {
continue
}
if followEntity.manager == nil {
return
}
let cameraTransform = followEntity.manager!.getOriginFromDeviceTransform()
let cameraPosition = SIMD3<Float>(cameraTransform.columns.3.x, cameraTransform.columns.3.y, cameraTransform.columns.3.z)
let entityPosition = entity.transform.translation
entity.look(at: cameraPosition, from: entityPosition, relativeTo: nil)
}
}
}
- 전체 몰입 공간을 열고 3D 오브젝트를 로드한 후 ARKit에서 정보를 사용할 수 있으려면 ARKitSessionManager를 초기화하고 ARKitSession을 시작해야 합니다. ARKitSessionManager를 사용하여 새로 생성된 FaceComponent에 전달하면 결국 엔티티에 부착되어 추적 효과를 구현할 수 있습니다. 페이스 시스템이 디바이스와 엔티티의 위치 정보를 가져와 추적 효과를 구현할 수 있습니다.
struct ImmersiveView: View {
@State var entity = Entity()
@ObservedObject var arkitSessionManager = ARKitSessionManager()
var body: some View {
RealityView { content in
let tv = try! await Entity(named: "tv_retro")
tv.transform.rotation = simd_quatf(angle: .pi, axis: [0, 1, 0])
entity.addChild(tv)
let followComponent = FaceComponent(manager: arkitSessionManager)
entity.components[FaceComponent.self] = followComponent
entity.position = SIMD3<Float>(x: 0, y: 1.2, z: 0)
content.add(entity)
}
.task {
await arkitSessionManager.startSession()
}
}
}





