From d2e2b8da4da132390225ffc85adb8a33a1b36c13 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 4 Apr 2019 14:50:23 -0700 Subject: [PATCH 1/5] Rename incorrectly-named get_pose methods --- components/script/dom/xrreferencespace.rs | 19 ++++++++++++++----- components/script/dom/xrspace.rs | 6 ++++-- .../script/dom/xrstationaryreferencespace.rs | 6 +++--- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/components/script/dom/xrreferencespace.rs b/components/script/dom/xrreferencespace.rs index ed42d63b4be..ce81a714e80 100644 --- a/components/script/dom/xrreferencespace.rs +++ b/components/script/dom/xrreferencespace.rs @@ -54,9 +54,9 @@ impl XRReferenceSpaceMethods for XRReferenceSpace { } impl XRReferenceSpace { - /// Gets viewer pose represented by this space + /// Gets pose of the viewer with respect to this space pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { - let pose = self.get_pose(base_pose); + let pose = self.get_unoffset_viewer_pose(base_pose); // This may change, see https://github.com/immersive-web/webxr/issues/567 let offset = self.transform.get().transform(); @@ -64,16 +64,25 @@ impl XRReferenceSpace { inverse.pre_mul(&pose) } - /// Gets pose represented by this space + /// Gets pose of the viewer with respect to this space /// /// Does not apply originOffset, use get_viewer_pose instead if you need it - pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { + pub fn get_unoffset_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { if let Some(stationary) = self.downcast::() { - stationary.get_pose(base_pose) + stationary.get_unoffset_viewer_pose(base_pose) } else { // non-subclassed XRReferenceSpaces exist, obtained via the "identity" // type. The pose does not depend on the base pose. RigidTransform3D::identity() } } + + /// Gets pose represented by this space + /// + /// The reference origin used is common between all + /// get_pose calls for spaces from the same device, so this can be used to compare + /// with other spaces + pub fn get_pose(&self, _: &WebVRFrameData) -> RigidTransform3D { + unimplemented!() + } } diff --git a/components/script/dom/xrspace.rs b/components/script/dom/xrspace.rs index 60589be4054..8bc62ae5d9e 100644 --- a/components/script/dom/xrspace.rs +++ b/components/script/dom/xrspace.rs @@ -39,7 +39,7 @@ impl XRSpace { } impl XRSpace { - /// Gets viewer pose represented by this space + /// Gets pose of the viewer with respect to this space #[allow(unused)] pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { if let Some(reference) = self.downcast::() { @@ -51,7 +51,9 @@ impl XRSpace { /// Gets pose represented by this space /// - /// Does not apply originOffset, use get_viewer_pose instead if you need it + /// The reference origin used is common between all + /// get_pose calls for spaces from the same device, so this can be used to compare + /// with other spaces #[allow(unused)] pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { if let Some(reference) = self.downcast::() { diff --git a/components/script/dom/xrstationaryreferencespace.rs b/components/script/dom/xrstationaryreferencespace.rs index ddba9aaa20b..5a7a9c49e6d 100644 --- a/components/script/dom/xrstationaryreferencespace.rs +++ b/components/script/dom/xrstationaryreferencespace.rs @@ -50,10 +50,10 @@ impl XRStationaryReferenceSpace { } impl XRStationaryReferenceSpace { - /// Gets pose represented by this space + /// Gets pose of the viewer with respect to this space /// - /// Does not apply originOffset, use get_viewer_pose instead - pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { + /// Does not apply originOffset, use get_viewer_pose on XRReferenceSpace instead + pub fn get_unoffset_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { // XXXManishearth add floor-level transform for floor-level and disable position in position-disabled let pos = base_pose.pose.position.unwrap_or([0., 0., 0.]); let translation = Vector3D::new(pos[0] as f64, pos[1] as f64, pos[2] as f64); From e33896f3ecc21a4a16d830bbf7076dcbd4d3c55f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 4 Apr 2019 16:06:23 -0700 Subject: [PATCH 2/5] Add proper get_pose for XRSpaces --- components/script/dom/xrreferencespace.rs | 28 +++++++++++++++++-- components/script/dom/xrspace.rs | 25 +++++++++-------- .../script/dom/xrstationaryreferencespace.rs | 25 +++++++++-------- 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/components/script/dom/xrreferencespace.rs b/components/script/dom/xrreferencespace.rs index ce81a714e80..804768eee69 100644 --- a/components/script/dom/xrreferencespace.rs +++ b/components/script/dom/xrreferencespace.rs @@ -55,6 +55,9 @@ impl XRReferenceSpaceMethods for XRReferenceSpace { impl XRReferenceSpace { /// Gets pose of the viewer with respect to this space + /// + /// This is equivalent to `get_pose(self).inverse() * get_pose(viewerSpace)`, however + /// we specialize it to be efficient pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { let pose = self.get_unoffset_viewer_pose(base_pose); @@ -72,7 +75,8 @@ impl XRReferenceSpace { stationary.get_unoffset_viewer_pose(base_pose) } else { // non-subclassed XRReferenceSpaces exist, obtained via the "identity" - // type. The pose does not depend on the base pose. + // type. These poses are equivalent to the viewer pose and follow the headset + // around, so the viewer is always at an identity transform with respect to them RigidTransform3D::identity() } } @@ -82,7 +86,25 @@ impl XRReferenceSpace { /// The reference origin used is common between all /// get_pose calls for spaces from the same device, so this can be used to compare /// with other spaces - pub fn get_pose(&self, _: &WebVRFrameData) -> RigidTransform3D { - unimplemented!() + pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { + let pose = self.get_unoffset_pose(base_pose); + + // This may change, see https://github.com/immersive-web/webxr/issues/567 + let offset = self.transform.get().transform(); + offset.post_mul(&pose) + } + + /// Gets pose represented by this space + /// + /// Does not apply originOffset, use get_viewer_pose instead if you need it + pub fn get_unoffset_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { + if let Some(stationary) = self.downcast::() { + stationary.get_unoffset_pose(base_pose) + } else { + // non-subclassed XRReferenceSpaces exist, obtained via the "identity" + // type. These are equivalent to the viewer pose and follow the headset + // around + XRSpace::viewer_pose_from_frame_data(base_pose) + } } } diff --git a/components/script/dom/xrspace.rs b/components/script/dom/xrspace.rs index 8bc62ae5d9e..d9b5a1fc983 100644 --- a/components/script/dom/xrspace.rs +++ b/components/script/dom/xrspace.rs @@ -11,7 +11,7 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrsession::XRSession; use dom_struct::dom_struct; -use euclid::RigidTransform3D; +use euclid::{RigidTransform3D, Rotation3D, Vector3D}; use webvr_traits::WebVRFrameData; #[dom_struct] @@ -39,16 +39,6 @@ impl XRSpace { } impl XRSpace { - /// Gets pose of the viewer with respect to this space - #[allow(unused)] - pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { - if let Some(reference) = self.downcast::() { - reference.get_viewer_pose(base_pose) - } else { - unreachable!() - } - } - /// Gets pose represented by this space /// /// The reference origin used is common between all @@ -62,4 +52,17 @@ impl XRSpace { unreachable!() } } + + pub fn viewer_pose_from_frame_data(data: &WebVRFrameData) -> RigidTransform3D { + let pos = data.pose.position.unwrap_or([0., 0., 0.]); + let translation = Vector3D::new(pos[0] as f64, pos[1] as f64, pos[2] as f64); + let orient = data.pose.orientation.unwrap_or([0., 0., 0., 0.]); + let rotation = Rotation3D::quaternion( + orient[0] as f64, + orient[1] as f64, + orient[2] as f64, + orient[3] as f64, + ); + RigidTransform3D::new(rotation, translation) + } } diff --git a/components/script/dom/xrstationaryreferencespace.rs b/components/script/dom/xrstationaryreferencespace.rs index 5a7a9c49e6d..6c5d53f9457 100644 --- a/components/script/dom/xrstationaryreferencespace.rs +++ b/components/script/dom/xrstationaryreferencespace.rs @@ -10,8 +10,9 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrrigidtransform::XRRigidTransform; use crate::dom::xrsession::XRSession; +use crate::dom::xrspace::XRSpace; use dom_struct::dom_struct; -use euclid::{RigidTransform3D, Rotation3D, Vector3D}; +use euclid::RigidTransform3D; use webvr_traits::WebVRFrameData; #[dom_struct] @@ -55,15 +56,17 @@ impl XRStationaryReferenceSpace { /// Does not apply originOffset, use get_viewer_pose on XRReferenceSpace instead pub fn get_unoffset_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { // XXXManishearth add floor-level transform for floor-level and disable position in position-disabled - let pos = base_pose.pose.position.unwrap_or([0., 0., 0.]); - let translation = Vector3D::new(pos[0] as f64, pos[1] as f64, pos[2] as f64); - let orient = base_pose.pose.orientation.unwrap_or([0., 0., 0., 0.]); - let rotation = Rotation3D::quaternion( - orient[0] as f64, - orient[1] as f64, - orient[2] as f64, - orient[3] as f64, - ); - RigidTransform3D::new(rotation, translation) + XRSpace::viewer_pose_from_frame_data(base_pose) + } + + /// Gets pose represented by this space + /// + /// Does not apply originOffset, use get_pose on XRReferenceSpace instead + pub fn get_unoffset_pose(&self, _: &WebVRFrameData) -> RigidTransform3D { + // XXXManishearth add floor-level transform for floor-level and disable position in position-disabled + + // The eye-level pose is basically whatever the headset pose was at t=0, which + // for most devices is (0, 0, 0) + RigidTransform3D::identity() } } From 3d790278f1033c1fbefd3d227ff3da7d842fb24d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 4 Apr 2019 16:09:53 -0700 Subject: [PATCH 3/5] Validate spaces passed to getViewerPose() --- components/script/dom/webidls/XRFrame.webidl | 2 +- components/script/dom/xrframe.rs | 14 +++++++++++--- components/script/dom/xrspace.rs | 5 ++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/components/script/dom/webidls/XRFrame.webidl b/components/script/dom/webidls/XRFrame.webidl index 24f714fcb76..4a8159177d8 100644 --- a/components/script/dom/webidls/XRFrame.webidl +++ b/components/script/dom/webidls/XRFrame.webidl @@ -8,6 +8,6 @@ interface XRFrame { readonly attribute XRSession session; - XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); + [Throws] XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); // XRInputPose? getInputPose(XRInputSource inputSource, optional XRReferenceSpace referenceSpace); }; diff --git a/components/script/dom/xrframe.rs b/components/script/dom/xrframe.rs index c9bb240a3bf..a3a8c201255 100644 --- a/components/script/dom/xrframe.rs +++ b/components/script/dom/xrframe.rs @@ -4,6 +4,8 @@ use crate::dom::bindings::codegen::Bindings::XRFrameBinding; use crate::dom::bindings::codegen::Bindings::XRFrameBinding::XRFrameMethods; +use crate::dom::bindings::error::Error; +use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; @@ -50,13 +52,19 @@ impl XRFrameMethods for XRFrame { } /// https://immersive-web.github.io/webxr/#dom-xrframe-getviewerpose - fn GetViewerPose(&self, reference: &XRReferenceSpace) -> Option> { + fn GetViewerPose( + &self, + reference: &XRReferenceSpace, + ) -> Result>, Error> { + if self.session != reference.upcast::().session() { + return Err(Error::InvalidState); + } let pose = reference.get_viewer_pose(&self.data); - Some(XRViewerPose::new( + Ok(Some(XRViewerPose::new( &self.global(), &self.session, pose, &self.data, - )) + ))) } } diff --git a/components/script/dom/xrspace.rs b/components/script/dom/xrspace.rs index d9b5a1fc983..d9bbad8cd86 100644 --- a/components/script/dom/xrspace.rs +++ b/components/script/dom/xrspace.rs @@ -44,7 +44,6 @@ impl XRSpace { /// The reference origin used is common between all /// get_pose calls for spaces from the same device, so this can be used to compare /// with other spaces - #[allow(unused)] pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { if let Some(reference) = self.downcast::() { reference.get_pose(base_pose) @@ -65,4 +64,8 @@ impl XRSpace { ); RigidTransform3D::new(rotation, translation) } + + pub fn session(&self) -> &XRSession { + &self.session + } } From 7e4b6512a7c0899b642e5eedf0f250630f7d9d34 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 4 Apr 2019 16:21:15 -0700 Subject: [PATCH 4/5] Add XRFrame.getPose() --- components/script/dom/webidls/XRFrame.webidl | 1 + components/script/dom/xrframe.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/components/script/dom/webidls/XRFrame.webidl b/components/script/dom/webidls/XRFrame.webidl index 4a8159177d8..a393acbc588 100644 --- a/components/script/dom/webidls/XRFrame.webidl +++ b/components/script/dom/webidls/XRFrame.webidl @@ -9,5 +9,6 @@ interface XRFrame { readonly attribute XRSession session; [Throws] XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); + [Throws] XRPose? getPose(XRSpace space, XRSpace relativeTo); // XRInputPose? getInputPose(XRInputSource inputSource, optional XRReferenceSpace referenceSpace); }; diff --git a/components/script/dom/xrframe.rs b/components/script/dom/xrframe.rs index a3a8c201255..67602709d9b 100644 --- a/components/script/dom/xrframe.rs +++ b/components/script/dom/xrframe.rs @@ -9,8 +9,10 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; +use crate::dom::xrpose::XRPose; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrsession::XRSession; +use crate::dom::xrspace::XRSpace; use crate::dom::xrviewerpose::XRViewerPose; use dom_struct::dom_struct; use webvr_traits::WebVRFrameData; @@ -67,4 +69,19 @@ impl XRFrameMethods for XRFrame { &self.data, ))) } + + /// https://immersive-web.github.io/webxr/#dom-xrframe-getpose + fn GetPose( + &self, + space: &XRSpace, + relative_to: &XRSpace, + ) -> Result>, Error> { + if self.session != space.session() || self.session != relative_to.session() { + return Err(Error::InvalidState); + } + let space = space.get_pose(&self.data); + let relative_to = relative_to.get_pose(&self.data); + let pose = relative_to.inverse().pre_mul(&space); + Ok(Some(XRPose::new(&self.global(), pose))) + } } From 813613628db87f09014330a9c508b079454198e6 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 4 Apr 2019 17:40:18 -0700 Subject: [PATCH 5/5] Add XRSession.viewerSpace --- components/script/dom/webidls/XRSession.webidl | 1 + components/script/dom/xrsession.rs | 6 ++++++ components/script/dom/xrspace.rs | 17 ++++++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/components/script/dom/webidls/XRSession.webidl b/components/script/dom/webidls/XRSession.webidl index 5f2cfb23929..f22918d469d 100644 --- a/components/script/dom/webidls/XRSession.webidl +++ b/components/script/dom/webidls/XRSession.webidl @@ -20,6 +20,7 @@ interface XRSession : EventTarget { readonly attribute XREnvironmentBlendMode environmentBlendMode; readonly attribute XRRenderState renderState; + readonly attribute XRSpace viewerSpace; // // Methods Promise requestReferenceSpace(XRReferenceSpaceOptions options); diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs index bf7dcb92258..c8394be5230 100644 --- a/components/script/dom/xrsession.rs +++ b/components/script/dom/xrsession.rs @@ -21,6 +21,7 @@ use crate::dom::vrdisplay::VRDisplay; use crate::dom::xrlayer::XRLayer; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrrenderstate::XRRenderState; +use crate::dom::xrspace::XRSpace; use crate::dom::xrstationaryreferencespace::XRStationaryReferenceSpace; use dom_struct::dom_struct; use std::rc::Rc; @@ -82,6 +83,11 @@ impl XRSessionMethods for XRSession { ) } + // https://immersive-web.github.io/webxr/#dom-xrsession-viewerspace + fn ViewerSpace(&self) -> DomRoot { + XRSpace::new_viewerspace(&self.global(), &self) + } + /// https://immersive-web.github.io/webxr/#dom-xrsession-requestanimationframe fn UpdateRenderState(&self, init: &XRRenderStateInit) -> Rc { let p = Promise::new(&self.global()); diff --git a/components/script/dom/xrspace.rs b/components/script/dom/xrspace.rs index d9bbad8cd86..8948ac03c8e 100644 --- a/components/script/dom/xrspace.rs +++ b/components/script/dom/xrspace.rs @@ -18,6 +18,7 @@ use webvr_traits::WebVRFrameData; pub struct XRSpace { eventtarget: EventTarget, session: Dom, + is_viewerspace: bool, } impl XRSpace { @@ -25,13 +26,21 @@ impl XRSpace { XRSpace { eventtarget: EventTarget::new_inherited(), session: Dom::from_ref(session), + is_viewerspace: false, } } - #[allow(unused)] - pub fn new(global: &GlobalScope, session: &XRSession) -> DomRoot { + fn new_viewerspace_inner(session: &XRSession) -> XRSpace { + XRSpace { + eventtarget: EventTarget::new_inherited(), + session: Dom::from_ref(session), + is_viewerspace: true, + } + } + + pub fn new_viewerspace(global: &GlobalScope, session: &XRSession) -> DomRoot { reflect_dom_object( - Box::new(XRSpace::new_inherited(session)), + Box::new(XRSpace::new_viewerspace_inner(session)), global, XRSpaceBinding::Wrap, ) @@ -47,6 +56,8 @@ impl XRSpace { pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D { if let Some(reference) = self.downcast::() { reference.get_pose(base_pose) + } else if self.is_viewerspace { + XRSpace::viewer_pose_from_frame_data(base_pose) } else { unreachable!() }