1. 소개
2. 초기화
2.1. 기능 설명자
애플리케이션이 세션 중 평면 감지를 사용하는 데 관심이 있음을 알리려면 해당 세션을 적절한 기능 설명자와 함께 요청해야 한다. 문자열 plane-detection은 이 모듈에서 평면 감지 기능을 위한 새로운 유효 기능 설명자로 도입된다.
기기의 추적 시스템이 네이티브 평면 감지 기능을 노출하는 경우 해당 기기는 평면 감지 기능을 지원할 수 있다. 인라인 XR 기기는 평면 감지 기능을 지원할 수 있는 것으로 취급해서는 안 된다.
평면 감지 기능을 활성화하여 세션을 생성할 때는 평면 갱신 알고리즘을 해당 세션의 프레임 갱신 목록에 추가해야 한다.
const session= await navigator. xr. requestSession( "immersive-ar" , { requiredFeatures: [ "plane-detection" ] });
3. 평면
3.1. XRPlaneOrientation
enum {XRPlaneOrientation "horizontal" ,"vertical" };
-
"horizontal"평면 방향은 평면이 주로 수평 방향임을 나타낸다(기반 플랫폼의 규칙에 따름). -
"vertical"평면 방향은 평면이 주로 수직 방향임을 나타낸다(기반 플랫폼의 규칙에 따름).
3.2. XRPlane
[Exposed =Window ]interface { [XRPlane SameObject ]readonly attribute XRSpace ;planeSpace readonly attribute FrozenArray <DOMPointReadOnly >;polygon readonly attribute XRPlaneOrientation ?;orientation readonly attribute DOMHighResTimeStamp ;lastChangedTime readonly attribute DOMString ?; };semanticLabel
XRPlane은
기반 XR 시스템에서 감지한 하나의 평평한 표면을 나타낸다.
planeSpace는
평면의 좌표계를 설정하는 XRSpace이다.
planeSpace의
네이티브 원점은 평면의 중심을 추적한다. 기반 XR 시스템은 평면 중심의 정확한 의미를 정의한다.
planeSpace에서
정의하는 좌표계의 Y축은 평면의 법선 벡터를 나타내야 한다.
각 XRPlane에는
연관된 네이티브 엔터티가 있다.
각 XRPlane에는
연관된 프레임이 있다.
polygon은
평면의 형태를 설명하는 꼭짓점 배열이다. 이 꼭짓점들은 다각형 가장자리의 점들로 이루어진 폐곡선 형태로 반환되며, planeSpace에서
정의하는 좌표계로 표현된다.
각 꼭짓점의 Y 좌표는 0.0이어야 한다.
semanticLabel
속성은 다각형의 의미 레이블을 설명하는 문자열이다.
의미 정보가 없는 경우 이 문자열은 null 또는 빈 문자열일
수 있다. XRSystem은
자신이 알고 있는 의미 레이블로 이 속성을 채우는
것이 좋다.
의미 레이블은
XRSystem이
알고 있는 XRPlane의 현실
세계 이름을 설명하는
ASCII 소문자 DOMString이다.
의미 레이블 목록은 의미 레이블 레지스트리에 정의되어 있다.
orientation은
기반 XR 시스템에서 분류한 평면의 방향을 설명한다. 기반 XR 시스템이 방향을 "horizontal"
또는 "vertical"로
분류할 수 없는 경우 이 속성은 null로 설정된다.
lastChangedTime은
평면 속성 중 하나가 마지막으로 변경된 시간이다.
참고: 평면의 자세는 평면
속성으로 간주하지 않으므로 평면 자세를 갱신해도 lastChangedTime은
변경되지 않는다. 이는 평면 자세가 서로 다른 두 엔터티, 즉 planeSpace와
getPose()
함수를 통해 자세를 계산할 기준이 되는 XRSpace에서
파생되는 속성이기 때문이다.
4. 감지된 평면 가져오기
4.1. XRPlaneSet
[Exposed =Window ]interface {XRPlaneSet readonly setlike <XRPlane >; };
XRPlaneSet은
XRPlane의 컬렉션이다.
이는
XRFrame에서
감지된 평면 컬렉션을 가져오는 주된 메커니즘이다.
partial interface XRFrame {readonly attribute XRPlaneSet ; };detectedPlanes
XRFrame은
프레임에서 계속 추적 중인 모든 평면을 포함하는 detectedPlanes
속성을 포함하도록 확장된다. 이 집합은 처음에는 비어 있으며 평면
갱신 알고리즘에 의해 채워진다. 프레임이 활성 상태가 아닐 때
이 속성에 접근하면 사용자 에이전트는 InvalidStateError를
던져야 한다.
partial interface XRSession {Promise <undefined >(); };initiateRoomCapture
XRSession은
연관된 추적 중인 평면 집합을 포함하도록 확장되며, 이 집합은 처음에는
비어 있다. 집합의 요소는 XRPlane 타입이다.
XRSession은
처음에는 false인 불리언 방 캡처 완료를 포함하도록 확장된다.
XR 기기가 수동 캡처를 지원하는 경우, 해당 기기에는 불리언을 반환하는 비동기 방 캡처 메서드가 있다.
XRSession은
지원되는 경우 XR
기기에 현재 방의 배치를 캡처하도록 요청하는 initiateRoomCapture
메서드도 포함하도록 확장된다. 이 캡처가 추적 중인
평면 집합을 대체할지 보강할지는 XR
기기가 결정한다.
-
session을 this로 둔다
-
session의
ended값이 `true`이면, "InvalidStateError"DOMException으로 promise을 거부하고 promise을 반환한다. -
방 캡처 완료가 `true`이면, "
InvalidStateError"DOMException으로 promise을 거부하고 promise을 반환한다. -
plane-detection 기능 설명자가 session의 XR 기기에 있는 session의 모드용 활성화된 기능 목록에 포함되어 있지 않으면, "
NotSupportedError"DOMException으로 promise을 거부하고 promise을 반환한다. -
session의 XR 기기가 수동 캡처를 지원하지 않거나
XRSystem이 방 캡처가 필요하지 않다고 판단하면: -
다음 단계를 수행하도록 태스크를 큐에 넣는다:
-
session의 XR 기기에 있는 방 캡처 메서드를 호출하고 그 결과를 기다린 뒤, 해당 결과를 result에 할당한다.
-
다음 단계를 실행한다:
- result가 `true`인 경우:
-
promise을 이행한다
- 그렇지 않은 경우:
-
"
OperationError"DOMException으로 promise을 거부한다
-
session의 방 캡처 완료를 `true`로 설정한다.
-
-
promise을 반환한다.
-
session을 frame의 세션으로 둔다.
-
device를 session의 XR 기기로 둔다.
-
plane-detection 기능 설명자가 device의 session 모드용 활성화된 기능 목록에 포함되어 있지 않으면 이 단계를 중단한다.
-
trackedPlanes를 frame의 시간에 추적 중인 평면을 가져오기 위해 device의 네이티브 평면 감지 기능을 호출한 결과로 둔다.
-
trackedPlanes의 각 native plane에 대해 다음을 실행한다:
-
필요한 경우 native plane이 trackedPlanes에 없는 것처럼 취급하고 다음 항목으로 계속한다. 이 방식으로 항목을 무시할지 판단하는 데 사용할 수 있는 기준은 § 6 개인정보 보호 및 보안 고려사항을 참조한다.
-
session의 추적 중인 평면 집합에 native plane에 대응하는 객체 plane이 포함되어 있으면, plane, native plane, frame을 사용해 평면 객체 갱신 알고리즘을 호출하고 다음 항목으로 계속한다.
-
plane을 native plane과 frame을 사용해 평면 객체 생성 알고리즘을 호출한 결과로 둔다.
-
plane을 session의 추적 중인 평면 집합에 추가한다.
-
-
이 알고리즘을 호출하는 동안 생성되거나 갱신되지 않은 모든 객체를 session의 추적 중인 평면 집합에서 제거한다.
-
frame의
detectedPlanes를 추적 중인 평면 집합으로 설정한다.
XRFrame
frame에서 평면
객체를 생성하려면 사용자 에이전트는 다음 단계를 실행해야 한다:
-
result를
XRPlane의 새 인스턴스로 둔다. -
result의 네이티브 엔터티를 native plane으로 설정한다.
-
result의
planeSpace를 세션은 frame의session으로 설정하고, 네이티브 원점은 native plane의 네이티브 원점을 추적하도록 설정하여 생성한 새XRSpace객체로 설정한다. -
result, native plane, frame을 사용해 평면 객체 갱신 알고리즘을 호출한다.
-
result를 반환한다.
이 방식으로 생성한 평면 객체 result는 전달된 네이티브 평면 객체 native plane에 대응한다고 한다.
XRFrame
frame으로부터 plane 평면
객체를 갱신하려면 사용자 에이전트는 다음 단계를 실행해야 한다:
-
plane의 프레임을 frame으로 설정한다.
-
기반 시스템이 native plane을 수직으로 분류한 경우 plane의
orientation을"vertical"로 설정한다. 그렇지 않고 기반 시스템이 native plane을 수평으로 분류한 경우 plane의orientation을"horizontal"로 설정한다. 그 외의 경우에는 plane의orientation을null로 설정한다. -
plane의
polygon을 네이티브 평면 다각형 표현의 차이를 고려하는 데 필요한 모든 변환을 수행하여 native plane의 다각형을 나타내는 새 꼭짓점 배열로 설정한다. -
plane의
semanticLabel을 의미 레이블이 포함된 새 문자열로 설정한다. -
필요한 경우 § 6 개인정보 보호 및 보안 고려사항에 설명된 대로 plane의
polygon의 세부 수준을 낮춘다. -
plane의
lastChangedTime을 시간으로 설정한다.
다음 예제는 애플리케이션이 감지된 평면에 대한 정보를 가져와 이를 처리하는 방법을 보여 준다. 평면을 그래픽으로 표현하는 데 사용할 수 있는 코드는 표시하지 않는다.
// `planes`는 애플리케이션이 알고 있는 감지된 모든 평면과 // 해당 평면이 갱신된 타임스탬프를 추적한다. 처음에는 빈 맵이다. const planes= Map(); function onXRFrame( timestamp, frame) { const detectedPlanes= frame. detectedPlanes; // 먼저, 알고 있던 평면 중 더 이상 추적되지 않는 평면이 있는지 확인한다: for ( const [ plane, timestamp] of planes) { if ( ! detectedPlanes. has( plane)) { // 제거된 평면을 처리한다. `plane`은 이전 프레임에는 있었지만 // 이제 더 이상 추적되지 않는다. // 평면이 더 이상 존재하지 않음을 알았으므로 맵에서 제거한다: planes. delete ( plane); } } // 그런 다음 아직 추적 중인 모든 평면을 처리한다. // 여기에는 이전에 확인한 추적 중인 평면(갱신되었을 수 있음)과 // 새 평면이 모두 포함된다. detectedPlanes. forEach( plane=> { if ( planes. has( plane)) { // 이전에 확인한 평면을 처리한다: if ( plane. lastChangedTime> planes. get( plane)) { // 갱신된, 이전에 확인한 평면을 처리한다. // 이는 평면의 속성 중 하나가 이전과 달라졌음을 의미하며, // 대부분의 경우 다각형이 변경된 것이다. ... // 평면을 렌더링하거나 렌더링을 준비하는 등의 작업을 한다. // 평면을 갱신한 시간을 갱신한다: planes. set( plane, plane. lastChangedTime); } else { // 현재 프레임에서 갱신되지 않은, 이전에 확인한 평면을 처리한다. // 다른 공간에 대한 평면의 상대 자세는 변경되었을 수 있다. } } else { // 새 평면을 처리한다. // 평면을 갱신한 시간을 설정한다: planes. set( plane, plane. lastChangedTime); } // 평면을 이전에 확인했는지 또는 갱신했는지와 관계없이 // 해당 평면의 자세는 변경되었을 수 있다: const planePose= frame. getPose( plane. planeSpace, xrReferenceSpace); }); frame. session. requestAnimationFrame( onXRFrame); }
5. 네이티브 기기 개념
5.1. 네이티브 평면 감지
평면 감지 API는 사용자의 환경에서 감지된 평평한 표면에 대한 정보를 제공한다. 이
명세에서는 사용자 에이전트가 평면 감지 기능을 구현하기 위해 기반 플랫폼에서 제공하는 네이티브 평면 감지 기능에 의존할 수 있다고
가정한다. 구체적으로 기반 XR 기기는 특정 XRFrame의
시간에 해당하는 시점에 추적 중인 모든 평면을 질의하는 방법을 제공해야 한다.
또한 네이티브 평면
객체라고 하는 추적 중인 평면은
여러 프레임에서 자신의 식별성을 유지한다고 가정한다. 즉, 시간
t0에 기반 시스템이 반환한 평면 객체 P와 시간
t1에 기반 시스템이 반환한 평면 객체 Q가 주어지면, 사용자 에이전트는
P와 Q가 동일한 논리적 평면 객체에 대응하는지 기반 시스템에 질의할 수 있다. 또한 기반 시스템은
시간 t의 자세 위치를 질의하는 데 사용할 수 있는 네이티브 원점을 제공할 것으로 예상되지만, 평면의 자세가 항상
알려진다는 보장은 없다(예를 들어 계속 추적 중이지만 특정 시점에는 위치를 결정할 수 없는 평면). 또한 네이티브
평면 객체는 감지된 평면의 대략적인 형태를 설명하는 다각형을 노출해야 한다.
또한 기반 시스템은
XRAnchor
생성을 위해 네이티브 평면을 네이티브 엔터티로 인식해야 한다.
자세한 내용은 WebXR Anchors Module
§ native-anchor 절을 참조한다.
6. 개인정보 보호 및 보안 고려사항
평면 감지 API는 사용자의 물리적 환경에 대한 정보를 노출한다. 사용자 에이전트가 선택하는 경우 노출되는 평면
정보(예: 평면의 다각형)를 제한할 수 있다. 사용자 에이전트가 노출되는 정보를 줄일 수 있는 몇 가지 방법은 다음과 같다:
평면 객체 갱신
알고리즘에서 평면 다각형의 세부 수준을 낮추기
(예: 꼭짓점 수를 줄이거나 꼭짓점 좌표를 반올림 / 양자화하기),
또는 평면 갱신 알고리즘의
trackedPlanes 컬렉션에 해당 평면 객체가 없는 것처럼 동작하여 평면을 완전히 제거하기
(예를 들어 감지된 평면이 노출하기에 너무 작거나 지나치게 상세하고, 사용자 에이전트가 평면에 노출되는 세부 정보를
줄이는 메커니즘을 구현하지 않은 경우 수행할 수 있음). 평면의 자세
(planeSpace에서
가져올 수 있음)도 양자화할 수 있다.
평면 감지 API의 개념은 [webxr-anchors-module] 명세에서 노출하는 메서드에 사용될 수 있으므로 WebXR Anchors Module과 관련된 개인정보 보호 및 보안 고려사항 중 일부가 여기에도 적용된다. 자세한 내용은 WebXR Anchors Module § privacy-security 절을 참조한다.
평면 감지 API가 WebXR Device API를 확장하는 방식으로 인해 WebXR Device API § 13. 보안, 개인정보 보호 및 편의성 고려사항 절도 WebXR Plane Detection Module에서 노출하는 기능에 적용된다.
7. 감사의 말
다음 사람들은 WebXR 평면 감지 명세의 설계에 기여했다: