mirror of
https://github.com/servo/servo.git
synced 2025-08-01 11:40:30 +01:00
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>
This commit is contained in:
parent
057873c94a
commit
825d6f10e9
12 changed files with 314 additions and 553 deletions
|
@ -10,6 +10,16 @@ interface XRFrame {
|
|||
|
||||
[Throws] XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace);
|
||||
[Throws] XRPose? getPose(XRSpace space, XRSpace relativeTo);
|
||||
[Pref="dom.webxr.hands.enabled", Throws] XRJointPose? getJointPose(XRJointSpace space, XRSpace relativeTo);
|
||||
|
||||
// WebXR Hand Input
|
||||
[Pref="dom.webxr.hands.enabled", Throws]
|
||||
XRJointPose? getJointPose(XRJointSpace joint, XRSpace baseSpace);
|
||||
[Pref="dom.webxr.hands.enabled", Throws]
|
||||
boolean fillJointRadii(sequence<XRJointSpace> jointSpaces, Float32Array radii);
|
||||
|
||||
[Pref="dom.webxr.hands.enabled", Throws]
|
||||
boolean fillPoses(sequence<XRSpace> spaces, XRSpace baseSpace, Float32Array transforms);
|
||||
|
||||
// WebXR Hit Test
|
||||
sequence<XRHitTestResult> getHitTestResults(XRHitTestSource hitTestSource);
|
||||
};
|
||||
|
|
|
@ -4,38 +4,43 @@
|
|||
|
||||
// https://github.com/immersive-web/webxr-hands-input/blob/master/explainer.md
|
||||
|
||||
enum XRHandJoint {
|
||||
"wrist",
|
||||
|
||||
"thumb-metacarpal",
|
||||
"thumb-phalanx-proximal",
|
||||
"thumb-phalanx-distal",
|
||||
"thumb-tip",
|
||||
|
||||
"index-finger-metacarpal",
|
||||
"index-finger-phalanx-proximal",
|
||||
"index-finger-phalanx-intermediate",
|
||||
"index-finger-phalanx-distal",
|
||||
"index-finger-tip",
|
||||
|
||||
"middle-finger-metacarpal",
|
||||
"middle-finger-phalanx-proximal",
|
||||
"middle-finger-phalanx-intermediate",
|
||||
"middle-finger-phalanx-distal",
|
||||
"middle-finger-tip",
|
||||
|
||||
"ring-finger-metacarpal",
|
||||
"ring-finger-phalanx-proximal",
|
||||
"ring-finger-phalanx-intermediate",
|
||||
"ring-finger-phalanx-distal",
|
||||
"ring-finger-tip",
|
||||
|
||||
"pinky-finger-metacarpal",
|
||||
"pinky-finger-phalanx-proximal",
|
||||
"pinky-finger-phalanx-intermediate",
|
||||
"pinky-finger-phalanx-distal",
|
||||
"pinky-finger-tip"
|
||||
};
|
||||
|
||||
[SecureContext, Exposed=Window, Pref="dom.webxr.hands.enabled"]
|
||||
interface XRHand {
|
||||
readonly attribute long length;
|
||||
getter XRJointSpace(unsigned long index);
|
||||
iterable<XRHandJoint, XRJointSpace>;
|
||||
|
||||
const unsigned long WRIST = 0;
|
||||
const unsigned long THUMB_METACARPAL = 1;
|
||||
const unsigned long THUMB_PHALANX_PROXIMAL = 2;
|
||||
const unsigned long THUMB_PHALANX_DISTAL = 3;
|
||||
const unsigned long THUMB_PHALANX_TIP = 4;
|
||||
|
||||
const unsigned long INDEX_METACARPAL = 5;
|
||||
const unsigned long INDEX_PHALANX_PROXIMAL = 6;
|
||||
const unsigned long INDEX_PHALANX_INTERMEDIATE = 7;
|
||||
const unsigned long INDEX_PHALANX_DISTAL = 8;
|
||||
const unsigned long INDEX_PHALANX_TIP = 9;
|
||||
|
||||
const unsigned long MIDDLE_METACARPAL = 10;
|
||||
const unsigned long MIDDLE_PHALANX_PROXIMAL = 11;
|
||||
const unsigned long MIDDLE_PHALANX_INTERMEDIATE = 12;
|
||||
const unsigned long MIDDLE_PHALANX_DISTAL = 13;
|
||||
const unsigned long MIDDLE_PHALANX_TIP = 14;
|
||||
|
||||
const unsigned long RING_METACARPAL = 15;
|
||||
const unsigned long RING_PHALANX_PROXIMAL = 16;
|
||||
const unsigned long RING_PHALANX_INTERMEDIATE = 17;
|
||||
const unsigned long RING_PHALANX_DISTAL = 18;
|
||||
const unsigned long RING_PHALANX_TIP = 19;
|
||||
|
||||
const unsigned long LITTLE_METACARPAL = 20;
|
||||
const unsigned long LITTLE_PHALANX_PROXIMAL = 21;
|
||||
const unsigned long LITTLE_PHALANX_INTERMEDIATE = 22;
|
||||
const unsigned long LITTLE_PHALANX_DISTAL = 23;
|
||||
const unsigned long LITTLE_PHALANX_TIP = 24;
|
||||
readonly attribute unsigned long size;
|
||||
XRJointSpace get(XRHandJoint key);
|
||||
};
|
||||
|
|
|
@ -5,4 +5,6 @@
|
|||
// https://github.com/immersive-web/webxr-hands-input/blob/master/explainer.md
|
||||
|
||||
[SecureContext, Exposed=Window, Pref="dom.webxr.hands.enabled"]
|
||||
interface XRJointSpace: XRSpace {};
|
||||
interface XRJointSpace: XRSpace {
|
||||
readonly attribute XRHandJoint jointName;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,101 @@
|
|||
use dom_struct::dom_struct;
|
||||
use webxr_api::{FingerJoint, Hand, Joint};
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::XRHandBinding::{XRHandConstants, XRHandMethods};
|
||||
use crate::dom::bindings::codegen::Bindings::XRHandBinding::{XRHandJoint, XRHandMethods};
|
||||
use crate::dom::bindings::iterable::Iterable;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::xrinputsource::XRInputSource;
|
||||
use crate::dom::xrjointspace::XRJointSpace;
|
||||
|
||||
const JOINT_SPACE_MAP: [(XRHandJoint, Joint); 25] = [
|
||||
(XRHandJoint::Wrist, Joint::Wrist),
|
||||
(XRHandJoint::Thumb_metacarpal, Joint::ThumbMetacarpal),
|
||||
(
|
||||
XRHandJoint::Thumb_phalanx_proximal,
|
||||
Joint::ThumbPhalanxProximal,
|
||||
),
|
||||
(XRHandJoint::Thumb_phalanx_distal, Joint::ThumbPhalanxDistal),
|
||||
(XRHandJoint::Thumb_tip, Joint::ThumbPhalanxTip),
|
||||
(
|
||||
XRHandJoint::Index_finger_metacarpal,
|
||||
Joint::Index(FingerJoint::Metacarpal),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Index_finger_phalanx_proximal,
|
||||
Joint::Index(FingerJoint::PhalanxProximal),
|
||||
),
|
||||
(XRHandJoint::Index_finger_phalanx_intermediate, {
|
||||
Joint::Index(FingerJoint::PhalanxIntermediate)
|
||||
}),
|
||||
(
|
||||
XRHandJoint::Index_finger_phalanx_distal,
|
||||
Joint::Index(FingerJoint::PhalanxDistal),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Index_finger_tip,
|
||||
Joint::Index(FingerJoint::PhalanxTip),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Middle_finger_metacarpal,
|
||||
Joint::Middle(FingerJoint::Metacarpal),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Middle_finger_phalanx_proximal,
|
||||
Joint::Middle(FingerJoint::PhalanxProximal),
|
||||
),
|
||||
(XRHandJoint::Middle_finger_phalanx_intermediate, {
|
||||
Joint::Middle(FingerJoint::PhalanxIntermediate)
|
||||
}),
|
||||
(
|
||||
XRHandJoint::Middle_finger_phalanx_distal,
|
||||
Joint::Middle(FingerJoint::PhalanxDistal),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Middle_finger_tip,
|
||||
Joint::Middle(FingerJoint::PhalanxTip),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Ring_finger_metacarpal,
|
||||
Joint::Ring(FingerJoint::Metacarpal),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Ring_finger_phalanx_proximal,
|
||||
Joint::Ring(FingerJoint::PhalanxProximal),
|
||||
),
|
||||
(XRHandJoint::Ring_finger_phalanx_intermediate, {
|
||||
Joint::Ring(FingerJoint::PhalanxIntermediate)
|
||||
}),
|
||||
(
|
||||
XRHandJoint::Ring_finger_phalanx_distal,
|
||||
Joint::Ring(FingerJoint::PhalanxDistal),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Ring_finger_tip,
|
||||
Joint::Ring(FingerJoint::PhalanxTip),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Pinky_finger_metacarpal,
|
||||
Joint::Little(FingerJoint::Metacarpal),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Pinky_finger_phalanx_proximal,
|
||||
Joint::Little(FingerJoint::PhalanxProximal),
|
||||
),
|
||||
(XRHandJoint::Pinky_finger_phalanx_intermediate, {
|
||||
Joint::Little(FingerJoint::PhalanxIntermediate)
|
||||
}),
|
||||
(
|
||||
XRHandJoint::Pinky_finger_phalanx_distal,
|
||||
Joint::Little(FingerJoint::PhalanxDistal),
|
||||
),
|
||||
(
|
||||
XRHandJoint::Pinky_finger_tip,
|
||||
Joint::Little(FingerJoint::PhalanxTip),
|
||||
),
|
||||
];
|
||||
|
||||
#[dom_struct]
|
||||
pub struct XRHand {
|
||||
reflector_: Reflector,
|
||||
|
@ -34,57 +122,55 @@ impl XRHand {
|
|||
pub fn new(global: &GlobalScope, source: &XRInputSource, support: Hand<()>) -> DomRoot<XRHand> {
|
||||
let id = source.id();
|
||||
let session = source.session();
|
||||
let spaces = support
|
||||
.map(|field, joint| field.map(|_| XRJointSpace::new(global, session, id, joint)));
|
||||
let spaces = support.map(|field, joint| {
|
||||
let hand_joint = JOINT_SPACE_MAP
|
||||
.iter()
|
||||
.find(|&&(_, value)| value == joint)
|
||||
.map(|&(hand_joint, _)| hand_joint)
|
||||
.expect("Invalid joint name");
|
||||
field.map(|_| XRJointSpace::new(global, session, id, joint, hand_joint))
|
||||
});
|
||||
reflect_dom_object(Box::new(XRHand::new_inherited(source, &spaces)), global)
|
||||
}
|
||||
}
|
||||
|
||||
impl XRHandMethods for XRHand {
|
||||
/// <https://github.com/immersive-web/webxr-hands-input/blob/master/explainer.md>
|
||||
fn Length(&self) -> i32 {
|
||||
XRHandConstants::LITTLE_PHALANX_TIP as i32 + 1
|
||||
fn Size(&self) -> u32 {
|
||||
XRHandJoint::Pinky_finger_tip as u32 + 1
|
||||
}
|
||||
|
||||
/// <https://github.com/immersive-web/webxr-hands-input/blob/master/explainer.md>
|
||||
fn IndexedGetter(&self, joint_index: u32) -> Option<DomRoot<XRJointSpace>> {
|
||||
let joint = match joint_index {
|
||||
XRHandConstants::WRIST => Joint::Wrist,
|
||||
XRHandConstants::THUMB_METACARPAL => Joint::ThumbMetacarpal,
|
||||
XRHandConstants::THUMB_PHALANX_PROXIMAL => Joint::ThumbPhalanxProximal,
|
||||
XRHandConstants::THUMB_PHALANX_DISTAL => Joint::ThumbPhalanxDistal,
|
||||
XRHandConstants::THUMB_PHALANX_TIP => Joint::ThumbPhalanxTip,
|
||||
XRHandConstants::INDEX_METACARPAL => Joint::Index(FingerJoint::Metacarpal),
|
||||
XRHandConstants::INDEX_PHALANX_PROXIMAL => Joint::Index(FingerJoint::PhalanxProximal),
|
||||
XRHandConstants::INDEX_PHALANX_INTERMEDIATE => {
|
||||
Joint::Index(FingerJoint::PhalanxIntermediate)
|
||||
},
|
||||
XRHandConstants::INDEX_PHALANX_DISTAL => Joint::Index(FingerJoint::PhalanxDistal),
|
||||
XRHandConstants::INDEX_PHALANX_TIP => Joint::Index(FingerJoint::PhalanxTip),
|
||||
XRHandConstants::MIDDLE_METACARPAL => Joint::Middle(FingerJoint::Metacarpal),
|
||||
XRHandConstants::MIDDLE_PHALANX_PROXIMAL => Joint::Middle(FingerJoint::PhalanxProximal),
|
||||
XRHandConstants::MIDDLE_PHALANX_INTERMEDIATE => {
|
||||
Joint::Middle(FingerJoint::PhalanxIntermediate)
|
||||
},
|
||||
XRHandConstants::MIDDLE_PHALANX_DISTAL => Joint::Middle(FingerJoint::PhalanxDistal),
|
||||
XRHandConstants::MIDDLE_PHALANX_TIP => Joint::Middle(FingerJoint::PhalanxTip),
|
||||
XRHandConstants::RING_METACARPAL => Joint::Ring(FingerJoint::Metacarpal),
|
||||
XRHandConstants::RING_PHALANX_PROXIMAL => Joint::Ring(FingerJoint::PhalanxProximal),
|
||||
XRHandConstants::RING_PHALANX_INTERMEDIATE => {
|
||||
Joint::Ring(FingerJoint::PhalanxIntermediate)
|
||||
},
|
||||
XRHandConstants::RING_PHALANX_DISTAL => Joint::Ring(FingerJoint::PhalanxDistal),
|
||||
XRHandConstants::RING_PHALANX_TIP => Joint::Ring(FingerJoint::PhalanxTip),
|
||||
XRHandConstants::LITTLE_METACARPAL => Joint::Little(FingerJoint::Metacarpal),
|
||||
XRHandConstants::LITTLE_PHALANX_PROXIMAL => Joint::Little(FingerJoint::PhalanxProximal),
|
||||
XRHandConstants::LITTLE_PHALANX_INTERMEDIATE => {
|
||||
Joint::Little(FingerJoint::PhalanxIntermediate)
|
||||
},
|
||||
XRHandConstants::LITTLE_PHALANX_DISTAL => Joint::Little(FingerJoint::PhalanxDistal),
|
||||
XRHandConstants::LITTLE_PHALANX_TIP => Joint::Little(FingerJoint::PhalanxTip),
|
||||
// XXXManishearth should this be a TypeError?
|
||||
_ => return None,
|
||||
};
|
||||
self.spaces.get(joint).map(|j| DomRoot::from_ref(&**j))
|
||||
fn Get(&self, joint_name: XRHandJoint) -> DomRoot<XRJointSpace> {
|
||||
let joint = JOINT_SPACE_MAP
|
||||
.iter()
|
||||
.find(|&&(key, _)| key == joint_name)
|
||||
.map(|&(_, joint)| joint)
|
||||
.expect("Invalid joint name");
|
||||
self.spaces
|
||||
.get(joint)
|
||||
.map(|j| DomRoot::from_ref(&**j))
|
||||
.expect("Failed to get joint pose")
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterable for XRHand {
|
||||
type Key = XRHandJoint;
|
||||
type Value = DomRoot<XRJointSpace>;
|
||||
|
||||
fn get_iterable_length(&self) -> u32 {
|
||||
JOINT_SPACE_MAP.len() as u32
|
||||
}
|
||||
|
||||
fn get_value_at_index(&self, n: u32) -> DomRoot<XRJointSpace> {
|
||||
let joint = JOINT_SPACE_MAP[n as usize].1;
|
||||
self.spaces
|
||||
.get(joint)
|
||||
.map(|j| DomRoot::from_ref(&**j))
|
||||
.expect("Failed to get joint pose")
|
||||
}
|
||||
|
||||
fn get_key_at_index(&self, n: u32) -> XRHandJoint {
|
||||
JOINT_SPACE_MAP[n as usize].0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ use dom_struct::dom_struct;
|
|||
use euclid::RigidTransform3D;
|
||||
use webxr_api::{BaseSpace, Frame, InputId, Joint, JointFrame, Space};
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::XRHandBinding::XRHandJoint;
|
||||
use crate::dom::bindings::codegen::Bindings::XRJointSpaceBinding::XRJointSpaceMethods;
|
||||
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
|
@ -21,14 +23,21 @@ pub struct XRJointSpace {
|
|||
#[ignore_malloc_size_of = "defined in rust-webxr"]
|
||||
#[no_trace]
|
||||
joint: Joint,
|
||||
hand_joint: XRHandJoint,
|
||||
}
|
||||
|
||||
impl XRJointSpace {
|
||||
pub fn new_inherited(session: &XRSession, input: InputId, joint: Joint) -> XRJointSpace {
|
||||
pub fn new_inherited(
|
||||
session: &XRSession,
|
||||
input: InputId,
|
||||
joint: Joint,
|
||||
hand_joint: XRHandJoint,
|
||||
) -> XRJointSpace {
|
||||
XRJointSpace {
|
||||
xrspace: XRSpace::new_inherited(session),
|
||||
input,
|
||||
joint,
|
||||
hand_joint,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,8 +47,12 @@ impl XRJointSpace {
|
|||
session: &XRSession,
|
||||
input: InputId,
|
||||
joint: Joint,
|
||||
hand_joint: XRHandJoint,
|
||||
) -> DomRoot<XRJointSpace> {
|
||||
reflect_dom_object(Box::new(Self::new_inherited(session, input, joint)), global)
|
||||
reflect_dom_object(
|
||||
Box::new(Self::new_inherited(session, input, joint, hand_joint)),
|
||||
global,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn space(&self) -> Space {
|
||||
|
@ -61,3 +74,10 @@ impl XRJointSpace {
|
|||
self.frame(frame).map(|f| f.pose).map(|t| t.cast_unit())
|
||||
}
|
||||
}
|
||||
|
||||
impl XRJointSpaceMethods for XRJointSpace {
|
||||
/// <https://www.w3.org/TR/webxr-hand-input-1/#xrjointspace-jointname>
|
||||
fn JointName(&self) -> XRHandJoint {
|
||||
self.hand_joint
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue