스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
ARKit으로 향상된 공간 컴퓨팅 경험 제작하기
ARKit의 최신 기능을 활용하여 매혹적이고 몰입감 넘치는 경험을 제작하는 방법을 알아보세요. 실내 추적 및 물체 추적을 사용하여 배경을 더욱 매끄럽게 통합하는 방법을 확인해 보세요. visionOS에서 앱이 환경의 조명에 따라 반응하도록 하는 방법도 공유합니다. 더 직관적인 공간 경험을 위한 손 동작 추적 및 평면 감지 기능의 개선 사항도 함께 확인해 보세요.
챕터
- 0:00 - Introduction
- 2:30 - Room tracking
- 5:46 - Plane detection
- 6:46 - Object tracking
- 9:34 - World tracking
- 11:38 - Hand tracking
리소스
관련 비디오
WWDC24
WWDC23
-
다운로드
안녕하세요 저는 Divyesh입니다 이 세션에서는 visionOS의 ARKit에 적용될 업데이트를 살펴보겠습니다 작년 Apple은 전체 OS를 구동하는 실시간 알고리즘의 핵심 호스트인 ARKit을 선보였습니다 개발자들은 ARKit의 추적 및 장면 이해 기능을 사용하여 경이로운 경험을 선보였습니다 흥미로운 퍼즐 게임 Blackbox는 ARKit을 활용하여 플레이어의 손 제스처를 감지합니다 Super Fruit Ninja는 손 동작 추적을 사용하여 과일 자르기를 표현하고 공간 이해 기능을 사용하여 남은 과일이 바닥에 튀는 장면을 생생하게 표현합니다 지난 한 해 Apple은 개발자 피드백을 바탕으로 앱이 사용자 주변 환경을 이해 및 활용할 수 있게 돕는 기능들을 개발했습니다 이러한 개선 사항을 살펴보겠습니다 먼저 공간 이해 기능의 개선 사항입니다 새로운 실내 추적 기능이 추가되었고 평면 감지가 업데이트되어 현재 실내 공간에 따라 경험을 맞춤화할 수 있습니다 새로운 객체 추적 기능은 실제 객체를 위한 대화식 시각 요소 제작에 사용할 수 있습니다 ARKit의 공간 추적 기능은 다양한 조명 조건에서 더욱 강력해졌습니다 손 동작 추적의 최신 개선 사항을 앱에서 활용할 방법도 소개합니다 본격적인 시작에 앞서 visionOS의 ARKit을 간략하게 살펴보겠습니다 요약하자면 visionOS 앱이 전체 공간을 표시할 때 ARKit에서 앵커 형태로 데이터를 수신할 수 있습니다
앵커는 3차원 공간에서 위치와 방향을 나타냅니다 예를 들어 표면 감지 데이터는 현실에서 감지된 표면 정보를 담고 있는 PlaneAnchor 형태로 전달됩니다
ARKit은 Data Provider를 통해 앱에 앵커를 전달합니다 Data Provider는 개별 ARKit 기능을 구성하고 해당 데이터를 수신하기 위한 인터페이스입니다 PlaneDetectionProvider는 PlaneAnchor를 수신하는 인터페이스입니다
ARKitSession을 실행하려면 경험에 사용하려는 Data Provider 세트를 제공하면 됩니다 ARKit의 API를 처음 접하시거나 자세한 정보가 필요하신 경우 작년 세션인 ‘공간 컴퓨팅을 위한 ARKit 알아보기’를 시청하시기 바랍니다 이제 첫 번째 신기능인 실내 추적에 대해 알아보겠습니다 많은 visionOS 앱은 사용자가 현재 있는 방 안에서 실행됩니다 메시 및 평면 앵커 데이터로도 사실적으로 배치된 가상 콘텐츠를 사용하여 AR 배경을 만들 수 있는데요 이제 사용자의 참여도를 새로운 차원으로 끌어올릴 수 있습니다 침실에 들어갈 때 가상의 반려동물이 반갑게 맞아준다고 상상해 보세요 실내 추적을 사용하면 방문하는 각 공간마다 경험을 독특하게 맞춤화할 수 있습니다
사용자가 주변을 둘러볼 때 ARKit이 현재 사용자가 있는 실내 경계를 식별합니다 이 정보를 사용하여 감지된 벽과 바닥의 정확히 정렬된 지오메트리를 계산합니다 게다가 ARKit은 방 사이의 전환을 인식할 수 있습니다 사용자가 다른 방에 들어가면 ARKit은 해당 공간에 대한 데이터를 제공합니다 이를 통해 앱은 사용자가 있는 공간에 따라 다른 경험을 표시할 수 있습니다
이 모든 정보는 새로운 Room Tracking Data Provider를 통해 표시되며 월드 센싱 인증이 필요합니다
RoomTrackingProvider는 사용자가 방문했던 방의 정보를 알려줄 수 있습니다 ARKit이 사용자가 밀폐된 공간에 있다고 판단하는 경우 이 인터페이스를 통해 현재 방의 앵커에 접근할 수 있습니다 현재 방 앵커를 사용하여 실내의 레이아웃에 맞춰 경험을 형성할 수 있습니다
앱에서 비동기식 실내 추적 업데이트를 수신할 수도 있는데 이는 다른 Data Provider로부터 앵커를 수신하는 방식과 유사합니다 이는 특히 다른 방으로 이동했을 때 새 방에 대한 최신 정보를 수신하기 좋은 방법입니다 참고로 RoomTrackingProvider는 현재 사용자가 있는 방의 앵커 데이터만 업데이트합니다 어떤 정보가 전달되는지 살펴보겠습니다 각 RoomAnchor는 한정된 특정 공간에 대한 공간 정보를 보유합니다
이 앵커는 현재 방의 모델링 여부를 나타낼 수 있습니다 이는 특정 콘텐츠를 사용자가 현재 있는 공간에만 표시하려는 경우에 유용합니다
각 RoomAnchor는 주변 벽과 바닥의 지오메트리도 보유합니다 이는 방의 모양을 정의하는 꼭짓점 에지, 삼각형 면의 모음으로 구성됩니다 이 메시는 메시 및 평면 앵커에서 볼 수 있는 지오메트리에 비해 방의 경계를 더 잘 나타냅니다
완전한 벽 또는 바닥마다 메시를 하나씩 분리된 지오메트리 배열로 가져올 수도 있습니다 이는 방 외부에 배치된 가상 콘텐츠를 가리거나 벽 전체를 따라 가상 포털을 여는 등의 AR 경험에 유용할 수 있습니다 지정된 3차원 포인트가 방의 경계 내에 존재하는지 테스트할 수도 있습니다 공간 추적과 함께 사용하면 특정 방에 진입할 때 가상 객체가 살아 움직이는 마법 같은 경험을 만들 수 있습니다
마지막으로, 이 새로운 앵커는 방과 관련된 평면 및 메시 앵커 ID를 제공합니다 기타 공간 이해 기능과 결합하여 앱을 최적화하는 데 유용할 수 있습니다 예를 들어 현재 방 외부의 평면 및 메시에서 고비용 연산을 제외할 수 있습니다 이외에도 실내 추적을 통해 앱을 향상할 수 있는 방법이 많으므로 활용해 보시기 바랍니다 다음은 평면 감지 기능 업데이트입니다 ARKit은 주변에서 평면 표면을 감지하여 PlaneAnchors의 형태로 정보를 제공합니다 테이블에 보드 게임을 배치하거나 벽에 가상 포스터를 배치하는 등 표면에 가상 콘텐츠를 배치할 때 유용합니다 PlaneDetectionProvider는 감지된 수평 표면과 수직 표면을 앱에 알려줄 수 있습니다
올해 새로 발표된 경사면 정렬은 경사진 표면을 감지하는 데 사용됩니다
앱은 수평 및 수직으로 정렬된 평면 앵커를 계속 받게 됩니다 여기에 변경 사항 하나만 적용하여 경사면 앵커도 받을 수 있습니다 PlaneDetectionProvider를 구성하는 정렬을 업데이트하기만 하면 됩니다
간단하게 ‘slanted’ 정렬을 추가하세요 아주 간단하죠
이제 visionOS의 새로운 기능인 객체 추적에 대해 살펴보겠습니다 이제 ARKit은 환경에 정적으로 배치된 현실 객체를 추적할 수 있습니다 객체 추적을 사용하면 이러한 각 항목의 위치와 방향을 파악하여 가상 콘텐츠를 고정할 수 있습니다 예를 들어 교육용 앱에서 사용자가 특정 도구를 관찰할 때 3D 시각 요소를 표시할 수 있습니다 ARKit이 이러한 항목을 추적하도록 하려면 ReferenceObjects 세트를 제공해야 합니다 참조 객체는 알려진 실제 항목의 공간적 특징을 인코딩합니다 ReferenceObject를 만들려면 먼저 추적하려는 항목의 3D 모델을 USDZ 형식으로 준비해야 합니다
그런 다음 CreateML의 새로운 공간 객체 추적 기능을 사용하여 애셋에서 ReferenceObject를 생성할 수 있습니다
마지막으로 ReferenceObject를 사용하여 ARKit으로 추적하면 됩니다
ReferenceObject 생성에 대해 자세히 알아보려면 올해 세션인 ‘visionOS의 물체 추적 기능 살펴보기’를 시청하세요
이 세션에서는 ReferenceObject를 만든 후 ARKit으로 실제 항목을 추적하는 마지막 단계를 집중적으로 보겠습니다
새로운 API를 사용하면 이 과정이 얼마나 간편한지 보죠
ReferenceObject는 런타임에 파일 URL 또는 번들에서 로드할 수 있습니다
여기서는 전역 ReferenceObject를 URL과 함께 로드합니다
ReferenceObject를 성공적으로 로드한 후에는 이것으로 새 ObjectTrackingProvider를 구성할 수 있습니다
다음으로 ARKitSession에서 새 ObjectTrackingProvider를 실행할 수 있습니다
Data Provider가 실행 상태가 되면 수신된 추적 결과를 처리할 수 있게 됩니다
이러한 추적 결과는 각각 추적된 항목을 나타내는 ObjectAnchor의 형태로 전달됩니다
ObjectAnchor는 감지된 객체의 축 정렬된 바운딩 박스를 보유합니다 바운딩 박스의 중심과 범위는 물론 최소 및 최대 3D 좌표점을 얻을 수 있습니다
이 앵커는 해당하는 ReferenceObject도 보유합니다 ReferenceObject에 파일 경로가 포함된 경우 이 앵커에서 기본 USDZ 파일 경로에 접근할 수 있습니다
다른 Data Provider와 마찬가지로 ObjectAnchor 업데이트를 수신할 수 있습니다 그런 다음 최신 추적 업데이트를 사용하여 객체에 감각적인 가상 콘텐츠를 추가할 수 있습니다 예를 들어 지구본 주변을 맴도는 물체와 사실적인 그림자를 추가하고 내부를 들여다볼 수도 있습니다
기기에 다운로드하여 사용해 볼 수 있는 샘플 앱도 게시할 예정입니다 추후 자세한 내용을 꼭 확인해 보세요 이제 visionOS의 기본인 공간 추적의 개선 사항을 살펴보겠습니다 ARKit은 공간 추적과 같은 정교한 알고리즘을 실행하기 위해 다양한 카메라와 센서를 사용합니다 사용자의 실제 위치에 조명이 충분하지 않으면 센서 데이터에 영향을 미치고 알고리즘이 원활하게 작동하지 않을 수 있습니다 예를 들어, 조명이 없는 어두운 방에 있으면 경험의 공간 추적 품질이 영향을 받을 수 있습니다
올해 Apple은 이러한 조명 변화에 대응하는 메커니즘을 추가했습니다 시스템이 저조도 조건이나 기타 물리적 요인으로 인해 추적이 제한되는 것을 감지하면 방향의 변화만 추적하고 공간에서의 위치는 추적하지 않습니다
이미 시스템 수준에서 방향 기반 추적이 앱에 적용되고 있기 때문입니다 즉, 까다로운 환경에서도 조명으로 인해 완전히 추적이 상실되는 것을 걱정할 필요가 없습니다
이러한 시나리오에 대비하여 경험을 조정하고자 한다면 추적 변경 사항을 알려주는 API를 사용해 보세요 예를 들어, 배치한 콘텐츠의 고정 위치는 그대로 두면서 콘텐츠를 매끄럽게 재배치하고 싶을 수 있습니다 앱이 전체 공간 추적에 완전히 의존하는 경우 사용자에게 더 밝은 환경으로 이동하여 경험을 다시 시작하도록 요청할 수 있습니다
SwiftUI를 사용하는 경우, 새로운 ‘worldTrackingLimitations’ 환경 값을 통해 이 표시를 사용할 수 있습니다 예를 들어, 위치 추적을 사용할 수 없을 때 콘텐츠 재정렬을 위해 이 값에 변경이 있는지 볼 수 있습니다
ARKit에서는 확장된 DeviceAnchor가 ‘trackingState’ 속성을 보유하므로 추적이 완전히 작동하는지 또는 방향 기반 추적으로만 제한되는지 알 수 있습니다 시스템이 방향 기반 추적으로 전환하는 경우 기존 공간 앵커는 ‘추적되지 않음’으로 표시될 수 있습니다 공간 추적이 복구되면 영구 앵커의 추적 상태가 복원됩니다
마지막으로 visionOS의 주요 입력 수단인 손 동작 추적의 개선 사항을 살펴보겠습니다 Apple은 visionOS를 출시하며 사용자의 손과 손가락을 추적하는 기능을 추가했습니다 앱은 이 정보를 사용하여 제스처를 감지하고 가상 콘텐츠를 사용자의 손에 고정할 수 있습니다
작년 Apple은 HandAnchors의 형태로 이 정보를 얻을 수 있는 2가지 방법을 마련했습니다 HandTrackingProvider에 최신 업데이트를 폴링하거나 HandAnchors가 제공될 때마다 비동기적으로 수신하는 것입니다 이제 HandTrackingProvider가 이 데이터를 디스플레이 속도로 전달할 수 있게 되었습니다 비동기식 HandAnchor 업데이트는 약간의 지연 시간이 있지만, 디스플레이에 맞춰 전송되는 빈도가 증가함에 따라 더 매끄러워질 것입니다 이 효과는 Apple Vision Pro를 착용한 상태에서 특히 두드러집니다 이제 ARKit이 가까운 미래에 특정 시점에 존재할 것으로 예상되는 HandAnchors를 예측할 수 있으므로 최소 지연으로 손 동작 추적 결과를 얻을 수 있습니다 앱 렌더링에 Compositor Services 또는 RealityKit을 사용하든 새로운 손 동작 예측 API를 활용하여 추적 결과를 더 빠르게 얻을 수 있습니다
예제를 살펴보겠습니다 Compositor Services를 사용하는 경우 visionOS에 새로 도입된 ‘추적 가능한 앵커 시간’을 타겟팅해야 합니다 이 타임스탬프에서 HandAnchors를 예측하면 콘텐츠를 가장 적절하게 등록하는 데 도움이 됩니다
이 타임스탬프를 초 단위로 변환하여 ARKit에 제공하면 전방을 정교하게 예측할 수 있습니다 이 앱은 Compositor Services를 사용하여 가상의 찻주전자를 렌더링합니다 예측된 HandAnchors를 사용하여 앵커가 적용된 찻주전자가 움직이더라도 손에 고정된 상태를 유지합니다 이 예측은 지연 시간이 짧은 예측이므로 정확도가 다소 떨어질 수 있습니다 Compositor Services 사용 렌더링에 관한 자세한 내용은 올해 세션인 ‘visionOS에서 Metal 콘텐츠를 패스스루와 통합하여 렌더링하기’에서 확인하세요 작년 세션인 ‘공간 컴퓨팅을 위한 ARKit 알아보기’에 있는 예제를 다시 살펴보는 것도 좋습니다
이 2가지 손 동작 추적 개선 사항은 다양한 사용 사례에서 유용합니다 디스플레이에 맞는 HandAnchor 업데이트는 지연 시간이 중요하지 않은 환경에서 제스처를 감지하고 부드러운 스트로크를 그리는 데 적합합니다 손 동작 예측은 유동성이 크게 중요하지 않으면서도 콘텐츠를 최대한 손에 밀착시키고 싶을 때 유용합니다
이 개선 사항은 RealityKit의 손 AnchorEntities에도 도입되었습니다
RealityKit을 사용하여 손 근처에 콘텐츠를 첨부하는 경우, 필요에 따라 ‘연속’ 또는 ‘예측’ 손 동작 추적 중에서 선택할 수 있습니다
자세한 예제는 새로운 세션인 ‘RealityKit으로 공간 드로잉 앱 빌드하기’에서 확인하세요 여기까지가 올해 ARKit의 새로운 기능입니다 먼저 공간 컴퓨팅 경험 향상에 유용할 수 있는 최신 개선 사항을 살펴봤습니다
또한 창의력을 한층 끌어올릴 수 있는 새로운 공간 추적 및 객체 추적 기능도 알아보았습니다 새로운 visionOS를 살펴볼 수 있는 놀라운 세션이 더 많이 있습니다 최신 ARKit을 활용하여 멋진 결과물을 세상에 선보이세요 시청해 주셔서 감사합니다
-
-
3:35 - RoomTrackingProvider
// RoomTrackingProvider @available(visionOS, introduced: 2.0) public final class RoomTrackingProvider: DataProvider, Sendable { /// The room which a person is currently in, if any. public var currentRoomAnchor: RoomAnchor? { get } /// An async sequence of all anchor updates. public var anchorUpdates: AnchorUpdateSequence<RoomAnchor> { get } ... }
-
4:20 - RoomAnchor
@available(visionOS, introduced: 2.0) public struct RoomAnchor: Anchor, Sendable, Equatable { /// True if this is the room which a person is currently in. public var isCurrentRoom: Bool { get } /// Get the geometry of the mesh in the anchor's coordinate system. public var geometry: MeshAnchor.Geometry { get } /// Get disjoint mesh geometries of a given classification. public func geometries(of classification: MeshAnchor.MeshClassification) -> [MeshAnchor.Geometry] /// True if this room contains the given point. public func contains(_ point: SIMD3<Float>) -> Bool /// Get the IDs of the plane anchors associated with this room. public var planeAnchorIDs: [UUID] { get } /// Get the IDs of the mesh anchors associated with this room. public var meshAnchorIDs: [UUID] { get } }
-
8:06 - Load Object Tracking referenceobject
// Object tracking Task { do { let url = URL(fileURLWithPath: "/path/to/globe.referenceobject") let referenceObject = try await ReferenceObject(from: url) let objectTracking = ObjectTrackingProvider(referenceObjects: [referenceObject]) } catch { // Handle reference object loading error. } ... }
-
8:27 - Run ARKitSession with ObjectTracking provider
let session = ARKitSession() Task { do { try await session.run([objectTracking]) } catch { // Handle session run error. } for await event in session.events { switch event { case .dataProviderStateChanged(_, newState: let newState, _): if newState == .running { // Ready to start processing anchor updates. } ... } } }
-
8:43 - ObjectAnchor
// ObjectAnchor @available(visionOS, introduced: 2.0) public struct ObjectAnchor: TrackableAnchor, Sendable, Equatable { /// An axis-aligned bounding box. public struct AxisAlignedBoundingBox: Sendable, Equatable { ... } /// The bounding box of this anchor. public var boundingBox: AxisAlignedBoundingBox { get } /// The reference object which this anchor corresponds to. public var referenceObject: ReferenceObject { get } }
-
11:03 - World Tracking - reacting to changes in lighting conditions
struct WellPreparedView: View { @Environment(\.worldTrackingLimitations) var worldTrackingLimitations var body: some View { ... .onChange(of: worldTrackingLimitations) { if worldTrackingLimitations.contains(.translation) { // Rearrange content when anchored positions are unavailable. } } } }
-
12:51 - Hands prediction
// Hands prediction func submitFrame(_ frame: LayerRenderer.Frame) { ... guard let drawable = frame.queryDrawable() else { return } // Get the trackable anchor time to target. let trackableAnchorTime = drawable.frameTiming.trackableAnchorTime // Convert the timestamp into units of seconds. let anchorPredictionTime = LayerRenderer.Clock.Instant.epoch.duration(to: trackableAnchorTime).timeInterval // Predict hand anchors for the time that provides best content registration. let (leftHand, rightHand) = handTracking.handAnchors(at: anchorPredictionTime) ... }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.