본문 바로가기
IOS

[iOS] ARKit(1) - OverView, Setting

by eigen96 2024. 1. 21.
728x90

 

요즘 그래픽스 관련 서적을 참고하고 Metal 관련 코드를 공부하고 있다.
그러다가 집중력이 흐려질땐 내부적으로 Metal 기능을 사용하고 있는 ARKit, RealityKit과 같은 프레임워크를 경험하면서 Top - Down 방식으로 접근해보는 것도 도움이 될 것이라 판단했다.
 

ARKit 

ARKit 프레임워크의 주요 목적은 증강 현실(AR) 경험을 개발하는 것이며 제공하는 기능은 다음의 4가지다.

  •  motion tracking
  • world tracking
  • 환경의 표면, 크기, 형태를 파악
  • 디스플레이 편의성

ARKit의 차별화된 기능: 마커리스 추적

ARKit의 특징 중 하나는 markerless tracking 이다.
추적 카드(마커)도 필요 없이 주변 환경을 파악하고, 가상 콘텐츠를 실제 환경에 자연스럽게 어우러지게 배치할 수 있다.
이전에 사용되던 많은 AR 프레임워크들은 ARKit의 Markerless Tracking 을 자신들의 API에 통합하여 사용할 수 있다고 한다. 
시간이 된다면 유니티와 함께 활용해보고 싶다는 생각이 들었다.

 
https://developer.apple.com/documentation/visionos/setting-up-access-to-arkit-data#Open-a-space-and-run-a-session

Setting up access to ARKit data | Apple Developer Documentation

Check whether your app can use ARKit and respect people’s privacy.

developer.apple.com

 
 
 

ARKit API

WWDC에서 안내하는 것에 따르면,
API는 Session, Data Provider, Anchor라는 세가지 기본 구성요소로 이루어진다고 합니다.
 

Anchor

Anchor 설명은 다음과 같다.

Anchor는 실제 세계에서의 위치와 방향을 나타냅니다.
모든 앵커는 고유 식별자와 변환(transform)을 포함합니다.

일부 Anchor 유형은 추적 가능합니다.
추적 가능한 Anchor가 추적되지 않을 때, 그것과 연결된 가상 콘텐츠를 숨겨야 합니다.

 

 

 
AR 게임에서 테이블 위에 가상의 체스판을 배치하고 싶다면, 테이블의 특정 위치에 앵커를 설정하여 그 위치를 가상 체스판의 기준점으로 사용할 수 있겠다.
만약 AR 게임에서 체스판을 표시하고자 할 때, 추적 가능한 앵커를 사용한다면, 사용자가 테이블 주위를 돌아다니며 게임을 플레이하면서도 체스판이 항상 동일한 위치에 고정되어 보이는 것이다.
만약 추적이 중단되면(예를 들어, 카메라가 테이블을 벗어나거나 조명이 변하여 테이블을 인식하지 못하는 경우), 체스판은 숨겨질 것이다.
 

Data Provider

DataProvider는 개별 ARKit 기능을 나타냅니다.
DataProvider를 통해 앵커 변화와 같은 데이터 업데이트를 폴링하거나 관찰할 수 있습니다.
다양한 유형의 DataProvider는 다른 유형의 데이터를 제공합니다.

 
예를 들어, 하나의 DataProvider는 사용자의 위치 데이터를 제공하는 반면, 다른 하나는 게임의 가상 객체들이 현실 세계의 물리적 공간 내에서 어떻게 배치되어야 하는지에 대한 정보를 제공할 수 있다.
 

ARKitSession

세션이 실행되면, 데이터 제공자는 데이터를 수신하기 시작합니다.
업데이트는 비동기적으로 도착하며 데이터 유형에 따라 다른 빈도로 도착합니다.

세션은 DataProvider들로부터 정보를 받아들여, 가상 환경을 관리하고 사용자의 행동에 반응하여 가상 콘텐츠를 업데이트한다.
 

 
run 함수는 비동기적으로 호출될 수 있으며, 실행 시 예외가 발생할 수 있음을 나타내는 throws 키워드를 포함한다.
run 함수는 DataProvider 배열을 인자로 받아, 이 데이터 제공자들로부터 데이터를 수집하고 처리하여 AR 경험을 실행한다.
stop 함수는 AR 세션을 중지한다.

 

권한 설정

ARKit을 사용하기 전에 권한 설정부터 해주어야 한다.
 
ARKit은 손 추적이나 World sensing처럼 민감한 데이터를 사용하여 경험을 제공한다.
그래서 만약에 사용자가 ARKit 데이터 접근을 거부한다면, 우리 앱은 이 상황을 잘 처리할 수 있어야 한다고 공식문서에 안내되어있다.
 

  • 필요한 키 :
    • NSHandsTrackingUsageDescription: 앱이 손 추적을 사용하는 경우,
      사용자에게 앱이 손 추적 데이터를 어떻게 사용하는지 설명하는 메시지를 제공
    • NSWorldSensingUsageDescription: 앱이 이미지 추적, 평면 감지, 또는 장면 재구성을 사용하는 경우,
      사용자에게 앱이 이러한 데이터를 어떻게 사용하는지 설명하는 메시지를 제공

그런데 world tracking world sensing와 달리 권한 요청이 필요하지 않다고 한다. 

 

이 둘은 무엇이 다를까?
 
1. World Tracking 
   - 주로 증강 현실 환경에서 사용자의 위치와 방향을 추적하는 데 사용된다.
   - World Tracking 은 장치의 카메라와 센서를 사용하여 사용자의 움직임과 주변 환경의 지형을 실시간으로 파악.
   - 가상 객체를 실제 환경에 정확하게 배치하고, 사용자가 움직임에 따라 그 객체를 보고 상호작용.
 
기본적인 위치 추적과 방향 감지에 초점을 맞추므로 일반적으로 추가적인 권한 요청이 필요하지 않다.

2. World Sensing
   - 사용자의 주변 환경에 대한 더 깊은 이해와 분석을 제공.
   - 주변 환경의 물리적 및 기하학적 속성을 감지
   - 예를 들어, 월드 센싱은 주변의 물체 크기, 위치, 심지어 표면의 질감과 같은 세부 사항을 인식할 수 있다.
 
주변 환경의 세부 정보를 수집하고 처리하기 때문에 민감한 데이터를 다룰 가능성이 있기 때문에 권한 요청이 필요할 수 있겠다.

명시적 권한 요청

권한 요청이 나타나는 시기를 정확히 제어

func requestARPermission() {
    ARSession.requestAuthorization(for: .camera)
}

 

암시적 권한 요청

run(_:) 메소드를 호출할 때 권한 요청

func startARSession() {
    let configuration = ARWorldTrackingConfiguration()
    arSession.run(configuration)
}

 
 
Open a Space and run a session
 
run(_:) 메소드를 호출하기 전에, space style이 필요하다.
공식문서 예제 코드는 다음과 같다.
 
MyApp 구조체 내에서 ImmersiveSpace를 사용하여 ARKit 세션을 실행하고 있다.
ContentView에서 버튼을 통해 전체 공간을 열고 ARKit 세션을 시작한다.
사용자가 버튼을 클릭하면 openImmersiveSpace를 호출하여 ARKit 경험을 제공한다.

@main
struct MyApp: App {
    @State var session = ARKitSession() // ARKit 세션을 관리하는 상태 변수
    @State var immersionState: ImmersionStyle = .mixed // 몰입 스타일 상태 변수
    var body: some Scene {
        WindowGroup {
            ContentView() // 앱의 주 내용을 표시하는 뷰
        }
        ImmersiveSpace(id: "appSpace") { // ARKit을 사용하는 몰입 공간을 생성
            MixedImmersionView()
            .task {
                let planeData = PlaneDetectionProvider(alignments: [.horizontal])
                // 평면 감지 제공자를 생성. 여기서는 수평 평면 감지를 설정

                if PlaneDetectionProvider.isSupported {
                    do {
                        try await session.run([planeData])
                        // 평면 데이터를 사용하여 ARKit 세션을 실행
                        for await update in planeData.anchorUpdates {
                            // 평면 데이터에 대한 업데이트를 처리
                            // 여기서는 앱 상태 업데이트를 예로 들 수 있음
                        }
                    } catch {
                        print("ARKit session error \(error)")
                        // ARKit 세션 실행 중 오류 처리
                    }
                }
            }
        }
        .immersionStyle(selection: $immersionState, in: .mixed)
        // 몰입 스타일 설정. 이 예시에서는 'mixed' 스타일 사용
    }
}

struct ContentView: View {
    @Environment(\.openImmersiveSpace) private var openImmersiveSpace
    // 몰입 공간을 여는 메서드에 대한 환경 변수

    var body: some View {
        Button("Start ARKit experience") {
            Task {
                await openImmersiveSpace(id: "appSpace")
                // 버튼을 누르면 몰입 공간을 열고 ARKit 세션을 시작
            }
        }
    }
}

 

 
ImmersiveSpace 는 앱이 제한 없는 공간에서 콘텐츠를 표시할 수 있게 하는 씬(scene)이다.
visionOS에서 앱이 제한 없는 공간에서 콘텐츠를 표시하기 위해 사용되는 구조체라고 한다. 

struct ImmersiveSpace<Content, Data> where Content : ImmersiveSpaceContent, Data : Decodable, Data : Encodable, Data : Hashable

ImmersiveSpace는 뷰 계층 구조를 포함하는 컨테이너로 사용된다.
다음 코드를 살펴보면,
SolarSystemAppImmersiveSpace를 사용하여 SolarSystem 뷰를 표시한다.

@main
struct SolarSystemApp: App {
    var body: some Scene {
        ImmersiveSpace {
            SolarSystem()
        }
    }
}

 
 
ImmersiveSpace | Apple Developer Documentation

ImmersiveSpace | Apple Developer Documentation

A scene that presents its content in an unbounded space.

developer.apple.com

 

728x90

댓글