diff --git a/components/script/dom/fakexrdevice.rs b/components/script/dom/fakexrdevice.rs index 537251fffed..b0ebb9f77fc 100644 --- a/components/script/dom/fakexrdevice.rs +++ b/components/script/dom/fakexrdevice.rs @@ -2,8 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit; use crate::dom::bindings::codegen::Bindings::FakeXRDeviceBinding::{ - FakeXRDeviceMethods, FakeXRRigidTransformInit, FakeXRViewInit, + FakeXRDeviceMethods, FakeXRRegionType, FakeXRRigidTransformInit, FakeXRViewInit, + FakeXRWorldInit, }; use crate::dom::bindings::codegen::Bindings::FakeXRInputControllerBinding::FakeXRInputSourceInit; use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{ @@ -21,15 +23,15 @@ use crate::dom::promise::Promise; use crate::task_source::TaskSource; use dom_struct::dom_struct; use euclid::{Point2D, Rect, Size2D}; -use euclid::{RigidTransform3D, Rotation3D, Transform3D, Vector3D}; +use euclid::{Point3D, RigidTransform3D, Rotation3D, Transform3D, Vector3D}; use ipc_channel::ipc::IpcSender; use ipc_channel::router::ROUTER; use profile_traits::ipc; use std::cell::Cell; use std::rc::Rc; use webxr_api::{ - Handedness, InputId, InputSource, MockDeviceMsg, MockInputInit, MockViewInit, MockViewsInit, - TargetRayMode, Visibility, + EntityType, Handedness, InputId, InputSource, MockDeviceMsg, MockInputInit, MockRegion, + MockViewInit, MockViewsInit, MockWorld, TargetRayMode, Triangle, Visibility, }; #[dom_struct] @@ -97,6 +99,7 @@ pub fn view(view: &FakeXRViewInit) -> Fallible> { fov, }) } + pub fn get_views(views: &[FakeXRViewInit]) -> Fallible { match views.len() { 1 => Ok(MockViewsInit::Mono(view(&views[0])?)), @@ -133,6 +136,50 @@ pub fn get_origin( Ok(RigidTransform3D::new(o, p)) } +pub fn get_point(pt: &DOMPointInit) -> Point3D { + Point3D::new(pt.x / pt.w, pt.y / pt.w, pt.z / pt.w).cast() +} + +pub fn get_world(world: &FakeXRWorldInit) -> Fallible { + let regions = world + .hitTestRegions + .iter() + .map(|region| { + let ty = region.type_.into(); + let faces = region + .faces + .iter() + .map(|face| { + if face.vertices.len() != 3 { + return Err(Error::Type( + "Incorrectly sized array for triangle list".into(), + )); + } + + Ok(Triangle { + first: get_point(&face.vertices[0]), + second: get_point(&face.vertices[1]), + third: get_point(&face.vertices[2]), + }) + }) + .collect::>>()?; + Ok(MockRegion { faces, ty }) + }) + .collect::>>()?; + + Ok(MockWorld { regions }) +} + +impl From for EntityType { + fn from(x: FakeXRRegionType) -> Self { + match x { + FakeXRRegionType::Point => EntityType::Point, + FakeXRRegionType::Plane => EntityType::Plane, + FakeXRRegionType::Mesh => EntityType::Mesh, + } + } +} + impl FakeXRDeviceMethods for FakeXRDevice { /// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md fn SetViews(&self, views: Vec) -> Fallible<()> { diff --git a/components/script/dom/webidls/FakeXRDevice.webidl b/components/script/dom/webidls/FakeXRDevice.webidl index 856df51cc7a..d30ee2cae62 100644 --- a/components/script/dom/webidls/FakeXRDevice.webidl +++ b/components/script/dom/webidls/FakeXRDevice.webidl @@ -25,6 +25,10 @@ interface FakeXRDevice { // behaves as if device was disconnected Promise disconnect(); + + // Hit test extensions: + // void setWorld(FakeXRWorldInit world); + // void clearWorld(); }; // https://immersive-web.github.io/webxr/#dom-xrwebgllayer-getviewport @@ -61,3 +65,26 @@ dictionary FakeXRFieldOfViewInit { required float leftDegrees; required float rightDegrees; }; + +// hit testing +dictionary FakeXRWorldInit { + required sequence hitTestRegions; +}; + + +dictionary FakeXRRegionInit { + required sequence faces; + required FakeXRRegionType type; +}; + + +dictionary FakeXRTriangleInit { + required sequence vertices; // size = 3 +}; + + +enum FakeXRRegionType { + "point", + "plane", + "mesh" +}; diff --git a/components/script/dom/webidls/XRTest.webidl b/components/script/dom/webidls/XRTest.webidl index d42ca640ba9..0071e4338b3 100644 --- a/components/script/dom/webidls/XRTest.webidl +++ b/components/script/dom/webidls/XRTest.webidl @@ -33,5 +33,8 @@ dictionary FakeXRDeviceInit { // Eye level used for calculating floor-level spaces FakeXRRigidTransformInit floorOrigin; FakeXRRigidTransformInit viewerOrigin; + + // Hit test extensions: + FakeXRWorldInit world; }; diff --git a/components/script/dom/xrtest.rs b/components/script/dom/xrtest.rs index 92f59bc0507..114260b89d9 100644 --- a/components/script/dom/xrtest.rs +++ b/components/script/dom/xrtest.rs @@ -13,7 +13,7 @@ use crate::dom::bindings::codegen::Bindings::XRTestBinding::{FakeXRDeviceInit, X use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; -use crate::dom::fakexrdevice::{get_origin, get_views, FakeXRDevice}; +use crate::dom::fakexrdevice::{get_origin, get_views, get_world, FakeXRDevice}; use crate::dom::globalscope::GlobalScope; use crate::dom::promise::Promise; use crate::script_thread::ScriptThread; @@ -106,6 +106,19 @@ impl XRTestMethods for XRTest { vec![] }; + let world = if let Some(ref w) = init.world { + let w = match get_world(w) { + Ok(w) => w, + Err(e) => { + p.reject_error(e); + return p; + }, + }; + Some(w) + } else { + None + }; + let init = MockDeviceInit { viewer_origin: origin, views, @@ -114,7 +127,7 @@ impl XRTestMethods for XRTest { supports_ar: false, floor_origin, supported_features, - world: None, + world, }; let global = self.global(); diff --git a/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_inputSources.https.html.ini b/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_inputSources.https.html.ini index 670b46927bc..23f35a787af 100644 --- a/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_inputSources.https.html.ini +++ b/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_inputSources.https.html.ini @@ -1,2 +1,10 @@ [ar_hittest_subscription_inputSources.https.html] - expected: ERROR + [Ensures subscription to hit test works with an XRSpace from input source - after move - no results] + expected: FAIL + + [Ensures subscription to hit test works with an XRSpace from input source - after move - 1 result] + expected: FAIL + + [Ensures subscription to hit test works with an XRSpace from input source - no move] + expected: FAIL + diff --git a/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html.ini b/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html.ini index acc47d4ee07..694dd586a5d 100644 --- a/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html.ini +++ b/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html.ini @@ -1,2 +1,13 @@ [ar_hittest_subscription_refSpaces.https.html] - expected: ERROR + [Ensures subscription to hit test works with viewer space - straight up - no results] + expected: FAIL + + [Ensures subscription to hit test works with viewer space - straight ahead - plane] + expected: FAIL + + [Ensures subscription to hit test works with local space] + expected: FAIL + + [Ensures subscription to hit test works with local-floor space] + expected: FAIL + diff --git a/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html.ini b/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html.ini index e33e7dce5f2..77ee3e16b32 100644 --- a/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html.ini +++ b/tests/wpt/metadata/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html.ini @@ -1,2 +1,10 @@ [ar_hittest_subscription_transientInputSources.https.html] - expected: ERROR + [Ensures subscription to transient hit test works with an XRSpace from input source - after move - 1 result] + expected: FAIL + + [Ensures subscription to transient hit test works with an XRSpace from input source - after move - no results] + expected: FAIL + + [Ensures subscription to transient hit test works with an XRSpace from input source - no move] + expected: FAIL +