Add hit test mocking at initialization

This commit is contained in:
Manish Goregaokar 2020-04-08 13:20:19 -07:00
parent 3f88310e23
commit d01d9065aa
7 changed files with 126 additions and 9 deletions

View file

@ -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<Eye>(view: &FakeXRViewInit) -> Fallible<MockViewInit<Eye>> {
fov,
})
}
pub fn get_views(views: &[FakeXRViewInit]) -> Fallible<MockViewsInit> {
match views.len() {
1 => Ok(MockViewsInit::Mono(view(&views[0])?)),
@ -133,6 +136,50 @@ pub fn get_origin<T, U>(
Ok(RigidTransform3D::new(o, p))
}
pub fn get_point<T>(pt: &DOMPointInit) -> Point3D<f32, T> {
Point3D::new(pt.x / pt.w, pt.y / pt.w, pt.z / pt.w).cast()
}
pub fn get_world(world: &FakeXRWorldInit) -> Fallible<MockWorld> {
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::<Fallible<Vec<_>>>()?;
Ok(MockRegion { faces, ty })
})
.collect::<Fallible<Vec<_>>>()?;
Ok(MockWorld { regions })
}
impl From<FakeXRRegionType> 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<FakeXRViewInit>) -> Fallible<()> {

View file

@ -25,6 +25,10 @@ interface FakeXRDevice {
// behaves as if device was disconnected
Promise<void> 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<FakeXRRegionInit> hitTestRegions;
};
dictionary FakeXRRegionInit {
required sequence<FakeXRTriangleInit> faces;
required FakeXRRegionType type;
};
dictionary FakeXRTriangleInit {
required sequence<DOMPointInit> vertices; // size = 3
};
enum FakeXRRegionType {
"point",
"plane",
"mesh"
};

View file

@ -33,5 +33,8 @@ dictionary FakeXRDeviceInit {
// Eye level used for calculating floor-level spaces
FakeXRRigidTransformInit floorOrigin;
FakeXRRigidTransformInit viewerOrigin;
// Hit test extensions:
FakeXRWorldInit world;
};

View file

@ -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();