안녕하세요! 피피아노입니다 🎵
이번 포스팅에서는 WWDC23 세션 중 하나인 공간 컴퓨팅을 위한 ARKit 세션을 정리해보려고 합니다.
자세한 내용은 아래 링크를 참고하시면 좋을 것 같습니다.
https://developer.apple.com/kr/videos/play/wwdc2023/10082
공간 컴퓨팅을 위한 ARKit 알아보기 - WWDC23 - 비디오 - Apple Developer
ARKit의 추적과 씬 이해 기능을 사용해 몰입형 앱과 게임에 완전히 새로운 세계를 개발할 방법을 알아보세요. visionOS와 ARKit이 만나 어떤 식으로 사람의 주변 환경을 이해하는 앱을 만들 수 있게
developer.apple.com
그럼 바로 시작하겠습니다!
아키텍처의 변화
새로운 설계 철학
기존 ARKit가 앱 레벨에서 동작하는 라이브러리 형태였다면, 새로운 ARKit는 운영체제 깊숙이 통합된 시스템 서비스로 설계되었습니다. 이는 단순히 기술적 변화를 넘어, 개발자들이 공간 컴퓨팅 경험을 구축하는 방식 자체를 혁신하는 변화입니다.
새로운 API 설계는 Swift와 C 언어 모두를 지원하며, 개발자에게 최대한의 유연성을 제공합니다.
모든 ARKit 기능이 개별적으로 제공되어, 필요한 기능만 선택적으로 사용할 수 있도록 모듈화되었습니다.
핵심 구성 요소
ARKit의 새로운 아키텍처는 Anchor, Data Provider, Session 이렇게 세 가지 핵심 빌딩 블록으로 구성됩니다.
1. 앵커(Anchor)
- 현실 세계의 위치와 방향을 나타내는 기본 단위
- 고유 식별자와 transform 정보를 포함
- 추적 가능한 앵커는 실시간으로 업데이트되어 가상 콘텐츠의 정확한 위치 유지
2. 데이터 공급자(Data Provider)
- 개별 ARKit 기능을 캡슐화한 컴포넌트
- 앵커 변경사항을 폴링하거나 관찰 가능
- 기능별로 특화된 데이터 타입 제공
3. 세션(Session)
- ARKit 기능들의 조합을 관리하는 중앙 제어 시스템
- 특정 경험에 필요한 데이터 공급자들을 통합 관리
- 비동기적으로 다양한 주파수의 업데이트 처리
프라이버시 우선 설계
데이터 보호 메커니즘
새로운 ARKit는 프라이버시 보호를 위한 안전장치를 구축했습니다. 카메라 프레임과 같은 민감한 센서 데이터는 절대 클라이언트 공간으로 전송되지 않으며, ARKit 데몬에서 안전하게 처리된 후 큐레이션된 결과 데이터만 앱으로 전달됩니다.
접근 권한 관리
ARKit 데이터 접근을 위한 두 가지 필수 조건이 있습니다.
- Full Space 진입: Shared Space에서는 ARKit 데이터 접근 불가
- 명시적 권한 부여: 특정 데이터 타입에 대한 사용자 승인 필요
권한 설정 API를 통해 필요한 권한을 배치로 요청할 수 있으며, 세션 실행 시 자동 권한 요청도 지원합니다.
// Privacy
// Authorization
session = ARKitSession()
Task {
let authorizationResult = await session.requestAuthorization(for: [.handTracking])
for (authorizationType, authorizationStatus) in authorizationResult {
print("Authorization status for \(authorizationType): \(authorizationStatus)")
switch authorizationStatus {
case .allowed:
// All good!
break
case .denied:
// Need to handle this.
break
...
}
}
}
핵심 기능별 분석
월드 추적(World Tracking)
월드 추적은 가상 콘텐츠를 현실 세계에 정확하게 고정시키는 것이 핵심 기능입니다.
WorldTrackingProvider의 주요 특징
- 6DOF 기기 움직임 추적: 위치와 회전을 실시간으로 추적
- WorldAnchor 자동 지속성: 앱 재시작 후에도 앵커 위치 유지
- 위치 기반 맵 관리: 사용자의 물리적 위치 변경에 따른 자동 맵 전환
// World tracking
// Device pose
#include <ARKit/ARKit.h>
#include <CompositorServices/CompositorServices.h>
struct Renderer {
ar_session_t session;
ar_world_tracking_provider_t world_tracking;
ar_pose_t pose;
...
};
void renderer_init(struct Renderer *renderer) {
renderer->session = ar_session_create();
ar_world_tracking_configuration_t config = ar_world_tracking_configuration_create();
renderer->world_tracking = ar_world_tracking_provider_create(config);
ar_data_providers_t providers = ar_data_providers_create();
ar_data_providers_add_data_provider(providers, renderer->world_tracking);
ar_session_run(renderer->session, providers);
renderer->pose = ar_pose_create();
...
}
// World tracking
// Device pose
void render(struct Renderer *renderer,
cp_layer_t layer,
cp_frame_t frame_encoder,
cp_drawable_t drawable) {
const cp_frame_timing_t timing_info = cp_drawable_get_frame_timing(drawable);
const cp_time_t presentation_time = cp_frame_timing_get_presentation_time(timing_info);
const CFTimeInterval target_render_time = cp_time_to_cf_time_interval(presentation_time);
simd_float4x4 pose = matrix_identity_float4x4;
const ar_pose_status_t status =
ar_world_tracking_provider_query_pose_at_timestamp(renderer->world_tracking,
target_render_time,
renderer->pose);
if (status == ar_pose_status_success) {
pose = ar_pose_get_origin_from_device_transform(renderer->pose);
}
...
cp_drawable_set_ar_pose(drawable, renderer->pose);
...
}
씬 이해 (Scene Understanding)
씬 이해는 주변 환경을 이해하고 분석하는 기능을 모아둔 것입니다.
평면 감지(Plane Detection)
- 수평/수직 표면의 실시간 감지
- 시맨틱 분류를 통한 표면 타입 식별(바닥, 테이블, 벽 등)
- 물리 시뮬레이션과 콘텐츠 배치에 활용
씬 지오매트리(Scene Geometry)
- 환경의 3D 형태를 다각형 매시로 재구성
- 면 단위 시맨틱 분류 제공
- 복잡한 물리 상호작용과 현실감 있는 콘텐츠 배치 지원
이미지 추적(Image Tracking)
이미지 추적은 2D 이미지의 실시간 감지 및 추적 기능입니다.
주요 특징으로는 Asset Catalog 또는 런타임 이미지 소스를 지원하고 스케일 팩터를 통한 크기 변화를 대응할 수 있습니다. 또한 정적 이미지 기반 콘테츠 앵커링이 가능합니다.
손 추적(Hand Tracking)
Apple은 이번 ARKit에 손 추적(Hand Tracking) 기능을 새롭게 추가했습니다. 이제 개발자는 사용자의 손 움직임과 제스처를 정밀하게 추적하여 더욱 자연스러운 상호작용을 구현할 수 있습니다.
손 추적 기능의 핵심은 HandAnchor입니다.
HandAnchor는 TrackableAnchor의 일종으로, 다음과 같은 데이터를 포함합니다.
- Skeleton 데이터: 손의 각 관절 정보를 담고 있음
- 카이랄성(Chirality): 왼손인지, 오른손인지를 구분
- Transform: 앱 원점에 대한 손목(wrist)의 위치와 회전 정보
Skeleton은 이름 기반으로 쿼리할 수 있는 관절들의 계층 구조를 갖습니다.
- 손목(wrist)이 루트(root) 관절
- 각 손가락의 첫 관절은 손목을 부모로 가짐
- 이후 관절들은 순차적으로 부모-자식 관계를 형성
또한, 각 관절에는 Bool 값이 있어서 해당 관절이 추적되고 있는지 여부를 확인할 수 있습니다.
/ Hand tracking
@available(xrOS 1.0, *)
public struct Skeleton : @unchecked Sendable, CustomStringConvertible {
public func joint(named: SkeletonDefinition.JointName) -> Skeleton.Joint
public struct Joint : CustomStringConvertible, @unchecked Sendable {
public var parentJoint: Skeleton.Joint? { get }
public var name: String { get }
public var localTransform: simd_float4x4 { get }
public var rootTransform: simd_float4x4 { get }
public var isTracked: Bool { get }
}
}
// Hand tracking
// Polling for hands
struct Renderer {
ar_hand_tracking_provider_t hand_tracking;
struct {
ar_hand_anchor_t left;
ar_hand_anchor_t right;
} hands;
...
};
void renderer_init(struct Renderer *renderer) {
...
ar_hand_tracking_configuration_t hand_config = ar_hand_tracking_configuration_create();
renderer->hand_tracking = ar_hand_tracking_provider_create(hand_config);
ar_data_providers_t providers = ar_data_providers_create();
ar_data_providers_add_data_provider(providers, renderer->world_tracking);
ar_data_providers_add_data_provider(providers, renderer->hand_tracking);
ar_session_run(renderer->session, providers);
renderer->hands.left = ar_hand_anchor_create();
renderer->hands.right = ar_hand_anchor_create();
...
}
HandAnchor 가져오기
HandAnchor는 두 가지 방식으로 사용할 수 있습니다.
- Polling 방식: get_latest_anchors를 사용해 최신 데이터를 가져옴
- Async 방식: 비동기 업데이트 시퀀스로 앵커를 받음
// Hand tracking
// Polling for hands
void render(struct Renderer *renderer,
... ) {
...
ar_hand_tracking_provider_get_latest_anchors(renderer->hand_tracking,
renderer->hands.left,
renderer->hands.right);
if (ar_trackable_anchor_is_tracked(renderer->hands.left)) {
const simd_float4x4 origin_from_wrist
= ar_anchor_get_origin_from_anchor_transform(renderer->hands.left);
...
}
...
}
감사합니다.
잘못된 내용이 있거나 더 좋은 내용 피드백은 언제나 환영합니다!
궁금하신 부분은 댓글로 질문 부탁드립니다!
'Apple > visionOS' 카테고리의 다른 글
[visionOS] Reality Composer Pro 사용해보기 (8) | 2024.09.01 |
---|---|
[visionOS] RealityKit과 ARKit 알아보기 (1) | 2024.08.25 |
[visionOS] Vision Pro의 제스처 및 정책 (4) | 2024.08.22 |
[visionOS] visionOS의 Environment 알아보기 (1) | 2024.08.16 |