mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Add XRSession::requestHitTestSource()
This commit is contained in:
parent
f1d6a89150
commit
1b07b77323
9 changed files with 131 additions and 22 deletions
|
@ -4,6 +4,17 @@
|
|||
|
||||
// https://immersive-web.github.io/hit-test/#xrhittestsource-interface
|
||||
|
||||
enum XRHitTestTrackableType {
|
||||
"point",
|
||||
"plane",
|
||||
"mesh"
|
||||
};
|
||||
|
||||
dictionary XRHitTestOptionsInit {
|
||||
required XRSpace space;
|
||||
sequence<XRHitTestTrackableType> entityTypes;
|
||||
XRRay offsetRay;
|
||||
};
|
||||
|
||||
[SecureContext, Exposed=Window]
|
||||
interface XRHitTestSource {
|
||||
|
|
|
@ -36,6 +36,9 @@ interface XRSession : EventTarget {
|
|||
|
||||
Promise<void> end();
|
||||
|
||||
// hit test module
|
||||
Promise<XRHitTestSource> requestHitTestSource(XRHitTestOptionsInit options);
|
||||
|
||||
// // Events
|
||||
attribute EventHandler onend;
|
||||
attribute EventHandler onselect;
|
||||
|
|
|
@ -82,6 +82,10 @@ impl XRRay {
|
|||
|
||||
Ok(Self::new(&window.global(), Ray { origin, direction }))
|
||||
}
|
||||
|
||||
pub fn ray(&self) -> Ray<ApiSpace> {
|
||||
self.ray
|
||||
}
|
||||
}
|
||||
|
||||
impl XRRayMethods for XRRay {
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::dom::xrsession::{cast_transform, ApiPose, ApiViewerPose, XRSession};
|
|||
use crate::dom::xrspace::XRSpace;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::RigidTransform3D;
|
||||
use webxr_api::Frame;
|
||||
use webxr_api::{BaseSpace, Frame, Space};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct XRReferenceSpace {
|
||||
|
@ -57,6 +57,17 @@ impl XRReferenceSpace {
|
|||
global,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn space(&self) -> Space {
|
||||
let base = match self.ty {
|
||||
XRReferenceSpaceType::Local => BaseSpace::Local,
|
||||
XRReferenceSpaceType::Viewer => BaseSpace::Viewer,
|
||||
XRReferenceSpaceType::Local_floor => BaseSpace::Floor,
|
||||
_ => panic!("unsupported reference space found"),
|
||||
};
|
||||
let offset = self.offset.transform();
|
||||
Space { base, offset }
|
||||
}
|
||||
}
|
||||
|
||||
impl XRReferenceSpaceMethods for XRReferenceSpace {
|
||||
|
|
|
@ -6,6 +6,8 @@ use crate::dom::bindings::callback::ExceptionHandling;
|
|||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorBinding::NavigatorMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::XRHitTestSourceBinding::XRHitTestOptionsInit;
|
||||
use crate::dom::bindings::codegen::Bindings::XRHitTestSourceBinding::XRHitTestTrackableType;
|
||||
use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding::XRReferenceSpaceType;
|
||||
use crate::dom::bindings::codegen::Bindings::XRRenderStateBinding::XRRenderStateInit;
|
||||
use crate::dom::bindings::codegen::Bindings::XRRenderStateBinding::XRRenderStateMethods;
|
||||
|
@ -28,6 +30,7 @@ use crate::dom::globalscope::GlobalScope;
|
|||
use crate::dom::performance::reduce_timing_resolution;
|
||||
use crate::dom::promise::Promise;
|
||||
use crate::dom::xrframe::XRFrame;
|
||||
use crate::dom::xrhittestsource::XRHitTestSource;
|
||||
use crate::dom::xrinputsourcearray::XRInputSourceArray;
|
||||
use crate::dom::xrinputsourceevent::XRInputSourceEvent;
|
||||
use crate::dom::xrreferencespace::XRReferenceSpace;
|
||||
|
@ -37,18 +40,20 @@ use crate::dom::xrspace::XRSpace;
|
|||
use crate::realms::InRealm;
|
||||
use crate::task_source::TaskSource;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::{Rect, RigidTransform3D, Transform3D};
|
||||
use euclid::{Rect, RigidTransform3D, Transform3D, Vector3D};
|
||||
use ipc_channel::ipc::IpcReceiver;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use metrics::ToMs;
|
||||
use profile_traits::ipc;
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use std::f64::consts::{FRAC_PI_2, PI};
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use webxr_api::{
|
||||
self, util, ApiSpace, Display, EnvironmentBlendMode, Event as XREvent, Frame, SelectEvent,
|
||||
SelectKind, Session, SessionId, View, Viewer, Visibility,
|
||||
self, util, ApiSpace, Display, EntityTypes, EnvironmentBlendMode, Event as XREvent, Frame,
|
||||
FrameUpdateEvent, HitTestId, HitTestSource, Ray, SelectEvent, SelectKind, Session, SessionId,
|
||||
View, Viewer, Visibility,
|
||||
};
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -75,6 +80,10 @@ pub struct XRSession {
|
|||
end_promises: DomRefCell<Vec<Rc<Promise>>>,
|
||||
/// https://immersive-web.github.io/webxr/#ended
|
||||
ended: Cell<bool>,
|
||||
#[ignore_malloc_size_of = "defined in webxr"]
|
||||
next_hit_test_id: Cell<HitTestId>,
|
||||
#[ignore_malloc_size_of = "defined in webxr"]
|
||||
pending_hit_test_promises: DomRefCell<HashMap<HitTestId, Rc<Promise>>>,
|
||||
/// Opaque framebuffers need to know the session is "outside of a requestAnimationFrame"
|
||||
/// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
outside_raf: Cell<bool>,
|
||||
|
@ -104,6 +113,8 @@ impl XRSession {
|
|||
input_sources: Dom::from_ref(input_sources),
|
||||
end_promises: DomRefCell::new(vec![]),
|
||||
ended: Cell::new(false),
|
||||
next_hit_test_id: Cell::new(HitTestId(0)),
|
||||
pending_hit_test_promises: DomRefCell::new(HashMap::new()),
|
||||
outside_raf: Cell::new(true),
|
||||
}
|
||||
}
|
||||
|
@ -373,7 +384,7 @@ impl XRSession {
|
|||
}
|
||||
|
||||
for event in frame.events.drain(..) {
|
||||
self.session.borrow_mut().apply_event(event)
|
||||
self.handle_frame_update(event);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
|
@ -480,6 +491,22 @@ impl XRSession {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_frame_update(&self, event: FrameUpdateEvent) {
|
||||
match event {
|
||||
FrameUpdateEvent::HitTestSourceAdded(id) => {
|
||||
if let Some(promise) = self.pending_hit_test_promises.borrow_mut().remove(&id) {
|
||||
promise.resolve_native(&XRHitTestSource::new(&self.global(), id, &self));
|
||||
} else {
|
||||
warn!(
|
||||
"received hit test add request for unknown hit test {:?}",
|
||||
id
|
||||
)
|
||||
}
|
||||
},
|
||||
_ => self.session.borrow_mut().apply_event(event),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl XRSessionMethods for XRSession {
|
||||
|
@ -709,6 +736,52 @@ impl XRSessionMethods for XRSession {
|
|||
self.session.borrow_mut().end_session();
|
||||
p
|
||||
}
|
||||
|
||||
// https://immersive-web.github.io/hit-test/#dom-xrsession-requesthittestsource
|
||||
fn RequestHitTestSource(&self, options: &XRHitTestOptionsInit) -> Rc<Promise> {
|
||||
let p = Promise::new(&self.global());
|
||||
|
||||
let id = self.next_hit_test_id.get();
|
||||
self.next_hit_test_id.set(HitTestId(id.0 + 1));
|
||||
|
||||
let space = options.space.space();
|
||||
let ray = if let Some(ref ray) = options.offsetRay {
|
||||
ray.ray()
|
||||
} else {
|
||||
Ray {
|
||||
origin: Vector3D::new(0., 0., 0.),
|
||||
direction: Vector3D::new(0., 0., -1.),
|
||||
}
|
||||
};
|
||||
|
||||
let mut types = EntityTypes::default();
|
||||
|
||||
if let Some(ref tys) = options.entityTypes {
|
||||
for ty in tys {
|
||||
match ty {
|
||||
XRHitTestTrackableType::Point => types.point = true,
|
||||
XRHitTestTrackableType::Plane => types.plane = true,
|
||||
XRHitTestTrackableType::Mesh => types.mesh = true,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
types.plane = true;
|
||||
}
|
||||
|
||||
let source = HitTestSource {
|
||||
id,
|
||||
space,
|
||||
ray,
|
||||
types,
|
||||
};
|
||||
self.pending_hit_test_promises
|
||||
.borrow_mut()
|
||||
.insert(id, p.clone());
|
||||
|
||||
self.session.borrow().request_hit_test(source);
|
||||
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
// The pose of an object in native-space. Should never be exposed.
|
||||
|
|
|
@ -11,7 +11,8 @@ use crate::dom::xrinputsource::XRInputSource;
|
|||
use crate::dom::xrreferencespace::XRReferenceSpace;
|
||||
use crate::dom::xrsession::{cast_transform, ApiPose, XRSession};
|
||||
use dom_struct::dom_struct;
|
||||
use webxr_api::Frame;
|
||||
use euclid::RigidTransform3D;
|
||||
use webxr_api::{BaseSpace, Frame, Space};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct XRSpace {
|
||||
|
@ -56,6 +57,24 @@ impl XRSpace {
|
|||
global,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn space(&self) -> Space {
|
||||
if let Some(rs) = self.downcast::<XRReferenceSpace>() {
|
||||
rs.space()
|
||||
} else if let Some(source) = self.input_source.get() {
|
||||
let base = if self.is_grip_space {
|
||||
BaseSpace::Grip(source.id())
|
||||
} else {
|
||||
BaseSpace::TargetRay(source.id())
|
||||
};
|
||||
Space {
|
||||
base,
|
||||
offset: RigidTransform3D::identity(),
|
||||
}
|
||||
} else {
|
||||
panic!("invalid space found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl XRSpace {
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
[ar_hittest_subscription_refSpaces.https.html]
|
||||
[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
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
[ar_hittest_subscription_states_regular.https.html]
|
||||
[Hit test subscription succeeds if the feature was requested]
|
||||
expected: FAIL
|
||||
|
||||
[Hit test subscription fails if the feature was not requested]
|
||||
expected: FAIL
|
||||
|
||||
[Hit test subscription fails if the feature was requested but the session already ended]
|
||||
expected: FAIL
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
[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
|
||||
expected: NOTRUN
|
||||
|
||||
[Ensures subscription to transient hit test works with an XRSpace from input source - after move - no results]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Ensures subscription to transient hit test works with an XRSpace from input source - no move]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue