Skip to content

Commit

Permalink
Modify the XRHandModifier3D to scale appropriately with Skeleton3D.mo…
Browse files Browse the repository at this point in the history
…tion_scale and XRServer.world_scale
  • Loading branch information
Malcolmnixon committed Mar 6, 2024
1 parent f2045ba commit 2fdabd9
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 5 deletions.
2 changes: 2 additions & 0 deletions doc/classes/XRHandModifier3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
</brief_description>
<description>
This node uses hand tracking data from a [XRHandTracker] to animate the skeleton of a hand mesh.
This node positions itself at the [constant XRHandTracker.HAND_JOINT_PALM] position and scales itself to [member XRServer.world_scale]. Adding the hand model as a child of this node will result in the model being positioned and scaled correctly for XR experiences.
The hand tracking position-data is scaled by [member Skeleton3D.motion_scale] when applied to the skeleton, which can be used to adjust the tracked hand to match the scale of the hand model.
</description>
<tutorials>
<link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link>
Expand Down
15 changes: 10 additions & 5 deletions scene/3d/xr_hand_modifier_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,21 +213,23 @@ void XRHandModifier3D::_update_skeleton() {
return;
}

// Get the world and skeleton scale.
const float ws = xr_server->get_world_scale();
const float ss = skeleton->get_motion_scale();

// We cache our transforms so we can quickly calculate local transforms.
bool has_valid_data[XRHandTracker::HAND_JOINT_MAX];
Transform3D transforms[XRHandTracker::HAND_JOINT_MAX];
Transform3D inv_transforms[XRHandTracker::HAND_JOINT_MAX];

const float ws = xr_server->get_world_scale();

if (tracker->get_has_tracking_data()) {
for (int joint = 0; joint < XRHandTracker::HAND_JOINT_MAX; joint++) {
BitField<XRHandTracker::HandJointFlags> flags = tracker->get_hand_joint_flags((XRHandTracker::HandJoint)joint);
has_valid_data[joint] = flags.has_flag(XRHandTracker::HAND_JOINT_FLAG_ORIENTATION_VALID);

if (has_valid_data[joint]) {
transforms[joint] = tracker->get_hand_joint_transform((XRHandTracker::HandJoint)joint);
transforms[joint].origin *= ws;
transforms[joint].origin *= ss;
inv_transforms[joint] = transforms[joint].inverse();
}
}
Expand All @@ -253,8 +255,11 @@ void XRHandModifier3D::_update_skeleton() {
skeleton->set_bone_pose_rotation(joints[joint].bone, Quaternion(relative_transform.basis));
}

// Transform to the skeleton pose.
set_transform(transforms[XRHandTracker::HAND_JOINT_PALM]);
// Transform to the skeleton pose. This uses the HAND_JOINT_PALM position without skeleton-scaling, as it
// must be positioned to match the physical hand location. It is scaled with the world space to match
// the scaling done to the camera and eyes.
set_transform(
tracker->get_hand_joint_transform(XRHandTracker::HAND_JOINT_PALM) * ws);

set_visible(true);
} else {
Expand Down

0 comments on commit 2fdabd9

Please sign in to comment.