diff options
author | Daniel Adams <70986246+msub2@users.noreply.github.com> | 2024-08-14 12:45:45 -1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-14 22:45:45 +0000 |
commit | 825d6f10e9cc837219aaa4db480405a31c5388a7 (patch) | |
tree | b5599c6152b08b81367176a8d7eb3cc519726dd3 /components/script/dom/xrframe.rs | |
parent | 057873c94a016b00d205f342d8929eb50365ac91 (diff) | |
download | servo-825d6f10e9cc837219aaa4db480405a31c5388a7.tar.gz servo-825d6f10e9cc837219aaa4db480405a31c5388a7.zip |
webxr: Update hand input to match latest spec (#32958)
* Update IDLs
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* Update XRHand and XRJointSpace methods/bindings
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* Implement fillJointRadii
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* Implement fillPoses
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* Formatting
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* Update test expectations
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* Tidy, missing spec link
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* Remove idlharness expectation files, update hands pref
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* Update interfaces
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* XRJointPose interface
Signed-off-by: Daniel Adams <msub2official@gmail.com>
* XRHand interface
Signed-off-by: Daniel Adams <msub2official@gmail.com>
---------
Signed-off-by: Daniel Adams <msub2official@gmail.com>
Diffstat (limited to 'components/script/dom/xrframe.rs')
-rw-r--r-- | components/script/dom/xrframe.rs | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/components/script/dom/xrframe.rs b/components/script/dom/xrframe.rs index 604ec422800..031a2578c34 100644 --- a/components/script/dom/xrframe.rs +++ b/components/script/dom/xrframe.rs @@ -5,6 +5,8 @@ use std::cell::Cell; use dom_struct::dom_struct; +use js::gc::CustomAutoRooterGuard; +use js::typedarray::Float32Array; use webxr_api::{Frame, LayerId, SubImages}; use crate::dom::bindings::codegen::Bindings::XRFrameBinding::XRFrameMethods; @@ -175,4 +177,107 @@ impl XRFrameMethods for XRFrame { .map(|r| XRHitTestResult::new(&self.global(), *r, self)) .collect() } + + #[allow(unsafe_code)] + /// <https://www.w3.org/TR/webxr-hand-input-1/#dom-xrframe-filljointradii> + fn FillJointRadii( + &self, + joint_spaces: Vec<DomRoot<XRJointSpace>>, + mut radii: CustomAutoRooterGuard<Float32Array>, + ) -> Result<bool, Error> { + if !self.active.get() { + return Err(Error::InvalidState); + } + + for joint_space in &joint_spaces { + if self.session != joint_space.upcast::<XRSpace>().session() { + return Err(Error::InvalidState); + } + } + + if joint_spaces.len() > radii.len() { + return Err(Error::Type( + "Length of radii does not match length of joint spaces".to_string(), + )); + } + + let mut radii_vec = radii.to_vec(); + let mut all_valid = true; + radii_vec.iter_mut().enumerate().for_each(|(i, radius)| { + if let Some(joint_frame) = joint_spaces + .get(i) + .and_then(|joint_space| joint_space.frame(&self.data)) + { + *radius = joint_frame.radius; + } else { + all_valid = false; + } + }); + + if !all_valid { + radii_vec.fill(f32::NAN); + } + + unsafe { + radii.update(&radii_vec); + } + + Ok(all_valid) + } + + #[allow(unsafe_code)] + /// <https://www.w3.org/TR/webxr-hand-input-1/#dom-xrframe-fillposes> + fn FillPoses( + &self, + spaces: Vec<DomRoot<XRSpace>>, + base_space: &XRSpace, + mut transforms: CustomAutoRooterGuard<Float32Array>, + ) -> Result<bool, Error> { + if !self.active.get() { + return Err(Error::InvalidState); + } + + for space in &spaces { + if self.session != space.session() { + return Err(Error::InvalidState); + } + } + + if self.session != base_space.session() { + return Err(Error::InvalidState); + } + + if spaces.len() * 16 > transforms.len() { + return Err(Error::Type( + "Transforms array length does not match 16 * spaces length".to_string(), + )); + } + + let mut transforms_vec = transforms.to_vec(); + let mut all_valid = true; + spaces.iter().enumerate().for_each(|(i, space)| { + let Some(joint_pose) = self.get_pose(space) else { + all_valid = false; + return; + }; + let Some(base_pose) = self.get_pose(base_space) else { + all_valid = false; + return; + }; + let pose = joint_pose.then(&base_pose.inverse()); + let elements = pose.to_transform(); + let elements_arr = elements.to_array(); + transforms_vec[i * 16..(i + 1) * 16].copy_from_slice(&elements_arr); + }); + + if !all_valid { + transforms_vec.fill(f32::NAN); + } + + unsafe { + transforms.update(&transforms_vec); + } + + Ok(all_valid) + } } |