aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/xrframe.rs
diff options
context:
space:
mode:
authorDaniel Adams <70986246+msub2@users.noreply.github.com>2024-08-14 12:45:45 -1000
committerGitHub <noreply@github.com>2024-08-14 22:45:45 +0000
commit825d6f10e9cc837219aaa4db480405a31c5388a7 (patch)
treeb5599c6152b08b81367176a8d7eb3cc519726dd3 /components/script/dom/xrframe.rs
parent057873c94a016b00d205f342d8929eb50365ac91 (diff)
downloadservo-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.rs105
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)
+ }
}