WebXR Hit Test Module

Editor’s Draft,

More details about this document
This version:
https://immersive-web.github.io/hit-test/
Latest published version:
https://www.w3.org/TR/webxr-hit-test-1/
Feedback:
GitHub
Inline In Spec
Editor:
(Google)
Participate:
File an issue (open issues)
Mailing list archive
W3C’s #immersive-web IRC

Abstract

Describes a method for performing hit tests against real world geometry to be used with the WebXR Device API.

Status of this document

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was published by the Immersive Web Working Group as an Editors' Draft. This document is intended to become a W3C Recommendation. Feedback and comments on this specification are welcome. Please use Github issues. Discussions may also be found in the public-immersive-web-wg@w3.org archives.

Publication as an Editors' Draft does not imply endorsement by W3C and its Members. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the 1 August 2017 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 2 November 2021 W3C Process Document.

1. Introduction

This module describes a mechanism for allowing WebXR applications to cast rays into the users' real world environment and report back, to the best of the XR device’s knowledge, the point at which the ray intersected with a physical object along with the orientation of the intersected surface. This allows for virtual objects to be placed in alignment with those surfaces, such as placing objects realistically on the floor or attaching them to a wall. The hit test API is an extension to WebXR Device API and builds on top of WebXR Augmented Reality Module.

1.1. Terminology

Hit testing, as understood by this document, is an act of checking if an idealised mathematical ray (half-line) intersects with real world as understood by the underlying Augmented Reality hardware & software. Ray intersections against virtual objects created by the application consuming the API are explicitly out of scope of the hit test API.

2. Initialization

2.1. Feature descriptor

In order for the applications to signal their interest in performing hit testing during a session, the session must be requested with appropriate feature descriptor. The string hit-test is introduced by this module as a new valid feature descriptor for hit test feature.

A device is capable of supporting the hit test feature if the device exposes a native hit test capability. The inline XR device MUST NOT be treated as capable of supporting the hit test feature.

The hit test feature is subject to feature policy and requires "xr-spatial-tracking" policy to be allowed on the requesting document’s origin.

3. Hit test options

3.1. XRHitTestTrackableType

An XRHitTestTrackableType enum specifies the type of entity that can be used for the purposes of hit test source creation.

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

3.2. XRHitTestOptionsInit

An XRHitTestOptionsInit dictionary represents a set of configurable values that affect the behavior of the hit test being performed.

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

The space dictionary member specifies XRSpace relative to which the offsetRay is specified.

The entityTypes dictionary member specifies array of XRHitTestTrackableTypes that will be used to compute results of the hit test.

The offsetRay dictionary member specifies XRRay that will be used to perform hit test. The offsetRay will be interpreted as if expressed in a coordinate system defined by space.

The XRHitTestOptionsInit dictionary has an associated effective entityTypes which is set to entityTypes if it was provided at dictionary construction time. If the entityTypes was not provided at construction time, the effective entityTypes is set to an array containing single element, "plane".

The XRHitTestOptionsInit dictionary has an associated effective offsetRay which is set to offsetRay if it was provided at dictionary construction time. If the offsetRay was not provided at construction time, the effective offsetRay is set to an XRRay constructed by invoking XRRay() without any parameters.

3.3. XRTransientInputHitTestOptionsInit

An XRTransientInputHitTestOptionsInit dictionary represents a set of configurable values that affect the behavior of the hit test for transient input that is being performed.

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

The profile dictionary member specifies an input profile name of the transient input source that will be used to compute hit test results.

The entityTypes dictionary member specifies array of XRHitTestTrackableTypes that will be used to compute results of the hit test.

The offsetRay dictionary member specifies XRRay that will be used to perform hit test. The offsetRay will be interpreted as if expressed in a coordinate system defined by XRInputSource whose profile matches the passed in profile when computing hit test results for transient input sources.

The XRTransientInputHitTestOptionsInit dictionary has an associated effective entityTypes which is set to entityTypes if it was provided at dictionary construction time. If the entityTypes was not provided at construction time, the effective entityTypes is set to an array containing single element, "plane".

The XRTransientInputHitTestOptionsInit dictionary has an associated effective offsetRay which is set to offsetRay if it was provided at dictionary construction time. If the offsetRay was not provided at construction time, the effective offsetRay is set to an XRRay constructed by invoking XRRay() without any parameters.

4. Hit test source

4.1. XRHitTestSource

XRHitTestSource

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone
[SecureContext, Exposed=Window]
interface XRHitTestSource {
  undefined cancel();
};

The XRHitTestSource object serves as a handle to an active subscription to hit test.

Each XRHitTestSource has an associated session which stores an XRSession that was used to create the hit test source.

Each XRHitTestSource has an associated native origin which stores information sufficient to identify the native origin of an XRSpace that was used to request hit test. This information will be subsequently used when computing hit test results.

Each XRHitTestSource has an associated entity types, which is an array of XRHitTestTrackableTypes describing which entity types will be considered when computing hit test results.

Each XRHitTestSource has an associated offset ray, which is an XRRay that will be used when computing hit test results.

XRHitTestSource is considered active for as long as it’s present in session's set of active hit test sources.

In order to create a hit test source from session, space, entityTypes and offsetRay, the user agent MUST run the following steps:

  1. Let hitTestSource be a new XRHitTestSource.

  2. Initialize hitTestSource’s session to session.

  3. Initialize hitTestSource’s native origin to space’s native origin.

  4. Initialize hitTestSource’s entity types to entityTypes.

  5. Compute transformedOffsetRay from offsetRay and space such that transformedOffsetRay, when interpreted in space’s native origin coordinate system, represents the same ray as offsetRay does when interpreted in space’s effective origin coordinate system.

  6. Initialize hitTestSource’s offset ray to transformedOffsetRay.

  7. Return hitTestSource.

XRHitTestSource/cancel

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

The cancel() method, when invoked on XRHitTestSource hitTestSource, signals that the application is no longer interested in obtaining hit test results for the specified hitTestSource.

When cancel() method is invoked, the user agent MUST cancel a hit test source by running the following steps:

  1. If the hitTestSource is not active, throw an InvalidStateError and abort these steps.

  2. Remove hitTestSource from session's set of active hit test sources.

When the application no longer retains any references to a particular XRHitTestSource hitTestSource, the user agent MAY cancel a hit test source if hitTestSource is still active. The cancelation MAY happen at an unspecified time (or not at all) and the application SHOULD NOT rely on this behavior for cleanup.

4.2. XRTransientInputHitTestSource

XRTransientInputHitTestSource

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone
[SecureContext, Exposed=Window]
interface XRTransientInputHitTestSource {
  undefined cancel();
};

The XRTransientInputHitTestSource object serves as a handle to an active subscription to hit test for transient input sources.

Each XRTransientInputHitTestSource has an associated session which stores an XRSession that was used to create the hit test source.

Each XRTransientInputHitTestSource has an associated profile which stores input profile name of an input source. This information will be subsequently used when computing hit test results for transient input sources.

Each XRTransientInputHitTestSource has an associated entity types, which is an array of XRHitTestTrackableTypes describing which entity types will be considered when computing hit test results.

Each XRTransientInputHitTestSource has an associated offset ray, which is an XRRay that will be used when computing hit test results.

XRTransientInputHitTestSource is considered active for as long as it’s present in session's set of active hit test sources for transient input.

In order to create a hit test source for transient input from session, profile, entityTypes and offsetRay, the user agent MUST run the following steps:

  1. Let hitTestSource be a new XRTransientInputHitTestSource.

  2. Initialize hitTestSource’s session to session.

  3. Initialize hitTestSource’s profile to profile.

  4. Initialize hitTestSource’s entity types to entityTypes.

  5. Initialize hitTestSource’s offset ray to offsetRay.

  6. Return hitTestSource.

XRTransientInputHitTestSource/cancel

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

The cancel() method, when invoked on XRTransientInputHitTestSource hitTestSource, signals that the application is no longer interested in obtaining hit test results for the specified hitTestSource.

When cancel() method is invoked, the user agent MUST cancel a hit test source for transient input by running the following steps:

  1. If the hitTestSource is not active, throw an InvalidStateError and abort these steps.

  2. Remove hitTestSource from session's set of active hit test sources for transient input.

When the application no longer retains any references to a particular XRTransientInputHitTestSource hitTestSource, the user agent MAY cancel a hit test source for transient input if hitTestSource is still active. The cancelation MAY happen at an unspecified time (or not at all) and the application SHOULD NOT rely on this behavior for cleanup.

5. Hit test result

5.1. XRHitTestResult

XRHitTestResult

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone
[SecureContext, Exposed=Window]
interface XRHitTestResult {
  XRPose? getPose(XRSpace baseSpace);
};

A XRHitTestResult contains single result of a hit test. It encapsulates information about the intersection point of the ray used to perform the hit test with user’s environment as understood by the underlying XR device.

Each XRHitTestResult has an associated frame which is an XRFrame for which the result was computed.

Each XRHitTestResult has an associated native origin. This native origin defines new coordinate system whose Y axis represents the surface’s normal vector at the intersection point.

In order to create a hit test result given XRFrame frame, array of XRHitTestTrackableType entityTypes, and native hit test result nativeResult, the user agent MUST run the following steps:

  1. Let hitTestResult be a new XRHitTestResult.

  2. Let session be frame’s session.

  3. Let device be session’s XR device.

  4. Query device for native entity type, nativeEntityType, of the nativeResult.

  5. Convert from native entity type nativeEntityType to entityType.

  6. If entityType is null or is not present in entityTypes array, return null and abort these steps.

  7. Set hitTestResult’s frame to frame.

  8. Set hitTestResult’s native origin to a native origin obtained from nativeResult.

  9. Return hitTestResult.

The getPose(baseSpace) method, when invoked on XRHitTestResult hitTestResult with baseSpace parameter, provides the pose of the hitTestResult relative to baseSpace as an XRPose, at the time represented by frame.

When getPose(baseSpace) method is invoked on hitTestResult, the user agent MUST run the following steps:

  1. Let frame be the hitTestResult’s frame.

  2. If frame’s active boolean is false, throw an InvalidStateError and abort these steps.

  3. Let pose be a new XRPose.

  4. Let space be a new XRSpace, with native origin set to native origin, origin offset set to identity transform, and session set to frame's session.

  5. Populate the pose of space in baseSpace at the time represented by frame into pose.

  6. Return pose.

5.2. XRTransientInputHitTestResult

XRTransientInputHitTestResult

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

XRTransientInputHitTestResult/inputSource

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

XRTransientInputHitTestResult/results

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone
[SecureContext, Exposed=Window]
interface XRTransientInputHitTestResult {
  [SameObject] readonly attribute XRInputSource inputSource;
  readonly attribute FrozenArray<XRHitTestResult> results;
};

A XRTransientInputHitTestResult contains array of result of a hit test for transient input, grouped by XRInputSource inputSource.

The inputSource attribute contains an XRInputSource that was used to compute the results array.

The results attribute contains an array of computed XRHitTestResults.

Each XRTransientInputHitTestResult has an associated frame which is an XRFrame for which the results were computed.

In order to create a hit test result for transient input given XRInputSource inputSource, XRFrame frame, array of XRHitTestTrackableType entityTypes, and array of native hit test results nativeResults, the user agent MUST run the following steps:

  1. Let hitTestResult be a new XRTransientInputHitTestResult.

  2. Set hitTestResult’s frame to frame.

  3. Set hitTestResult’s inputSource to inputSource.

  4. Let results be an empty array of XRHitTestResults.

  5. For each nativeResult in nativeResults:

    1. Create a hit test result result from frame, entityTypes, and nativeResult.

    2. If result is null, continue to the next entry in nativeResults.

    3. Add result to results array.

  6. Set hitTestResult’s results to results.

  7. Return hitTestResult.

6. Requesting hit test

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

The XRSession is extended to contain an associated set of active hit test sources that will be used when computing hit test results.

The XRSession is extended to contain an associated set of active hit test sources for transient input that will be used when computing hit test results for transient input.

The application is considered to make an unreasonable number of requests when the total number of active hit test sources or recently made requests is considered too high for a legitimate use of the API. This is an OPTIONAL privacy measure that the user agent MAY take to avoid abuse.

The application can request hit test using XRSession's requestHitTestSource() method.

XRSession/requestHitTestSource

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet12.1+Opera MobileNone

The requestHitTestSource(options) method, when invoked on an XRSession session, MUST run the following steps:

  1. Let promise be a new Promise.

  2. If hit-test feature descriptor is not contained in the session’s list of enabled features, reject promise with NotSupportedError and abort these steps.

  3. If session’s ended value is true, throw an InvalidStateError and abort these steps.

  4. The user agent MAY reject promise with NotAllowedError and abort these steps if there is a unreasonable number of requests.

  5. Add compute all hit test results algorithm to session’s list of frame updates if it is not already present there.

  6. Create a hit test source, hitTestSource, with session, optionsspace, optionseffective entityTypes and optionseffective offsetRay.

  7. If hitTestSource is null, reject promise with an OperationError and abort these steps.

  8. Store created hitTestSource in session’s set of active hit test sources.

  9. Resolve promise with created hitTestSource.

XRSession/requestHitTestSourceForTransientInput

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

The requestHitTestSourceForTransientInput(options) method, when invoked on an XRSession session, MUST run the following steps:

  1. Let promise be a new Promise.

  2. If hit-test feature descriptor is not contained in the session’s list of enabled features, reject promise with NotSupportedError and abort these steps.

  3. If session’s ended value is true, throw an InvalidStateError and abort these steps.

  4. The user agent MAY reject promise with NotAllowedError and abort these steps if there is a unreasonable number of requests.

  5. Add compute all hit test results algorithm to session’s list of frame updates if it is not already present there.

  6. Create a hit test source for transient input, hitTestSource, with session, optionsprofile, optionseffective entityTypes and optionseffective offsetRay.

  7. If hitTestSource is null, reject promise with an OperationError and abort these steps.

  8. Store created hitTestSource in session’s set of active hit test sources for transient input.

  9. Resolve promise with created hitTestSource.

7. Computing hit test results

In order to compute all hit test results for a given XRFrame frame, the user agent MUST perform the following steps:

  1. Invoke compute hit test results algorithm with frame.

  2. Invoke compute hit test results for transient input algorithm with frame.

In order to compute hit test results for a given XRFrame frame, for each hit test source, hitTestSource, that is present in session's set of active hit test sources, the user agent MUST perform the following steps:

  1. Let entityTypes be the hitTestSource’s entity types.

  2. Let session be frame’s session.

  3. Let device be the session’s XR device.

  4. Query the device’s tracking system for hitTestSource’s native origin's latest coordinates.

  5. Interpret hitTestSource’s offset ray, offsetRay, as if expressed relative to coordinates and using that interpretation, perform native hit test obtaining native hit test results nativeResults.

  6. Let hitTestResults be an empty list.

  7. For each native hit test result nativeResult in nativeResults, perform the following steps:

    1. Create a hit test result, hitTestResult from frame, entityTypes, and nativeResult.

    2. If hitTestResult is null, continue to the next entry in nativeResults.

    3. Add hitTestResult to hitTestResults such that the list remains sorted by the distance along the ray from offsetRay to nativeResult.

  8. Store hitTestResults in frame’s map of hit test sources to hit test results under the hitTestSource key.

In order to compute hit test results for transient input for a given XRFrame frame, for each hit test source, hitTestSource, that is present in session's set of active hit test sources for transient input, the user agent MUST perform the following steps:

  1. Let entityTypes be the hitTestSource’s entity types.

  2. Let session be frame’s session.

  3. Let device be the session’s XR device.

  4. Let candidateInputSources be a set of all session’s input sources contained in list of active XR input sources that are considered transient.

  5. Let matchingInputSources be a set of all input sources contained in candidateInputSources whose profiles array contain an entry equal to hitTestSource’s profile.

  6. Let hitTestResults be an empty array of XRTransientInputHitTestResults.

  7. For each transient input source inputSource in matchingInputSources:

    1. Query the device’s tracking system for inputSource’s targetRaySpace's native origin's latest coordinates.

    2. Interpret hitTestSource’s offset ray, as if expressed relative to coordinates and using that interpretation, perform native hit test obtaining native hit test results nativeResults.

    3. Create a hit test result for transient input, hitTestResult from frame, inputSource, entityTypes, and nativeResults.

    4. Add hitTestResult to hitTestResults array.

  8. Store hitTestResults in frame’s map of hit test sources to hit test results for transient input under the hitTestSource key.

8. Obtaining hit test results

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

The XRFrame is extended to contain an associated map of hit test sources to hit test results that stores a mapping from XRHitTestSource to an array of XRHitTestResults.

The XRFrame is extended to contain an associated map of hit test sources to hit test results for transient input that stores a mapping from XRTransientInputHitTestSource to an array of XRTransientInputHitTestResults.

The application can obtain hit test results from an XRHitTestSource by using XRFrame's getHitTestResults() method.

XRFrame/getHitTestResults

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

