1. 소개
WebXR 앵커 모듈은 하위 XR 시스템이 세계에 대한 이해를 변경함에 따라 특정 3차원 포즈(위치와 방향)의 변경을 추적하도록 애플리케이션이 요청할 수 있게 한다. 이를 통해 애플리케이션은 장면에 배치한 가상 객체의 위치를 조정할 수 있으며, 배치된 객체가 사용자의 환경에 실제로 존재한다는 착시를 유지하는 데 도움이 된다.
1.1. 용어
이 문서에서 이해하는 포즈는 3D 공간에서의 위치와 방향을 의미한다.
이 문서에서 이해하는 앵커는 현실 세계에 대해 고정된 포즈를 추적하는 엔티티이며, 애플리케이션이 생성한다.
2. 초기화
2.1. 기능 기술자
애플리케이션이 세션 중 앵커 사용에 대한 관심을 표시하려면, 적절한 기능 기술자와 함께 세션을 요청해야 한다. 문자열 anchors는 이 모듈에서 앵커 기능을 위한 새로운 유효한 기능 기술자로 도입된다.
기기의 추적 시스템이 네이티브 앵커 기능을 노출하는 경우, 그 기기는 앵커 기능을
지원 가능하다. 인라인 XR 기기는 앵커 기능을
지원
가능한 것으로 취급해서는 안 된다. 사용자 에이전트는 모드가 "immersive-ar"와
같은
세션에 대해 앵커 기능 지원을 시도해야 한다.
참고: 앵커 기능 지원이 필수는 아니지만,
앵커는 AR 지원 애플리케이션이 좋은 사용자 경험을 제공하는 데 필요한 기본 기능 중 하나다. 따라서 사용자 에이전트가
"immersive-ar" 세션에 대해 이를 지원하는 것을 *강력히* 권장한다.
3. 앵커
3.1. XRAnchor
[SecureContext ,Exposed =Window ]interface {XRAnchor readonly attribute XRSpace ;anchorSpace Promise <DOMString >();requestPersistentHandle undefined (); };delete
XRAnchor는
다른 XRSpaces에
대해 앵커를 위치 지정하는 데 사용할 수 있는 anchorSpace를
포함한다.
deleted가
true로 설정되어 있을 때 이 속성에 접근하면,
사용자 에이전트는 InvalidStateError를
던져야 한다.
각 XRAnchor에는
처음에 false로 설정되는 연관된 deleted 불리언 값이 있다.
각 XRAnchor에는
연관된 native origin이 있다.
각 XRAnchor에는
연관된 session이 있다.
-
anchor를 새로운
XRAnchor로 둔다. -
anchor의 native origin을 native origin으로 설정한다.
-
anchor의 session을 session으로 설정한다.
-
anchor의 deleted를
false로 설정한다. -
anchor의
anchorSpace를, session을 anchor의 session으로 설정하고 native origin을 native origin으로 설정하여 생성한 새로운XRSpace객체로 설정한다. -
anchor를 반환한다.
requestPersistentHandle()
메서드가 XRAnchor
anchor에서 호출되면, 다음 단계를 실행해야 한다:
-
promise를 이
XRSystem의 관련 렐름에 있는 새로운 Promise로 둔다. -
anchor의 deleted가
true이면, promise를InvalidStateError로 거부하고, promise를 반환한 뒤, 이 단계를 중단한다. -
session을 anchor의 session으로 둔다.
-
session의 map of persistent anchors가 anchor 값을 포함하면, 다음 단계를 실행한다:
-
uuid를 session의 map of persistent anchors에서 anchor 값에 대한 매핑의 키로 둔다.
-
promise를 uuid로 해결한다.
-
promise를 반환한다.
-
이 단계를 중단한다.
-
-
uuid를 빈 문자열로 둔다.
-
UUID [RFC9562]를 문자열로 생성하고 이를 uuid에 추가한다.
-
uuid와 anchor를 session의 map of persistent anchors에 추가한다.
-
promise를 uuid로 해결한다.
-
promise를 반환한다.
참고: XRSystem이
고유 ID를 생성할 때, 그 ID는 고유해야 하며 현재 출처에만 알려져야 한다.
4. 앵커 생성
XRSession은
연관된 set of tracked anchors를 포함하도록 확장된다.
XRSession은
UUID 문자열을 키로 하고 XRAnchor에
매핑되는
연관된 map of persistent
anchors를 포함하도록 확장된다.
이 맵은 XR
device가 채우고 저장하며, origin에서 임의의 XRSession에
의해
생성되었고 아직 파괴되지 않은 영속 앵커의 집합으로만 제한된다.
이 맵의 크기는 사용자 에이전트가 결정한다. 사용자 에이전트는 어떤 이유로든 이 맵에서 항목을 삭제할 수 있다.
예를 들어 모든 출처의 모든 맵에 대한 시스템 앵커의 최대 수에 도달한 경우, 사용자 에이전트는 새로 요청된
앵커를 위한 공간을 만들기 위해 항목 하나를 해제할 수 있다.
XRSession은
XRAnchor 객체를 키로
하고
객체에 매핑되는 연관된 map of new anchors를 포함하도록 확장된다.
Promise<XRAnchor>
partial interface XRFrame {Promise <XRAnchor >(createAnchor XRRigidTransform ,pose XRSpace ); };space partial interface XRSession {readonly attribute FrozenArray <DOMString >;persistentAnchors Promise <XRAnchor >(restorePersistentAnchor DOMString );uuid Promise <undefined >(deletePersistentAnchor DOMString ); };uuid partial interface XRHitTestResult {Promise <XRAnchor >(); };createAnchor
XRHitTestResult는
연관된 native entity를 포함하도록 확장된다.
하위 시스템이 결과 계산을 일으킨 네이티브 엔티티에 대한 정보를 제공하지 않으면,
native entity가 null로 설정된 것으로 가정한다.
애플리케이션은 다음 두 가지 방법 중 하나로 앵커를 생성할 수 있다:
-
프레임에서 앵커 생성 - 생성된 앵커는 특정한 현실 세계 객체에 부착되지 않는다.
-
히트 테스트 결과에서 앵커 생성 - 하위 XR device가 이를 지원하는 경우, 생성된 앵커는 현실 세계 객체에 부착된다.
프레임에서 앵커를
생성하기 위해, 애플리케이션은 XRFrame의
createAnchor(pose, space)
메서드를 호출할 수 있다.
createAnchor(pose, space)
메서드가 XRFrame
frame에서 pose와 space와 함께 호출되면, 다음 단계를 실행해야 한다:
-
promise를 새로운 Promise로 둔다.
-
frame의 active 불리언이
false이면, promise를InvalidStateError로 거부하고, promise를 반환한 뒤, 이 단계를 중단한다. -
session을 frame의 session으로 둔다.
-
update anchors 알고리즘이 아직 없으면 session의 list of frame updates에 추가한다.
-
device를 session의 XR device로 둔다.
-
effective origin을 space의 effective origin으로 둔다.
-
anchor native origin을, frame의 time에 effective origin에 대해 표현된 것으로 해석한 pose를 사용하여 새 앵커를 생성하는 device 호출에서 반환된 새로운 네이티브 원점으로 둔다.
-
anchor native origin과 session을 사용하여 새 앵커 객체 생성 anchor를 수행한다.
-
anchor를 session의 set of tracked anchors에 추가한다.
-
anchor에서 promise로의 매핑을 session의 map of new anchors에 추가한다.
-
promise를 반환한다.
참고: 각 createAnchor(pose, space)
호출이 반환하는 앵커가 추적하는 물리적 원점이, 해당 메서드가 호출된 프레임이 나타내는 시점의 space 내
pose의 물리적 위치와 최대한 가깝게 정렬되도록 보장하는 것은 사용자 에이전트의 책임이다.
구체적으로 이는 동적으로 변경되는 공간에 대해 사용자 에이전트가 앱이 지정한 시점에서 그러한 공간의 네이티브
원점을 캡처하려고 시도해야 함을 의미한다. 이 텍스트는 비규범적이지만, 사양 작성자와 기여자의 의도를 표현하므로
서로 다른 공급자 간의 일관된 동작을 보장하기 위해 구현에서 이를 따르는 것을 강력히 권장한다.
persistentAnchors는
알려진 영속 앵커의 목록을 반환한다. 이 목록은 map of persistent anchors의 키를 반영해야 한다.
restorePersistentAnchor(uuid)
메서드가 XRSession
session에서 uuid와 함께 호출되면, 다음 단계를 실행해야 한다:
-
promise를 이
XRSystem의 관련 렐름에 있는 새로운 Promise로 둔다. -
session의 map of persistent anchors에 uuid에서
XRAnchor로의 매핑이 없으면, promise를InvalidStateError로 거부하고, promise를 반환한 뒤, 이 단계를 중단한다. -
session의
ended값이 `true`이면, promise를InvalidStateError로 거부하고, promise를 반환한 뒤, 이 단계를 중단한다. -
anchor를 session의 map of persistent anchors에서 uuid에 대한 매핑의 값으로 둔다.
-
session의 map of new anchors가 anchor에서 promise로의 매핑을 포함하면, 그 promise를
InvalidStateError로 거부하고, promise를 반환한 뒤, 이 단계를 중단한다. -
session의 map of new anchors가 사용자 에이전트 최대 크기에 도달했으면, promise를
InvalidStateError로 거부하고, promise를 반환한 뒤, 이 단계를 중단한다. -
anchor를 session의 set of tracked anchors에 추가한다.
-
anchor에서 promise로의 매핑을 session의 map of new anchors에 추가한다.
-
promise를 반환한다.
deletePersistentAnchor()
메서드가 XRSession
session에서 uuid와 함께 호출되면, 다음 단계를 실행해야 한다:
-
promise를 이
XRSystem의 관련 렐름에 있는 새로운 Promise로 둔다. -
session의 map of persistent anchors에 anchor로의 매핑이 없으면, promise를
InvalidStateError로 거부하고, promise를 반환한 뒤, 이 단계를 중단한다. -
anchor를 session의 map of persistent anchors에서 uuid에 대한 매핑의 값으로 둔다.
-
session의 map of persistent anchors에서 매핑을 제거한다.
-
anchor에서
delete()를 호출한다. -
promise를 반환한다.
히트 테스트
결과에서 앵커를 생성하기 위해, 애플리케이션은
XRHitTestResult의
createAnchor()
메서드를 호출할 수 있다.
createAnchor()
메서드가 XRHitTestResult
hitTestResult에서 호출되면, 다음 단계를 실행해야 한다:
-
promise를 새로운 Promise로 둔다.
-
frame을 hitTestResult의 frame으로 둔다.
-
frame의 active 불리언이
false이면, promise를InvalidStateError로 거부하고, promise를 반환한 뒤, 이 단계를 중단한다. -
session을 frame의 session으로 둔다.
-
update anchors 알고리즘이 아직 없으면 session의 list of frame updates에 추가한다.
-
device를 session의 XR device로 둔다.
-
nativeEntity를 hitTestResult의 native entity로 둔다.
-
anchor native origin을, frame의 time에 hitTestResult의 native origin에 위치하고 nativeEntity에 attached된 새 앵커를 생성하는 device 호출에서 반환된 새로운 네이티브 원점으로 둔다.
-
anchor native origin과 session을 사용하여 새 앵커 객체 생성 anchor를 수행한다.
-
anchor를 session의 set of tracked anchors에 추가한다.
-
anchor에서 promise로의 매핑을 session의 map of new anchors에 추가한다.
-
promise를 반환한다.
참고: createAnchor(pose, space)
메서드에 있는 동일한 설명이 여기에도 적용된다.
세션의 "list of frame updates"에는 순서를 지정하는 방법이 필요할 수 있다. 일부 알고리즘은 다른 알고리즘에 의존할 수 있다.
5. 앵커 업데이트
[Exposed =Window ]interface {XRAnchorSet readonly setlike <XRAnchor >; };partial interface XRFrame { [SameObject ]readonly attribute XRAnchorSet ; };trackedAnchors
XRAnchorSet
인터페이스는 앵커 컬렉션을 노출하는 방법으로 도입된다.
XRFrame은
프레임에서 아직 추적 중인 모든 앵커를 포함하는 trackedAnchors
속성을 포함하도록 확장된다. XRFrame
생성 시, 이 집합은 처음에는 비어 있으며 update
anchors 알고리즘에 의해 채워진다.
-
session을 frame의 session으로 둔다.
-
device를 session의 XR device로 둔다.
-
session의 set of tracked anchors에 있는 각 anchor에 대해 다음을 실행한다:
-
anchor의 native origin 정보에 대해 device의 추적 시스템에 질의한다.
-
device의 추적 시스템이 더 이상 anchor를 tracks하지 않으면, 다음 단계를 실행한다:
-
anchor를 session의 set of tracked anchors에서 제거한다.
-
session의 map of new anchors가 anchor에서 promise로의 매핑을 포함하면, promise를 거부하고 매핑을 제거한다.
-
session의 set of tracked anchors에 있는 다음 항목으로 계속한다.
-
-
anchor를 frame의
trackedAnchors집합에 추가한다. -
session의 map of new anchors가 anchor에서 promise로의 매핑을 포함하면, promise를 anchor로 해결하고 매핑을 제거한다.
-
6. 앵커 제거
애플리케이션이 더 이상 앵커 업데이트 수신에 관심이 없으면, delete()를
호출하여 앵커를 삭제할 수 있다.
delete()
메서드가 XRAnchor
anchor에서 호출되면, 다음 단계를 실행하여 앵커를 삭제해야 한다:
-
anchor의 deleted가
true이면, 이 단계를 중단한다. -
anchor의
anchorSpace를null로 설정한다. -
anchor의 deleted를
true로 설정한다. -
session을 anchor의 session으로 둔다.
-
device를 session의 XR device로 둔다.
-
native origin을 anchor의 native origin으로 둔다.
-
device의 추적 시스템에 native origin을 더 이상 추적하지 않도록 알린다.
-
anchor를 session의 set of tracked anchors에서 제거한다.
7. 네이티브 기기 개념
사용자 에이전트가 앵커 API를 구현할 수 있으려면, 하위 XR 기기가 이 기능에 대한 네이티브 지원을 제공해야 한다. 이 절은 하위 XR 시스템에 부과되는 요구사항을 설명하며, 다양한 프레임워크/기기 위에서 앵커 API를 구현할 수 있도록 필연적으로 덜 명세되어 있다.
7.1. 네이티브 앵커
하위 XR device는 앵커와 관련된 다음 기능을 지원하는 경우 지원 가능한 anchors 기능이다:
-
다음 요구사항과 함께 네이티브 앵커 생성이 가능하다:
-
네이티브 앵커 API는 앵커의 포즈를 현실 세계에 대해 고정된 것처럼 유지하려고 시도한다.
-
특정 시간
t에서 새로 생성된 앵커의 포즈를 받는다. -
새로 생성된 앵커를 주어진 엔티티에 부착하려는 의도를 표현하기 위해 선택적으로 네이티브 엔티티 정보를 받는다. 하위 XR 시스템이 앵커를 네이티브 엔티티에 부착하는 것을 지원하지 않으면(즉 네이티브 엔티티를 받지 않으면), 새로 생성된 앵커는 자유 부동 상태가 된다.
-
사용자 에이전트가 native origin으로 취급할 수 있는 결과를 반환한다.
-
-
네이티브 앵커는 하위 XR 시스템에 의해 지속적으로 tracked되며 일반적으로 최신 상태를 질의할 수 있다. 그러나 위치를 알 수 없는 프레임이 있을 수 있으며, 따라서 사용자 에이전트는 일정 시간 동안 포즈를 위치 지정할 수 없다고 보고할 수 있다. 하위 시스템이 네이티브 앵커의 위치를 다시는 알 수 없다고 판단하면, 네이티브 앵커가 더 이상 추적되지 않는다고 보고해야 한다.
-
선택적으로, 네이티브 앵커는 네이티브 엔티티에 attached될 수 있다. 네이티브 엔티티에 부착된 네이티브 앵커는 그 위치를 자신이 부착된 엔티티에 대해 고정된 상태로 유지하려고 시도한다(자유 부동 앵커의 경우 현실 세계에 대해 고정되는 것과 반대). 기기가 앵커가 부착된 객체의 포즈가 변경되었음을 감지하면, 앵커도 그에 따라 업데이트된다. 이는 객체 자체가 움직였음을 의미하지 않는다. 시스템의 해당 위치에 대한 이해가 변경된 것일 수 있다. 하위 시스템이 움직이는 객체를 추적할 수 있다면, 움직이는 객체에 부착된 네이티브 앵커도 함께 업데이트되어야 한다.
하위 기기가 네이티브 앵커를 지원하지 않는 경우, 사용자 에이전트는 에뮬레이트된 네이티브 앵커를 통해 앵커 API를 구현하기로 결정할 수 있다.
이 접근 방식은 앵커가 일단 생성되면 포즈가 절대 변경되지 않으며, 그 포즈가 XRFrame의
createAnchor(pose, space)
또는 XRHitTestResult의
createAnchor()와
같은
앵커 생성 메서드에 애플리케이션이 전달한 포즈라고 가정한다.
참고: 에뮬레이트된 네이티브 앵커
접근 방식은 애플리케이션이 앵커 기능을 직접 에뮬레이트하는 것과 동등하며, 애플리케이션이 처리해야 하는 서로 다른
경우의 수를 줄이는 데 도움이 될 수 있다. 또한 애플리케이션이 "immersive-ar"
및 "immersive-vr"
세션에 대해 같은 코드를 재사용할 수 있게 할 수도 있다.
8. 개인정보 보호 및 보안 고려사항
앵커 API는 사용자 환경에 대한 정보 접근을 직접 노출하지 않는다. 세션이 hit-test 지원이 활성화된 상태로 생성되었고 기기가 움직이는 객체 추적을 지원하는 경우, 애플리케이션은 예를 들어 주변으로 운반되는 객체의 앵커 포즈 변화를 관찰하여 사용자 환경의 레이아웃을 추론할 수 있을 수 있다. 이는 hit-testing API와 유사한 수준의 사용자 환경 정보를 제공한다. 앵커 기능은 XR 세션 생성 시 선언되어야 하며, 이를 통해 사용자 에이전트는 웹사이트가 앵커 API 사용을 허용하는 것의 잠재적 개인정보 보호 영향을 사용자에게 알릴 수 있다.
움직이는 일반 객체 추적을 지원하는 기기를 나는 알지 못한다. 이런 기기를 사양에서 전혀 고려해야 하는가? 그런 기기의 예가 있는가?
9. 감사의 말
다음 개인들이 WebXR Anchors 사양의 설계에 기여했다: