WebXR 히트 테스트 모듈

W3C 작업 초안,

이 문서에 대한 더 자세한 정보
이 버전:
https://www.w3.org/TR/2025/WD-webxr-hit-test-1-20251211/
최신 공개 버전:
https://www.w3.org/TR/webxr-hit-test-1/
편집자 초안:
https://immersive-web.github.io/hit-test/
이전 버전:
이력:
https://www.w3.org/standards/history/webxr-hit-test-1/
피드백:
GitHub
사양 내 인라인
편집자:
(Google)
이전 편집자:
(Google)
참여:
이슈 제출 (열린 이슈)
메일링 리스트 아카이브
W3C의 #immersive-web IRC

초록

WebXR Device API와 함께 사용하기 위해 실제 세계 기하 구조에 대해 히트 테스트를 수행하는 방법을 설명한다.

이 문서의 상태

이 절은 이 문서가 발행된 시점의 상태를 설명한다. 현재 W3C 발행물 목록 및 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있다.

Immersive Web 작업 그룹은 그룹에서 아직 처리하지 않은 모든 버그 보고서 목록을 관리한다. 이 초안은 작업 그룹에서 아직 논의해야 할 보류 중인 이슈 중 일부를 강조한다. 이러한 이슈의 결과에 대해서는, 그것이 유효한지 여부를 포함해 어떠한 결정도 내려지지 않았다. 미해결 이슈에 대한 제안된 명세 텍스트가 포함된 풀 리퀘스트를 강력히 권장한다.

이 문서는 Immersive Web 작업 그룹에 의해 Recommendation 트랙을 사용한 작업 초안으로 발행되었다. 이 문서는 W3C Recommendation이 되는 것을 목적으로 한다.

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

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

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

1. 소개

이 모듈은 WebXR 애플리케이션이 사용자의 실제 세계 환경으로 광선을 쏘고, XR 장치가 아는 최선의 범위에서, 그 광선이 물리적 객체와 교차한 지점 및 교차한 표면의 방향을 다시 보고하도록 허용하는 메커니즘을 설명한다. 이를 통해 가상 객체를 해당 표면과 정렬되도록 배치할 수 있다. 예를 들어 객체를 바닥 위에 사실적으로 배치하거나 벽에 부착할 수 있다. 히트 테스트 API는 WebXR Device API의 확장이며 WebXR Augmented Reality Module 위에 구축된다.

1.1. 용어

이 문서에서 이해하는 히트 테스트는 이상화된 수학적 광선 (반직선)이 기반 증강 현실 하드웨어 및 소프트웨어가 이해하는 실제 세계와 교차하는지를 확인하는 행위이다. API를 사용하는 애플리케이션이 생성한 가상 객체에 대한 광선 교차는 명시적으로 히트 테스트 API의 범위 밖이다.

2. 초기화

2.1. 기능 설명자

애플리케이션이 세션 중 히트 테스트 수행에 대한 관심을 신호하기 위해서는, 해당 세션이 적절한 기능 설명자와 함께 요청되어야 한다. 문자열 hit-test는 이 모듈에 의해 히트 테스트 기능을 위한 새로운 유효한 기능 설명자로 도입된다.

장치가 지원할 수 있는 히트 테스트 기능은 장치가 네이티브 히트 테스트 기능을 노출하는 경우이다. inline XR device는 히트 테스트 기능을 지원할 수 있는 것으로 취급되어서는 안 된다.

히트 테스트 기능은 기능 정책의 적용을 받으며, 요청 문서의 출처에서 "xr-spatial-tracking" 정책이 허용되어 있어야 한다.

3. 히트 테스트 옵션

3.1. XRHitTestTrackableType

XRHitTestTrackableType enum은 히트 테스트 소스 생성 목적으로 사용될 수 있는 엔티티 타입을 지정한다.

enum XRHitTestTrackableType {
  "point",
  "plane",
  "mesh"
};

3.2. XRHitTestOptionsInit

XRHitTestOptionsInit dictionary는 수행되는 히트 테스트의 동작에 영향을 주는 구성 가능한 값들의 집합을 나타낸다.

dictionary XRHitTestOptionsInit {
  required XRSpace space;
  sequence<XRHitTestTrackableType> entityTypes;
  XRRay offsetRay;
};

space dictionary 멤버는 XRSpace를 지정하며, 이는 offsetRay가 상대적으로 지정되는 기준이다.

entityTypes dictionary 멤버는 히트 테스트 결과를 계산하는 데 사용될 XRHitTestTrackableTypes의 배열을 지정한다.

offsetRay dictionary 멤버는 히트 테스트를 수행하는 데 사용될 XRRay를 지정한다. offsetRayspace가 정의한 좌표계로 표현된 것처럼 해석된다.

XRHitTestOptionsInit dictionary에는 연관된 effective entityTypes가 있으며, 이는 dictionary 생성 시 제공된 경우 entityTypes로 설정된다. 생성 시 entityTypes가 제공되지 않은 경우, effective entityTypes는 단일 요소 "plane"를 포함하는 배열로 설정된다.

XRHitTestOptionsInit dictionary에는 연관된 effective offsetRay가 있으며, 이는 dictionary 생성 시 제공된 경우 offsetRay로 설정된다. 생성 시 offsetRay가 제공되지 않은 경우, effective offsetRay는 매개변수 없이 XRRay()를 호출하여 생성된 XRRay로 설정된다.

3.3. XRTransientInputHitTestOptionsInit

XRTransientInputHitTestOptionsInit dictionary는 수행되는 transient input에 대한 히트 테스트의 동작에 영향을 주는 구성 가능한 값들의 집합을 나타낸다.

dictionary XRTransientInputHitTestOptionsInit {
  required DOMString profile;
  sequence<XRHitTestTrackableType> entityTypes;
  XRRay offsetRay;
};

profile dictionary 멤버는 히트 테스트 결과를 계산하는 데 사용될 transient input source의 input profile name을 지정한다.

entityTypes dictionary 멤버는 히트 테스트의 결과를 계산하는 데 사용될 XRHitTestTrackableTypes의 배열을 지정한다.

offsetRay dictionary 멤버는 히트 테스트를 수행하는 데 사용될 XRRay를 지정한다. offsetRay는 transient input source에 대한 히트 테스트 결과를 계산할 때 전달된 profile과 일치하는 profile을 가진 XRInputSource가 정의한 좌표계로 표현된 것처럼 해석된다.

XRTransientInputHitTestOptionsInit dictionary에는 연관된 effective entityTypes가 있으며, 이는 dictionary 생성 시 제공된 경우 entityTypes로 설정된다. 생성 시 entityTypes가 제공되지 않은 경우, effective entityTypes는 단일 요소 "plane"를 포함하는 배열로 설정된다.

XRTransientInputHitTestOptionsInit dictionary에는 연관된 effective offsetRay가 있으며, 이는 dictionary 생성 시 제공된 경우 offsetRay로 설정된다. 생성 시 offsetRay가 제공되지 않은 경우, effective offsetRay는 매개변수 없이 XRRay를 구성하기 위해 XRRay()를 호출하여 생성된 것으로 설정된다.

4. 히트 테스트 소스

4.1. XRHitTestSource

[SecureContext, Exposed=Window]
interface XRHitTestSource {
  undefined cancel();
};

XRHitTestSource 객체는 히트 테스트에 대한 활성 구독의 핸들 역할을 한다.

XRHitTestSource에는 연관된 session이 있으며, 이는 히트 테스트 소스를 생성하는 데 사용된 XRSession을 저장한다.

XRHitTestSource에는 연관된 native origin이 있으며, 이는 히트 테스트 요청에 사용된 XRSpacenative origin을 식별하기에 충분한 정보를 저장한다. 이 정보는 이후 히트 테스트 결과를 계산할 때 사용된다.

XRHitTestSource에는 연관된 entity types가 있으며, 이는 히트 테스트 결과를 계산할 때 고려될 엔티티 타입을 설명하는 XRHitTestTrackableTypes의 배열이다.

XRHitTestSource에는 연관된 offset ray가 있으며, 이는 히트 테스트 결과를 계산할 때 사용될 XRRay이다.

XRHitTestSourcesession활성 히트 테스트 소스 집합에 존재하는 동안 active한 것으로 간주된다.

session, space, entityTypes, offsetRay로부터 히트 테스트 소스를 생성하기 위해, 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. hitTestSource를 새 XRHitTestSource로 둔다.

  2. hitTestSourcesessionsession으로 초기화한다.

  3. hitTestSourcenative originspacenative origin으로 초기화한다.

  4. hitTestSourceentity typesentityTypes로 초기화한다.

  5. offsetRayspace로부터 transformedOffsetRay를 계산하되, transformedOffsetRayspacenative origin 좌표계에서 해석될 때, offsetRayspaceeffective origin 좌표계에서 해석될 때와 동일한 광선을 나타내도록 한다.

  6. hitTestSourceoffset raytransformedOffsetRay로 초기화한다.

  7. hitTestSource를 반환한다.

cancel() 메서드는 XRHitTestSource hitTestSource에서 호출될 때, 애플리케이션이 지정된 hitTestSource에 대한 히트 테스트 결과 획득에 더 이상 관심이 없음을 신호한다.

cancel() 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행하여 히트 테스트 소스를 취소해야 한다:

  1. hitTestSourceactive하지 않은 경우, InvalidStateError를 던지고 이 단계를 중단한다.

  2. hitTestSourcesession활성 히트 테스트 소스 집합에서 제거한다.

애플리케이션이 특정 XRHitTestSource hitTestSource에 대한 어떤 참조도 더 이상 보유하지 않는 경우, 사용자 에이전트는 hitTestSource가 아직 active하다면 히트 테스트 소스를 취소할 수 있다. 취소는 지정되지 않은 시간에 발생할 수도 있고(또는 전혀 발생하지 않을 수도 있으며), 애플리케이션은 정리를 위해 이 동작에 의존해서는 안 된다.

4.2. XRTransientInputHitTestSource

[SecureContext, Exposed=Window]
interface XRTransientInputHitTestSource {
  undefined cancel();
};

