WebXR 평면 감지 모듈

편집자 초안,

이 문서에 대한 자세한 정보
이 버전:
https://immersive-web.github.io/plane-detection/
이슈 추적:
GitHub
편집자:
(Google)
(Meta)
이전 편집자:
(Google)
참여:
이슈 제출 (열린 이슈)
메일링 리스트 아카이브
W3C의 #immersive-web IRC

초록

평면 감지는 WebXR Device API의 기능을 확장하는 모듈이다. 앱이 네이티브 XR 기기에서 감지된 평면 집합을 수신할 수 있게 하여 더욱 몰입감 있는 경험을 제공할 수 있도록 한다.

이 문서의 상태

이 절에서는 이 문서가 발행된 시점의 상태를 설명한다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 http://www.w3.org/TR/의 W3C 기술 보고서 색인에서 확인할 수 있다.

이 문서는 몰입형 웹 워킹 그룹에서 편집자 초안으로 발행했다. 이 문서는 W3C 권고안이 되는 것을 목표로 한다. 이 명세에 대한 의견과 논평을 환영한다. 다음 GitHub 이슈를 이용하기 바란다. 논의 내용은 public-immersive-web-wg@w3.org 아카이브에서도 확인할 수 있다.

편집자 초안으로 발행되었다는 사실이 W3C와 그 회원의 승인을 의미하지는 않는다. 이 문서는 초안이며 언제든지 다른 문서에 의해 갱신되거나 대체되거나 폐기될 수 있다. 진행 중인 작업 이외의 것으로 이 문서를 인용하는 것은 적절하지 않다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했다. W3C는 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하며, 해당 페이지에는 특허 공개 지침도 포함되어 있다. 자신이 실제로 알고 있는 특허에 필수 청구항이 포함되어 있다고 판단하는 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 한다.

이 문서는 2025년 8월 18일 W3C 절차 문서의 적용을 받는다.

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"
};

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은 변경되지 않는다. 이는 평면 자세가 서로 다른 두 엔터티, 즉 planeSpacegetPose() 함수를 통해 자세를 계산할 기준이 되는 XRSpace에서 파생되는 속성이기 때문이다.

4. 감지된 평면 가져오기

4.1. XRPlaneSet

[Exposed=Window]
interface XRPlaneSet {
  readonly setlike<XRPlane>;
};

XRPlaneSetXRPlane의 컬렉션이다. 이는 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 기기가 결정한다.

이 메서드가 호출되면 사용자 에이전트는 다음 단계를 실행해야 한다:
  1. sessionthis로 둔다

  2. promisesession관련 렐름에서 생성한 새 Promise로 둔다.

  3. sessionended 값이 `true`이면, "InvalidStateError" DOMException으로 promise거부하고 promise을 반환한다.

  4. 방 캡처 완료가 `true`이면, "InvalidStateError" DOMException으로 promise거부하고 promise을 반환한다.

  5. plane-detection 기능 설명자가 sessionXR 기기에 있는 session모드활성화된 기능 목록포함되어 있지 않으면, "NotSupportedError" DOMException으로 promise거부하고 promise을 반환한다.

  6. sessionXR 기기가 수동 캡처를 지원하지 않거나 XRSystem이 방 캡처가 필요하지 않다고 판단하면:

    1. session방 캡처 완료를 `true`로 설정한다.

    2. promise이행한다.

    3. promise을 반환한다.

  7. 다음 단계를 수행하도록 태스크를 큐에 넣는다:

    1. sessionXR 기기에 있는 방 캡처 메서드를 호출하고 그 결과를 기다린 뒤, 해당 결과를 result에 할당한다.

    2. 다음 단계를 실행한다:

      result가 `true`인 경우:

      promise이행한다

      그렇지 않은 경우:

      "OperationError" DOMException으로 promise거부한다

    3. session방 캡처 완료를 `true`로 설정한다.

  8. promise을 반환한다.

frame평면을 갱신하려면 사용자 에이전트는 다음 단계를 실행해야 한다:
  1. sessionframe세션으로 둔다.

  2. devicesessionXR 기기로 둔다.

  3. plane-detection 기능 설명자가 devicesession 모드활성화된 기능 목록포함되어 있지 않으면 이 단계를 중단한다.

  4. trackedPlanesframe시간에 추적 중인 평면을 가져오기 위해 device네이티브 평면 감지 기능을 호출한 결과로 둔다.

  5. trackedPlanes의 각 native plane에 대해 다음을 실행한다:

    1. 필요한 경우 native planetrackedPlanes에 없는 것처럼 취급하고 다음 항목으로 계속한다. 이 방식으로 항목을 무시할지 판단하는 데 사용할 수 있는 기준은 § 6 개인정보 보호 및 보안 고려사항을 참조한다.

    2. session추적 중인 평면 집합native plane대응하는 객체 plane이 포함되어 있으면, plane, native plane, frame을 사용해 평면 객체 갱신 알고리즘을 호출하고 다음 항목으로 계속한다.

    3. planenative planeframe을 사용해 평면 객체 생성 알고리즘을 호출한 결과로 둔다.

    4. planesession추적 중인 평면 집합에 추가한다.

  6. 이 알고리즘을 호출하는 동안 생성되거나 갱신되지 않은 모든 객체를 session추적 중인 평면 집합에서 제거한다.

  7. framedetectedPlanes추적 중인 평면 집합으로 설정한다.

네이티브 평면 객체 native planeXRFrame frame에서 평면 객체를 생성하려면 사용자 에이전트는 다음 단계를 실행해야 한다:
  1. resultXRPlane의 새 인스턴스로 둔다.

  2. result네이티브 엔터티native plane으로 설정한다.

  3. resultplaneSpace세션framesession으로 설정하고, 네이티브 원점native plane의 네이티브 원점을 추적하도록 설정하여 생성한 새 XRSpace 객체로 설정한다.

  4. result, native plane, frame을 사용해 평면 객체 갱신 알고리즘을 호출한다.

  5. result를 반환한다.

이 방식으로 생성한 평면 객체 result는 전달된 네이티브 평면 객체 native plane대응한다고 한다.

네이티브 평면 객체 native planeXRFrame frame으로부터 plane 평면 객체를 갱신하려면 사용자 에이전트는 다음 단계를 실행해야 한다:
  1. plane프레임frame으로 설정한다.

  2. 기반 시스템이 native plane을 수직으로 분류한 경우 planeorientation"vertical"로 설정한다. 그렇지 않고 기반 시스템이 native plane을 수평으로 분류한 경우 planeorientation"horizontal"로 설정한다. 그 외의 경우에는 planeorientationnull로 설정한다.

  3. planepolygon을 네이티브 평면 다각형 표현의 차이를 고려하는 데 필요한 모든 변환을 수행하여 native plane의 다각형을 나타내는 새 꼭짓점 배열로 설정한다.

  4. planesemanticLabel의미 레이블이 포함된 새 문자열로 설정한다.

  5. 필요한 경우 § 6 개인정보 보호 및 보안 고려사항에 설명된 대로 planepolygon의 세부 수준을 낮춘다.

  6. planelastChangedTime시간으로 설정한다.

다음 예제는 애플리케이션이 감지된 평면에 대한 정보를 가져와 이를 처리하는 방법을 보여 준다. 평면을 그래픽으로 표현하는 데 사용할 수 있는 코드는 표시하지 않는다.

// `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가 주어지면, 사용자 에이전트는 PQ가 동일한 논리적 평면 객체에 대응하는지 기반 시스템에 질의할 수 있다. 또한 기반 시스템은 시간 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 평면 감지 명세의 설계에 기여했다:

적합성

문서 규칙

적합성 요구사항은 설명적 주장과 RFC 2119 용어를 조합하여 표현한다. 이 문서의 규범적 부분에 사용된 핵심어 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL”은 RFC 2119에 설명된 대로 해석해야 한다. 그러나 가독성을 위해 이 명세에서는 이러한 단어를 모두 대문자로 표시하지 않는다.

명시적으로 비규범적이라고 표시된 절, 예제 및 참고를 제외한 이 명세의 모든 텍스트는 규범적이다. [RFC2119]

이 명세의 예제는 “예를 들어”라는 말로 시작하거나 다음과 같이 class="example"을 사용하여 규범적 텍스트와 구분한다:

이는 비규범적 예제의 예이다.

비규범적 참고는 “참고”라는 말로 시작하며 다음과 같이 class="note"를 사용하여 규범적 텍스트와 구분한다:

참고: 이는 비규범적 참고이다.

적합 알고리즘

알고리즘의 일부로 명령형으로 표현된 요구사항 (예: "선행 공백 문자를 모두 제거한다" 또는 "false를 반환하고 이 단계를 중단한다")은 알고리즘을 도입할 때 사용한 핵심어 ("must", "should", "may" 등)의 의미에 따라 해석해야 한다.

알고리즘이나 구체적인 단계로 표현된 적합성 요구사항은 최종 결과가 동등하다면 어떠한 방식으로도 구현할 수 있다. 특히 이 명세에서 정의한 알고리즘은 이해하기 쉽도록 작성되었으며 성능을 목적으로 하지 않는다. 구현자는 최적화하는 것이 좋다.

색인

이 명세에서 정의하는 용어

참조로 정의되는 용어

참고문헌

규범적 참고문헌

[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv. Geometry Interfaces Module Level 1. URL: https://drafts.csswg.org/geometry/
[HR-TIME-3]
Yoav Weiss. 고해상도 시간. URL: https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; et al. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. RFC에서 요구사항 수준을 나타내기 위한 핵심어. 1997년 3월. 현행 최선의 관행. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/
[WEBXR]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR Device API. URL: https://immersive-web.github.io/webxr/

비규범적 참고문헌

[WEBXR-ANCHORS-MODULE]
Piotr Bialecki. WebXR 앵커 모듈. DR. URL: https://immersive-web.github.io/anchors/

IDL 색인

enum XRPlaneOrientation {
    "horizontal",
    "vertical"
};

[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;
};

[Exposed=Window]
interface XRPlaneSet {
  readonly setlike<XRPlane>;
};

partial interface XRFrame {
  readonly attribute XRPlaneSet detectedPlanes;
};

partial interface XRSession {
  Promise<undefined> initiateRoomCapture();
};