When the getHitTestResults(hitTestSource) method, when invoked on an XRFrame frame, the user agent MUST run the following steps:

  1. If frame’s active boolean is false, throw an InvalidStateError and abort these steps.

  2. Check that the entry for hitTestSource is present in frame’s map of hit test sources to hit test results. If the entry is not present, throw an InvalidStateError and abort these steps.

  3. Look up an entry for hitTestSource in frame’s map of hit test sources to hit test results and assign it to results.

  4. Return results.

The application can obtain hit test results for transient input from an XRTransientInputHitTestSource by using XRFrame's getHitTestResultsForTransientInput() method.

XRFrame/getHitTestResultsForTransientInput

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

When the getHitTestResultsForTransientInput(hitTestSource) method, when invoked on an XRFrame frame, the user agent MUST run the following steps:

  1. If frame’s active boolean is false, throw an InvalidStateError and abort these steps.

  2. Check that the entry for hitTestSource is present in frame’s map of hit test sources to hit test results for transient input. If the entry is not present, throw an InvalidStateError and abort these steps.

  3. Look up an entry for hitTestSource in frame’s map of hit test sources to hit test results for transient input and assign it to results.

  4. Return results.

9. Geometric primitives

9.1. XRRayDirectionInit

An XRRayDirectionInit dictionary represents a direction vector to be passed to the XRRay(origin, direction) constructor.

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

9.2. XRRay

XRRay

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

An XRRay is a geometric ray described by an origin point and direction vector.

An XRRay contains a matrix which is a matrix.

[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/XRRay

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

The XRRay(origin, direction) constructor MUST perform the following steps when invoked:

  1. Let ray be a new XRRay.

  2. Initialize ray’s origin to { x: 0.0, y: 0.0, z: 0.0, w: 1.0 }.

  3. Initialize ray’s direction to { x: 0.0, y: 0.0, z: -1.0, w: 0.0 }.

  4. If all of direction’s x, y, and z are zero, throw a TypeError and abort these steps.

  5. If direction’s w is not 0.0, throw a TypeError and abort these steps.

  6. If origin’s w is not 1.0, throw a TypeError and abort these steps.

  7. Initialize ray’s origin’s x value to origin’s x, y value to origin’s y, and z value to origin’s z.

  8. Initialize ray’s direction’s x value to direction’s x, y value to direction’s y, and z value to direction’s z.

  9. Normalize the x, y, and z components of ray’s direction.

  10. Initialize ray’s matrix to null.

  11. Return ray.

The XRRay(transform) constructor MUST perform the following steps when invoked:

  1. Let ray be a new XRRay.

  2. Initialize ray’s origin to { x: 0.0, y: 0.0, z: 0.0, w: 1.0 }.

  3. Initialize ray’s direction to { x: 0.0, y: 0.0, z: -1.0, w: 0.0 }.

  4. Transform ray’s origin by premultiplying the transform’s matrix and set ray to the result.

  5. Transform ray’s direction by premultiplying the transform’s matrix and set ray to the result.

  6. Normalize the x, y, and z components of ray’s direction.

  7. Initialize ray’s matrix to null.

  8. Return ray.

XRRay/origin

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

The origin attribute defines the 3-dimensional point in space that the ray originates from, given in meters. The origin's w attribute MUST be 1.0.

XRRay/direction

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

The direction attribute defines the ray’s 3-dimensional directional vector. The direction's w attribute MUST be 0.0 and the vector MUST be normalized to have a length of 1.0.

XRRay/matrix

In only one current engine.

FirefoxNoneSafariNoneChrome81+
OperaNoneEdge81+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS SafariNoneChrome for Android81+Android WebViewNoneSamsung Internet13.0+Opera MobileNone

The matrix attribute is a matrix which represents a transform that can be used to position objects along the XRRay. It is a transform from a ray originating at [0, 0, 0] and extending down the negative Z axis to the ray described by the XRRay's origin and direction. Such a matrix MUST be one that has a rotation component which leaves any vector perpendicular to direction and the Z axis unchanged. This attribute MUST be computed by obtaining the matrix for the XRRay. This attribute SHOULD be lazily evaluated.

Note: The XRRay's matrix can be used to easily position graphical representations of the ray when rendering.

To obtain the matrix for a given XRRay ray

  1. If ray’s matrix is not null, perform the following steps:

    1. If the operation IsDetachedBuffer on matrix is false, return ray’s matrix.

  2. Let z be the vector [0, 0, -1].

  3. Let axis be the vector cross product of z and ray’s direction, z × direction.

  4. Let cos_angle be the scalar dot product of z and ray’s direction, z · direction.

  5. Set rotation based on the following:

    If cos_angle is greater than -1 and less than 1
    Set rotation to the rotation matrix representing a right handed planar rotation around axis by arccos(cos_angle).
    Else, if cos_angle is -1
    Set rotation to the rotation matrix representing a right handed planar rotation around vector [1, 0, 0] by arccos(cos_angle).
    Else
    Set rotation to an identity matrix.
  6. Let translation be the translation matrix with components corresponding to ray’s origin.

  7. Let matrix be the result of premultiplying rotation from the left onto translation (i.e. translation * rotation) in column-vector notation.

  8. Set ray’s matrix to matrix.

  9. Return matrix.

The distance along the ray, distance, from XRRay ray to any entity entity is defined such that ray.origin + ray.direction * distance results in a point beloning to the entity entity, distance is non-negative, and there does not exist a smaller value of distance for the above predicate to still hold. It is up to the XR device to define the meaning of "point belonging to an entity".

10. Native device concepts

User agents implementing hit test API must have a way of obtaining information about user’s environment from underlying XR device. This section attempts to describe requirements and concepts related to native capabilities of the device and is by neccesity sufficiently under-specified to leave ample room for different underlying frameworks / devices.

10.1. Native hit test

In this specification it is assumed that XR device exposes a way for the user agent to perform a native hit test that satisfies the following requirements:

Note: For devices that do not expose the hit test functionality natively, it might still be possible for user agents to implement this specification by leveraging other ways of obtaining the information about user’s environment that might be exposed by the XR device.

10.2. Native entity type

Native hit test results returned by XR device should contain information about the type of the entity used to compute the result. Such native types might consist of, but not be limited to:

To convert from native entity type into XRHitTestTrackableType, the user agent MUST run the following steps:

  1. Let nativeEntityType be the native entity type to be converted.

  2. Let entityType be a new XRHitTestTrackableType.

  3. Initialize entityType as follows:

    If nativeEntityType contains type that corresponds to "point"
    Set entityType to "point".
    Else, if nativeEntityType contains type that corresponds to "plane"
    Set entityType to "plane".
    Else, if nativeEntityType contains type that corresponds to "mesh"
    Set entityType to "mesh".
    Else
    Set entityType to null
  4. Return entityType.

10.3. Native hit test result

Native hit test results returned from XR device should contain the position of the intersection point with user’s environment. Depending on the native entity type and the information available to the XR device, the result should also contain orientation defined in such a way to allow the user agent to compute a surface normal to the user’s environment at the intersection point.

The information about position and orientation of the intersection point should be contained in native hit test result's native origin. Native origin defines a new coordinate system in such a way that its Y axis represents the surface’s normal vector at the intersection point. If the orientation is not returned from the XR device, the user agent SHOULD set the native origin in such a way that Y axis of the coordinate system it defines is pointing up (towards negative gravity vector).

Decide if we need to specify other axes of the coordinate system defined by hit test result’s native origin to maintain compatibility between different implementations & differrent AR frameworks.

11. Privacy & Security Considerations

The hit test API can be used to map the user environment with more or less precision by sending hit test rays in multiple directions. Hit test has to be declared when creating an XR session as a feature descriptor which will allow the user agent to notify the user of the potential privacy implications of allowing the hit test API to be used by the website. Furthermore, the user agent is allowed to deny hit test requests when it considers that an unreasonable number of requests have been made for a genuine non-privacy invasive usage.

Changes

Changes from the First Public Working Draft 31 August 2021

12. Acknowledgements

The following individuals have contributed to the design of the WebXR Hit Test specification:

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[GEOMETRY-1]
Simon Pieters; Chris Harrelson. Geometry Interfaces Module Level 1. 4 December 2018. 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. March 1997. 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. 31 March 2022. CR. URL: https://www.w3.org/TR/webxr/

IDL Index

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

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

dictionary XRTransientInputHitTestOptionsInit {
  required DOMString profile;
  FrozenArray<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 {
  FrozenArray<XRHitTestResult> getHitTestResults(XRHitTestSource hitTestSource);
  FrozenArray<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;
};

Issues Index

Decide if we need to specify other axes of the coordinate system defined by hit test result’s native origin to maintain compatibility between different implementations & differrent AR frameworks.