XRTransientInputHitTestSource 객체는 transient input source에 대한 히트 테스트의 활성 구독에 대한 핸들 역할을 한다.

XRTransientInputHitTestSource에는 연관된 session이 있으며, 이는 히트 테스트 소스를 생성하는 데 사용된 XRSession을 저장한다.

XRTransientInputHitTestSource에는 연관된 profile이 있으며, 이는 입력 소스의 input profile name을 저장한다. 이 정보는 이후 transient input source에 대한 히트 테스트 결과를 계산할 때 사용된다.

XRTransientInputHitTestSource에는 연관된 entity types가 있으며, 이는 히트 테스트 결과를 계산할 때 고려될 엔티티 타입을 설명하는 XRHitTestTrackableTypes의 배열이다.

XRTransientInputHitTestSource에는 연관된 offset ray가 있으며, 이는 히트 테스트 결과를 계산할 때 사용될 XRRay이다.

XRTransientInputHitTestSourcesessiontransient input에 대한 활성 히트 테스트 소스 집합에 존재하는 동안 active한 것으로 간주된다.

session, profile, entityTypes, offsetRay로부터 transient input에 대한 히트 테스트 소스를 생성하기 위해, 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. hitTestSource를 새 XRTransientInputHitTestSource로 둔다.

  2. hitTestSourcesessionsession으로 초기화한다.

  3. hitTestSourceprofileprofile로 초기화한다.

  4. hitTestSourceentity typesentityTypes로 초기화한다.

  5. hitTestSourceoffset rayoffsetRay로 초기화한다.

  6. hitTestSource를 반환한다.

cancel() 메서드는 XRTransientInputHitTestSource hitTestSource에서 호출될 때, 애플리케이션이 지정된 hitTestSource에 대한 히트 테스트 결과 획득에 더 이상 관심이 없음을 신호한다.

cancel() 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행하여 transient input에 대한 히트 테스트 소스를 취소해야 한다:

  1. hitTestSourceactive하지 않은 경우, InvalidStateError를 던지고 이 단계를 중단한다.

  2. hitTestSourcesessiontransient input에 대한 활성 히트 테스트 소스 집합에서 제거한다.

애플리케이션이 특정 XRTransientInputHitTestSource hitTestSource에 대한 어떤 참조도 더 이상 보유하지 않는 경우, 사용자 에이전트는 hitTestSource가 아직 active하다면 transient input에 대한 히트 테스트 소스를 취소할 수 있다. 취소는 지정되지 않은 시간에 발생할 수도 있고(또는 전혀 발생하지 않을 수도 있으며), 애플리케이션은 정리를 위해 이 동작에 의존해서는 안 된다.

5. 히트 테스트 결과

5.1. XRHitTestResult

[SecureContext, Exposed=Window]
interface XRHitTestResult {
  XRPose? getPose(XRSpace baseSpace);
};

XRHitTestResult는 히트 테스트의 단일 결과를 포함한다. 이는 기반 XR 장치가 이해하는 사용자의 환경과 히트 테스트 수행에 사용된 광선의 교차점에 대한 정보를 캡슐화한다.

XRHitTestResult에는 연관된 frame이 있으며, 이는 결과가 계산된 XRFrame이다.

XRHitTestResult에는 연관된 native origin이 있다. 이 native origin은 Y축이 교차점에서 표면의 법선 벡터를 나타내는 새 좌표계를 정의한다.

XRFrame frame, XRHitTestTrackableType의 배열 entityTypes, 그리고 native hit test result nativeResult가 주어졌을 때 히트 테스트 결과를 생성하기 위해, 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. hitTestResult를 새 XRHitTestResult로 둔다.

  2. sessionframesession으로 둔다.

  3. devicesessionXR device로 둔다.

  4. devicenativeResultnative entity type, nativeEntityType를 조회한다.

  5. native entity type에서 변환하여 nativeEntityTypeentityType로 변환한다.

  6. entityTypenull이거나 entityTypes 배열에 존재하지 않으면, null을 반환하고 이 단계를 중단한다.

  7. hitTestResultframeframe으로 설정한다.

  8. hitTestResultnative originnativeResult에서 얻은 native origin으로 설정한다.

  9. hitTestResult를 반환한다.

getPose(baseSpace) 메서드는 XRHitTestResult hitTestResult에서 baseSpace 매개변수와 함께 호출될 때, frame이 나타내는 시점의 baseSpace에 상대적인 hitTestResult의 포즈를 XRPose로 제공한다.

getPose(baseSpace) 메서드가 hitTestResult에서 호출되면, 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. framehitTestResultframe으로 둔다.

  2. frameactive boolean이 false이면, InvalidStateError를 던지고 이 단계를 중단한다.

  3. pose를 새 XRPose로 둔다.

  4. space를 새 XRSpace로 두고, native originnative origin으로, origin offsetidentity transform으로, 그리고 sessionframe의 session으로 설정한다.

  5. frame이 나타내는 시점에서 baseSpace 안의 spacepose를 채워 pose에 넣는다.

  6. pose를 반환한다.

5.2. XRTransientInputHitTestResult

[SecureContext, Exposed=Window]
interface XRTransientInputHitTestResult {
  [SameObject] readonly attribute XRInputSource inputSource;
  readonly attribute FrozenArray<XRHitTestResult> results;
};

XRTransientInputHitTestResult는 transient input에 대한 히트 테스트 결과의 배열을 포함하며, XRInputSource inputSource별로 그룹화된다.

inputSource 속성은 XRInputSource를 포함하며, 이는 results 배열을 계산하는 데 사용된 것이다.

results 속성은 계산된 XRHitTestResult들의 배열을 포함한다.

XRTransientInputHitTestResult에는 연관된 frame이 있으며, 이는 결과가 계산된 XRFrame이다.

XRInputSource inputSource, XRFrame frame, XRHitTestTrackableType의 배열 entityTypes, 그리고 native hit test results의 배열 nativeResults가 주어졌을 때 transient input에 대한 히트 테스트 결과를 생성하기 위해, 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. hitTestResult를 새 XRTransientInputHitTestResult로 둔다.

  2. hitTestResultframeframe으로 설정한다.

  3. hitTestResultinputSourceinputSource로 설정한다.

  4. resultsXRHitTestResult들의 빈 배열로 둔다.

  5. nativeResults의 각 nativeResult에 대해:

    1. frame, entityTypes, nativeResult로부터 히트 테스트 결과를 생성하여 result로 둔다.

    2. resultnull이면, nativeResults의 다음 항목으로 계속한다.

    3. resultresults 배열에 추가한다.

  6. hitTestResultresultsresults로 설정한다.

  7. hitTestResult를 반환한다.

6. 히트 테스트 요청

partial interface XRSession {
  Promise<XRHitTestSource> requestHitTestSource(XRHitTestOptionsInit options);
  Promise<XRTransientInputHitTestSource> requestHitTestSourceForTransientInput(XRTransientInputHitTestOptionsInit options);
};

XRSession은 히트 테스트 결과를 계산할 때 사용될 연관된 활성 히트 테스트 소스 집합을 포함하도록 확장된다.

XRSession은 transient input에 대한 히트 테스트 결과를 계산할 때 사용될 연관된 transient input에 대한 활성 히트 테스트 소스 집합을 포함하도록 확장된다.

활성 히트 테스트 소스의 총 수 또는 최근 요청 수가 API의 정당한 사용에 비해 너무 높다고 간주되는 경우, 애플리케이션은 비합리적인 수의 요청을 하는 것으로 간주된다. 이는 남용을 피하기 위해 사용자 에이전트가 취할 수 있는 OPTIONAL 개인정보 보호 조치이다.

애플리케이션은 XRSessionrequestHitTestSource() 메서드를 사용하여 히트 테스트를 요청할 수 있다.

requestHitTestSource(options) 메서드는 XRSession session에서 호출될 때, 다음 단계를 실행해야 한다:

  1. promise새 Promise로 둔다.

  2. hit-test 기능 설명자가 session활성화된 기능 목록포함되어 있지 않으면, promiseNotSupportedError거부하고 이 단계를 중단한다.

  3. sessionended 값이 true이면, InvalidStateError를 던지고 이 단계를 중단한다.

  4. 사용자 에이전트는 비합리적인 수의 요청이 있는 경우, promiseNotAllowedError거부하고 이 단계를 중단할 수 있다.

  5. 모든 히트 테스트 결과 계산 알고리즘이 session프레임 업데이트 목록에 아직 없으면 추가한다.

  6. session, optionsspace, optionseffective entityTypesoptionseffective offsetRay히트 테스트 소스를 생성하여 hitTestSource로 둔다.

  7. hitTestSourcenull이면, promiseOperationError거부하고 이 단계를 중단한다.

  8. 생성된 hitTestSourcesession활성 히트 테스트 소스 집합에 저장한다.

  9. promise를 생성된 hitTestSource해결한다.

requestHitTestSourceForTransientInput(options) 메서드는 XRSession session에서 호출될 때, 다음 단계를 실행해야 한다:

  1. promise새 Promise로 둔다.

  2. hit-test 기능 설명자가 session활성화된 기능 목록포함되어 있지 않으면, promiseNotSupportedError거부하고 이 단계를 중단한다.

  3. sessionended 값이 true이면, InvalidStateError를 던지고 이 단계를 중단한다.

  4. 사용자 에이전트는 비합리적인 수의 요청이 있는 경우, promiseNotAllowedError거부하고 이 단계를 중단할 수 있다.

  5. 모든 히트 테스트 결과 계산 알고리즘이 session프레임 업데이트 목록에 아직 없으면 추가한다.

  6. session, optionsprofile, optionseffective entityTypesoptionseffective offsetRaytransient input에 대한 히트 테스트 소스를 생성하여 hitTestSource로 둔다.

  7. hitTestSourcenull이면, promiseOperationError거부하고 이 단계를 중단한다.

  8. 생성된 hitTestSourcesessiontransient input에 대한 활성 히트 테스트 소스 집합에 저장한다.

  9. promise를 생성된 hitTestSource해결한다.

7. 히트 테스트 결과 계산

