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() } }