Add XRInputSource.targetRaySpace

This commit is contained in:
Manish Goregaokar 2019-04-29 20:27:07 -07:00
parent e5716624d4
commit d4a6a4987d
5 changed files with 55 additions and 13 deletions

View file

@ -20,7 +20,7 @@ enum XRTargetRayMode {
interface XRInputSource { interface XRInputSource {
readonly attribute XRHandedness handedness; readonly attribute XRHandedness handedness;
// [SameObject] readonly attribute XRTargetRayMode targetRayMode; // [SameObject] readonly attribute XRTargetRayMode targetRayMode;
// [SameObject] readonly attribute XRSpace targetRaySpace; [SameObject] readonly attribute XRSpace targetRaySpace;
// [SameObject] readonly attribute XRSpace? gripSpace; // [SameObject] readonly attribute XRSpace? gripSpace;
// [SameObject] readonly attribute Gamepad? gamepad; // [SameObject] readonly attribute Gamepad? gamepad;
}; };

View file

@ -7,12 +7,13 @@ use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding;
use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{ use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{
XRHandedness, XRInputSourceMethods, XRHandedness, XRInputSourceMethods,
}; };
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::xrsession::XRSession; use crate::dom::xrsession::XRSession;
use crate::dom::xrspace::XRSpace;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState, WebVRPose};
#[dom_struct] #[dom_struct]
pub struct XRInputSource { pub struct XRInputSource {
@ -22,6 +23,7 @@ pub struct XRInputSource {
data: WebVRGamepadData, data: WebVRGamepadData,
#[ignore_malloc_size_of = "Defined in rust-webvr"] #[ignore_malloc_size_of = "Defined in rust-webvr"]
state: DomRefCell<WebVRGamepadState>, state: DomRefCell<WebVRGamepadState>,
target_ray_space: MutNullableDom<XRSpace>,
} }
impl XRInputSource { impl XRInputSource {
@ -35,6 +37,7 @@ impl XRInputSource {
session: Dom::from_ref(session), session: Dom::from_ref(session),
data, data,
state: DomRefCell::new(state), state: DomRefCell::new(state),
target_ray_space: Default::default(),
} }
} }
@ -54,6 +57,10 @@ impl XRInputSource {
pub fn update_state(&self, state: WebVRGamepadState) { pub fn update_state(&self, state: WebVRGamepadState) {
*self.state.borrow_mut() = state; *self.state.borrow_mut() = state;
} }
pub fn pose(&self) -> WebVRPose {
self.state.borrow().pose
}
} }
impl XRInputSourceMethods for XRInputSource { impl XRInputSourceMethods for XRInputSource {
@ -65,4 +72,12 @@ impl XRInputSourceMethods for XRInputSource {
WebVRGamepadHand::Right => XRHandedness::Right, WebVRGamepadHand::Right => XRHandedness::Right,
} }
} }
/// https://immersive-web.github.io/webxr/#dom-xrinputsource-targetrayspace
fn TargetRaySpace(&self) -> DomRoot<XRSpace> {
self.target_ray_space.or_init(|| {
let global = self.global();
XRSpace::new_inputspace(&global, &self.session, &self)
})
}
} }

View file

@ -110,7 +110,7 @@ impl XRReferenceSpace {
// non-subclassed XRReferenceSpaces exist, obtained via the "identity" // non-subclassed XRReferenceSpaces exist, obtained via the "identity"
// type. These are equivalent to the viewer pose and follow the headset // type. These are equivalent to the viewer pose and follow the headset
// around // around
XRSpace::viewer_pose_from_frame_data(base_pose) XRSpace::pose_to_transform(&base_pose.pose)
} }
} }
} }

View file

@ -5,20 +5,22 @@
use crate::dom::bindings::codegen::Bindings::XRSpaceBinding; use crate::dom::bindings::codegen::Bindings::XRSpaceBinding;
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::xrinputsource::XRInputSource;
use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrreferencespace::XRReferenceSpace;
use crate::dom::xrsession::XRSession; use crate::dom::xrsession::XRSession;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::{RigidTransform3D, Rotation3D, Vector3D}; use euclid::{RigidTransform3D, Rotation3D, Vector3D};
use webvr_traits::WebVRFrameData; use webvr_traits::{WebVRFrameData, WebVRPose};
#[dom_struct] #[dom_struct]
pub struct XRSpace { pub struct XRSpace {
eventtarget: EventTarget, eventtarget: EventTarget,
session: Dom<XRSession>, session: Dom<XRSession>,
is_viewerspace: bool, is_viewerspace: bool,
input_source: MutNullableDom<XRInputSource>,
} }
impl XRSpace { impl XRSpace {
@ -27,6 +29,7 @@ impl XRSpace {
eventtarget: EventTarget::new_inherited(), eventtarget: EventTarget::new_inherited(),
session: Dom::from_ref(session), session: Dom::from_ref(session),
is_viewerspace: false, is_viewerspace: false,
input_source: Default::default(),
} }
} }
@ -35,6 +38,7 @@ impl XRSpace {
eventtarget: EventTarget::new_inherited(), eventtarget: EventTarget::new_inherited(),
session: Dom::from_ref(session), session: Dom::from_ref(session),
is_viewerspace: true, is_viewerspace: true,
input_source: Default::default(),
} }
} }
@ -45,6 +49,27 @@ impl XRSpace {
XRSpaceBinding::Wrap, XRSpaceBinding::Wrap,
) )
} }
fn new_inputspace_inner(session: &XRSession, input: &XRInputSource) -> XRSpace {
XRSpace {
eventtarget: EventTarget::new_inherited(),
session: Dom::from_ref(session),
is_viewerspace: false,
input_source: MutNullableDom::new(Some(input)),
}
}
pub fn new_inputspace(
global: &GlobalScope,
session: &XRSession,
input: &XRInputSource,
) -> DomRoot<XRSpace> {
reflect_dom_object(
Box::new(XRSpace::new_inputspace_inner(session, input)),
global,
XRSpaceBinding::Wrap,
)
}
} }
impl XRSpace { impl XRSpace {
@ -57,16 +82,18 @@ impl XRSpace {
if let Some(reference) = self.downcast::<XRReferenceSpace>() { if let Some(reference) = self.downcast::<XRReferenceSpace>() {
reference.get_pose(base_pose) reference.get_pose(base_pose)
} else if self.is_viewerspace { } else if self.is_viewerspace {
XRSpace::viewer_pose_from_frame_data(base_pose) XRSpace::pose_to_transform(&base_pose.pose)
} else if let Some(source) = self.input_source.get() {
XRSpace::pose_to_transform(&source.pose())
} else { } else {
unreachable!() unreachable!()
} }
} }
pub fn viewer_pose_from_frame_data(data: &WebVRFrameData) -> RigidTransform3D<f64> { pub fn pose_to_transform(pose: &WebVRPose) -> RigidTransform3D<f64> {
let pos = data.pose.position.unwrap_or([0., 0., 0.]); let pos = pose.position.unwrap_or([0., 0., 0.]);
let translation = Vector3D::new(pos[0] as f64, pos[1] as f64, pos[2] as f64); 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 orient = pose.orientation.unwrap_or([0., 0., 0., 0.]);
let rotation = Rotation3D::quaternion( let rotation = Rotation3D::quaternion(
orient[0] as f64, orient[0] as f64,
orient[1] as f64, orient[1] as f64,

View file

@ -55,7 +55,7 @@ impl XRStationaryReferenceSpace {
/// ///
/// Does not apply originOffset, use get_viewer_pose on XRReferenceSpace instead /// Does not apply originOffset, use get_viewer_pose on XRReferenceSpace instead
pub fn get_unoffset_viewer_pose(&self, viewer_pose: &WebVRFrameData) -> RigidTransform3D<f64> { pub fn get_unoffset_viewer_pose(&self, viewer_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
let viewer_pose = XRSpace::viewer_pose_from_frame_data(viewer_pose); let viewer_pose = XRSpace::pose_to_transform(&viewer_pose.pose);
// all math is in column-vector notation // all math is in column-vector notation
// we use the following equation to verify correctness here: // we use the following equation to verify correctness here:
// get_viewer_pose(space) = get_pose(space).inverse() * get_pose(viewer_space) // get_viewer_pose(space) = get_pose(space).inverse() * get_pose(viewer_space)
@ -113,7 +113,7 @@ impl XRStationaryReferenceSpace {
}, },
XRStationaryReferenceSpaceSubtype::Position_disabled => { XRStationaryReferenceSpaceSubtype::Position_disabled => {
// This space follows the user around, but does not mirror the user's orientation // This space follows the user around, but does not mirror the user's orientation
let viewer_pose = XRSpace::viewer_pose_from_frame_data(viewer_pose); let viewer_pose = XRSpace::pose_to_transform(&viewer_pose.pose);
viewer_pose.translation.into() viewer_pose.translation.into()
}, },
} }