주어진 XRFrame frame에 대한 모든 히트 테스트 결과를 계산하기 위해, 사용자 에이전트는 다음 단계를 수행해야 한다:

  1. frame으로 히트 테스트 결과 계산 알고리즘을 호출한다.

  2. frame으로 transient input에 대한 히트 테스트 결과 계산 알고리즘을 호출한다.

주어진 XRFrame frame에 대한 히트 테스트 결과를 계산하기 위해, session활성 히트 테스트 소스 집합에 존재하는 각 히트 테스트 소스 hitTestSource에 대해, 사용자 에이전트는 다음 단계를 수행해야 한다:

  1. entityTypeshitTestSourceentity types로 둔다.

  2. sessionframesession으로 둔다.

  3. devicesessionXR device로 둔다.

  4. device의 트래킹 시스템에 hitTestSourcenative origin의 최신 coordinates를 조회한다.

  5. hitTestSourceoffset ray, offsetRaycoordinates에 상대적으로 표현된 것처럼 해석하고, 그 해석을 사용하여 native hit test를 수행하여 native hit test results nativeResults를 얻는다.

  6. hitTestResults를 빈 list로 둔다.

  7. nativeResults의 각 native hit test result nativeResult에 대해 다음 단계를 수행한다:

    1. frame, entityTypes, 그리고 nativeResult로부터 히트 테스트 결과를 생성하여 hitTestResult로 둔다.

    2. hitTestResultnull이면, nativeResults의 다음 항목으로 계속한다.

    3. hitTestResultshitTestResult를 추가하되, 목록이 offsetRay에서 nativeResult까지의 광선을 따른 거리 순서로 정렬된 상태를 유지하도록 한다.

  8. hitTestResultsframe히트 테스트 소스에서 히트 테스트 결과로의 맵hitTestSource 키 아래 저장한다.

주어진 XRFrame frame에 대한 transient input에 대한 히트 테스트 결과를 계산하기 위해, sessiontransient input에 대한 활성 히트 테스트 소스 집합에 존재하는 각 히트 테스트 소스 hitTestSource에 대해, 사용자 에이전트는 다음 단계를 수행해야 한다:

  1. entityTypeshitTestSourceentity types로 둔다.

  2. sessionframesession으로 둔다.

  3. devicesessionXR device로 둔다.

  4. candidateInputSources를 transient로 간주되고 활성 XR 입력 소스 목록에 포함된 모든 session의 입력 소스 집합으로 둔다.

  5. matchingInputSourcescandidateInputSources에 포함된 입력 소스 중, 그 profiles 배열이 hitTestSourceprofile과 동일한 항목을 포함하는 모든 입력 소스의 집합으로 둔다.

  6. hitTestResults를 XRTransientInputHitTestResults의 빈 배열로 둔다.

  7. matchingInputSources의 각 transient input source inputSource에 대해:

    1. device의 트래킹 시스템에 inputSourcetargetRaySpacenative origin의 최신 coordinates를 조회한다.

    2. hitTestSourceoffset raycoordinates에 상대적으로 표현된 것처럼 해석하고, 그 해석을 사용하여 native hit test를 수행하여 native hit test results nativeResults를 얻는다.

    3. frame, inputSource, entityTypes, 그리고 nativeResults로부터 transient input에 대한 히트 테스트 결과를 생성하여 hitTestResult로 둔다.

    4. hitTestResulthitTestResults 배열에 추가한다.

  8. hitTestResultsframetransient input에 대한 히트 테스트 소스에서 히트 테스트 결과로의 맵hitTestSource 키 아래 저장한다.

8. 히트 테스트 결과 획득

partial interface XRFrame {
  sequence<XRHitTestResult> getHitTestResults(XRHitTestSource hitTestSource);
  sequence<XRTransientInputHitTestResult> getHitTestResultsForTransientInput(XRTransientInputHitTestSource hitTestSource);
};

XRFrameXRHitTestSource에서 XRHitTestResults 배열로의 매핑을 저장하는 연관된 히트 테스트 소스에서 히트 테스트 결과로의 맵을 포함하도록 확장된다.

XRFrameXRTransientInputHitTestSource에서 XRTransientInputHitTestResults 배열로의 매핑을 저장하는 연관된 transient input에 대한 히트 테스트 소스에서 히트 테스트 결과로의 맵을 포함하도록 확장된다.

애플리케이션은 XRHitTestSource에서 XRFramegetHitTestResults() 메서드를 사용하여 히트 테스트 결과를 획득할 수 있다.

getHitTestResults(hitTestSource) 메서드가 XRFrame frame에서 호출될 때, 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. frameactive boolean이 false이면, InvalidStateError를 던지고 이 단계를 중단한다.

  2. hitTestSource에 대한 항목이 frame히트 테스트 소스에서 히트 테스트 결과로의 맵에 존재하는지 확인한다. 항목이 존재하지 않으면, InvalidStateError를 던지고 이 단계를 중단한다.

  3. frame히트 테스트 소스에서 히트 테스트 결과로의 맵에서 hitTestSource에 대한 항목을 찾아 results에 할당한다.

  4. results를 반환한다.

애플리케이션은 XRTransientInputHitTestSource에서 XRFramegetHitTestResultsForTransientInput() 메서드를 사용하여 transient input에 대한 히트 테스트 결과를 획득할 수 있다.

getHitTestResultsForTransientInput(hitTestSource) 메서드가 XRFrame frame에서 호출될 때, 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. frameactive boolean이 false이면, InvalidStateError를 던지고 이 단계를 중단한다.

  2. hitTestSource에 대한 항목이 frametransient input에 대한 히트 테스트 소스에서 히트 테스트 결과로의 맵에 존재하는지 확인한다. 항목이 존재하지 않으면, InvalidStateError를 던지고 이 단계를 중단한다.

  3. frametransient input에 대한 히트 테스트 소스에서 히트 테스트 결과로의 맵에서 hitTestSource에 대한 항목을 찾아 results에 할당한다.

  4. results를 반환한다.

9. 기하 프리미티브

9.1. XRRayDirectionInit

XRRayDirectionInit dictionary는 XRRay(origin, direction) 생성자에 전달될 방향 벡터를 나타낸다.

dictionary XRRayDirectionInit {
  double x = 0;
  double y = 0;
  double z = -1;
  double w = 0;
};

9.2. XRRay

XRRayorigin 점과 direction 벡터로 설명되는 기하 광선이다.

XRRaymatrixmatrix를 포함한다.

[SecureContext, Exposed=Window]
interface XRRay {
  constructor(optional DOMPointInit origin = {}, optional XRRayDirectionInit direction = {});
  constructor(XRRigidTransform transform);
  [SameObject] readonly attribute DOMPointReadOnly origin;
  [SameObject] readonly attribute DOMPointReadOnly direction;
  [SameObject] readonly attribute Float32Array matrix;
};

XRRay(origin, direction) 생성자는 호출될 때 다음 단계를 수행해야 한다:

  1. ray를 새 XRRay로 둔다.

  2. rayorigin{ x: 0.0, y: 0.0, z: 0.0, w: 1.0 }으로 초기화한다.

  3. raydirection{ x: 0.0, y: 0.0, z: -1.0, w: 0.0 }으로 초기화한다.

  4. directionx, y, 그리고 z가 모두 0이면, TypeError를 던지고 이 단계를 중단한다.

  5. directionw가 0.0이 아니면, TypeError를 던지고 이 단계를 중단한다.

  6. originw가 1.0이 아니면, TypeError를 던지고 이 단계를 중단한다.

  7. rayoriginx 값을 originx로, y 값을 originy로, 그리고 z 값을 originz로 초기화한다.

  8. raydirectionx 값을 directionx로, y 값을 directiony로, 그리고 z 값을 directionz로 초기화한다.

  9. raydirectionx, y, 그리고 z 성분을 정규화한다.

  10. raymatrixnull로 초기화한다.

  11. ray를 반환한다.

XRRay(transform) 생성자는 호출될 때 다음 단계를 수행해야 한다:

  1. ray를 새 XRRay로 둔다.

  2. rayorigin{ x: 0.0, y: 0.0, z: 0.0, w: 1.0 }으로 초기화한다.

  3. raydirection{ x: 0.0, y: 0.0, z: -1.0, w: 0.0 }으로 초기화한다.

  4. transformmatrix를 왼쪽에서 미리 곱하여 rayorigin을 변환하고, 그 결과로 ray를 설정한다.

  5. transformmatrix를 왼쪽에서 미리 곱하여 raydirection을 변환하고, 그 결과로 ray를 설정한다.

  6. raydirectionx, y, 그리고 z 성분을 정규화한다.

  7. raymatrixnull로 초기화한다.

  8. ray를 반환한다.

origin 속성은 광선이 시작되는 공간상의 3차원 점을 미터 단위로 정의한다. originw 속성은 1.0이어야 한다.

direction 속성은 광선의 3차원 방향 벡터를 정의한다. directionw 속성은 0.0이어야 하며, 벡터는 길이가 1.0이 되도록 정규화되어야 한다.

matrix 속성은 matrix이며, XRRay를 따라 객체를 배치하는 데 사용할 수 있는 변환을 나타낸다. 이는 [0, 0, 0]에서 시작하여 음의 Z축 방향으로 뻗는 광선에서 XRRayorigindirection으로 설명되는 광선으로의 변환이다. 이러한 matrix는 directionZ축에 수직인 임의의 벡터를 변경하지 않는 회전 성분을 가진 것이어야 한다. 이 속성은 XRRay에 대한 matrix 획득으로 계산되어야 한다. 이 속성은 지연 평가되어야 한다.

참고: XRRaymatrix는 렌더링할 때 광선의 그래픽 표현을 쉽게 배치하는 데 사용할 수 있다.

주어진 XRRay ray에 대해 matrix를 획득하려면

  1. raymatrixnull이 아니면, 다음 단계를 수행한다:

    1. matrix에 대한 IsDetachedBuffer 연산이 false이면, raymatrix를 반환한다.

  2. z를 벡터 [0, 0, -1]로 둔다.

  3. axiszraydirection의 벡터 외적으로 둔다. z × direction.

  4. cos_anglezraydirection의 스칼라 내적으로 둔다. z · direction.

  5. 다음에 따라 rotation을 설정한다:

    cos_angle이 -1보다 크고 1보다 작은 경우
    rotationaxis 주위의 arccos(cos_angle)만큼의 오른손 평면 회전을 나타내는 회전 행렬로 설정한다.
    그렇지 않고, cos_angle이 -1인 경우
    rotation을 벡터 [1, 0, 0] 주위의 arccos(cos_angle)만큼의 오른손 평면 회전을 나타내는 회전 행렬로 설정한다.
    그 외의 경우
    rotation을 단위 행렬로 설정한다.
  6. translationrayorigin에 해당하는 성분을 가진 평행 이동 행렬로 둔다.

  7. matrix를 열 벡터 표기법에서 rotation을 왼쪽에서 translation에 미리 곱한 결과(즉 translation * rotation)로 둔다.

  8. raymatrixmatrix로 설정한다.

  9. matrix를 반환한다.

XRRay ray에서 임의의 엔티티 entity까지의 광선을 따른 거리, distanceray.origin + ray.direction * distance가 엔티티 entity에 속하는 점이 되고, distance가 음수가 아니며, 위 조건이 계속 성립하는 더 작은 distance 값이 존재하지 않도록 정의된다. "엔티티에 속하는 점"의 의미를 정의하는 것은 XR 장치에 달려 있다.

10. 네이티브 장치 개념

히트 테스트 API를 구현하는 사용자 에이전트는 기반 XR 장치로부터 사용자의 환경에 대한 정보를 얻는 방법을 가져야 한다. 이 절은 장치의 네이티브 기능과 관련된 요구사항 및 개념을 설명하려고 하며, 필연적으로 다양한 기반 프레임워크 / 장치를 위한 충분한 여지를 남기기 위해 충분히 덜 명세화되어 있다.

10.1. 네이티브 히트 테스트

이 명세에서는 XR 장치가 다음 요구사항을 만족하는 네이티브 히트 테스트를 사용자 에이전트가 수행할 수 있는 방법을 노출한다고 가정한다:

참고: 히트 테스트 기능을 네이티브로 노출하지 않는 장치의 경우에도, XR 장치가 노출할 수 있는 사용자의 환경에 대한 정보를 얻는 다른 방법을 활용하여 사용자 에이전트가 이 명세를 구현하는 것이 가능할 수 있다.

10.2. 네이티브 엔티티 타입

XR 장치가 반환한 네이티브 히트 테스트 결과는 결과를 계산하는 데 사용된 엔티티의 타입에 대한 정보를 포함해야 한다. 이러한 native 타입은 다음을 포함할 수 있지만 이에 한정되지는 않는다:

native entity type에서 변환하여 XRHitTestTrackableType으로 만들기 위해, 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. nativeEntityType을 변환될 native entity type으로 둔다.

  2. entityType을 새 XRHitTestTrackableType로 둔다.

  3. entityType을 다음과 같이 초기화한다:

    nativeEntityType"point"에 대응하는 타입을 포함하는 경우
    entityType"point"로 설정한다.
    그렇지 않고, nativeEntityType"plane"에 대응하는 타입을 포함하는 경우
    entityType"plane"로 설정한다.
    그렇지 않고, nativeEntityType"mesh"에 대응하는 타입을 포함하는 경우
    entityType"mesh"로 설정한다.
    그 외의 경우
    entityTypenull로 설정한다
  4. entityType을 반환한다.

10.3. 네이티브 히트 테스트 결과

XR 장치에서 반환되는 Native hit test results는 사용자의 환경과의 교차점 위치를 포함해야 한다. native entity type과 XR 장치가 이용할 수 있는 정보에 따라, 그 결과는 교차점에서 사용자의 환경에 대한 표면 법선을 사용자 에이전트가 계산할 수 있도록 하는 방식으로 정의된 방향도 포함해야 한다.

교차점의 위치와 방향에 대한 정보는 native hit test result의 native origin에 포함되어야 한다. Native origin은 그 Y축이 교차점에서 표면의 법선 벡터를 나타내는 방식으로 새 좌표계를 정의한다. XR 장치에서 방향을 반환하지 않는 경우, 사용자 에이전트는 그것이 정의하는 좌표계의 Y축이 위쪽(음의 중력 벡터 방향)을 가리키도록 native origin을 설정해야 한다.

서로 다른 구현 및 서로 다른 AR 프레임워크 간 호환성을 유지하기 위해 히트 테스트 결과의 native origin이 정의하는 좌표계의 다른 축들을 명세해야 하는지 결정한다.

11. 개인정보 보호 및 보안 고려사항

히트 테스트 API는 여러 방향으로 히트 테스트 광선을 보내 사용자의 환경을 더 많거나 적은 정밀도로 매핑하는 데 사용될 수 있다. 히트 테스트는 XR 세션을 생성할 때 기능 설명자로 선언되어야 하며, 이는 웹사이트가 히트 테스트 API를 사용하도록 허용하는 것의 잠재적인 개인정보 영향을 사용자 에이전트가 사용자에게 알릴 수 있게 한다. 또한, 사용자 에이전트는 진정한 비-개인정보 침해적 사용에 대해 비합리적인 수의 요청이 이루어졌다고 판단하는 경우 히트 테스트 요청을 거부할 수 있다.

변경사항

2021년 8월 31일 최초 공개 작업 초안 이후의 변경사항

12. 감사의 말

다음 개인들은 WebXR Hit Test 명세의 설계에 기여했다:

적합성

문서 규약

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

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

이 명세의 예제는 “예를 들어”라는 단어로 도입되거나, 규범 텍스트와 구분되도록 class="example"로 따로 표시된다. 다음과 같다:

이는 정보 제공용 예제의 예이다.

정보 제공용 참고는 “참고”라는 단어로 시작하며, 규범 텍스트와 구분되도록 class="note"로 따로 표시된다. 다음과 같다:

참고, 이는 정보 제공용 참고이다.

적합한 알고리즘

알고리즘의 일부로 명령형으로 표현된 요구사항 (예: "strip any leading space characters" 또는 "return false and abort these steps")은 해당 알고리즘을 도입할 때 사용된 핵심 단어 ("must", "should", "may" 등)의 의미로 해석되어야 한다.

알고리즘 또는 특정 단계로 표현된 적합성 요구사항은 최종 결과가 동등한 한 어떤 방식으로든 구현될 수 있다. 특히, 이 명세에 정의된 알고리즘은 이해하기 쉽도록 의도된 것이며 성능을 의도한 것은 아니다. 구현자는 최적화할 것이 권장된다.

색인

이 명세에서 정의하는 용어

참조로 정의되는 용어

참고문헌

규범 참고문헌

[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[GEOMETRY-1]
Simon Pieters; Chris Harrelson. Geometry Interfaces Module Level 1. 2018년 12월 4일. CR. URL: https://www.w3.org/TR/geometry-1/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBXR]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR Device API. 2025년 10월 1일. CRD. URL: https://www.w3.org/TR/webxr/

IDL 색인

enum XRHitTestTrackableType {
  "point",
  "plane",
  "mesh"
};

dictionary XRHitTestOptionsInit {
  required XRSpace space;
  sequence<XRHitTestTrackableType> entityTypes;
  XRRay offsetRay;
};

dictionary XRTransientInputHitTestOptionsInit {
  required DOMString profile;
  sequence<XRHitTestTrackableType> entityTypes;
  XRRay offsetRay;
};

[SecureContext, Exposed=Window]
interface XRHitTestSource {
  undefined cancel();
};

[SecureContext, Exposed=Window]
interface XRTransientInputHitTestSource {
  undefined cancel();
};

[SecureContext, Exposed=Window]
interface XRHitTestResult {
  XRPose? getPose(XRSpace baseSpace);
};

[SecureContext, Exposed=Window]
interface XRTransientInputHitTestResult {
  [SameObject] readonly attribute XRInputSource inputSource;
  readonly attribute FrozenArray<XRHitTestResult> results;
};

partial interface XRSession {
  Promise<XRHitTestSource> requestHitTestSource(XRHitTestOptionsInit options);
  Promise<XRTransientInputHitTestSource> requestHitTestSourceForTransientInput(XRTransientInputHitTestOptionsInit options);
};

partial interface XRFrame {
  sequence<XRHitTestResult> getHitTestResults(XRHitTestSource hitTestSource);
  sequence<XRTransientInputHitTestResult> getHitTestResultsForTransientInput(XRTransientInputHitTestSource hitTestSource);
};

dictionary XRRayDirectionInit {
  double x = 0;
  double y = 0;
  double z = -1;
  double w = 0;
};

[SecureContext, Exposed=Window]
interface XRRay {
  constructor(optional DOMPointInit origin = {}, optional XRRayDirectionInit direction = {});
  constructor(XRRigidTransform transform);
  [SameObject] readonly attribute DOMPointReadOnly origin;
  [SameObject] readonly attribute DOMPointReadOnly direction;
  [SameObject] readonly attribute Float32Array matrix;
};

이슈 색인

서로 다른 구현 및 서로 다른 AR 프레임워크 간 호환성을 유지하기 위해 히트 테스트 결과의 native origin이 정의하는 좌표계의 다른 축들을 명세해야 하는지 결정한다.
MDN

XRFrame/getHitTestResults

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRFrame/getHitTestResultsForTransientInput

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRHitTestResult/getPose

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRHitTestResult

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRHitTestSource/cancel

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRHitTestSource

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRay/XRRay

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRay/direction

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRay/matrix

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRay/origin

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRay

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSession/requestHitTestSource

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet12.1+Opera Mobile?
MDN

XRSession/requestHitTestSourceForTransientInput

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRTransientInputHitTestResult/inputSource

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRTransientInputHitTestResult/results

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRTransientInputHitTestResult

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRTransientInputHitTestSource/cancel

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRTransientInputHitTestSource

In only one current engine.

FirefoxNoneSafariNoneChrome81+
Opera?Edge81+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?