2
0
Эх сурвалжийг харах

Modify the XRHandModifier3D to scale appropriately with Skeleton3D.motion_scale and XRServer.world_scale

Malcolm Nixon 1 жил өмнө
parent
commit
2fdabd97f9

+ 2 - 0
doc/classes/XRHandModifier3D.xml

@@ -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>

+ 10 - 5
scene/3d/xr_hand_modifier_3d.cpp

@@ -213,13 +213,15 @@ 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);
@@ -227,7 +229,7 @@ void XRHandModifier3D::_update_skeleton() {
 
 			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();
 			}
 		}
@@ -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 {