diff --git a/doc/classes/XRBodyModifier3D.xml b/doc/classes/XRBodyModifier3D.xml index 4227bc57df2b..cb1caf12a907 100644 --- a/doc/classes/XRBodyModifier3D.xml +++ b/doc/classes/XRBodyModifier3D.xml @@ -1,10 +1,12 @@ - + A node for driving body meshes from [XRBodyTracker] data. This node uses body tracking data from a [XRBodyTracker] to animate the skeleton of a body mesh. + This node positions itself at the [constant XRBodyTracker.JOINT_ROOT] position and scales itself to [member XRServer.world_scale]. Adding the body model as a child of this node will result in the model being positioned and scaled correctly for XR experiences. + The body tracking position-data is scaled by [member Skeleton3D.motion_scale] when applied to the skeleton, which can be used to adjust the tracked body to match the scale of the body model. $DOCS_URL/tutorials/xr/index.html diff --git a/doc/classes/XRBodyTracker.xml b/doc/classes/XRBodyTracker.xml index 5d45ad11bd14..9c869b4f5f3f 100644 --- a/doc/classes/XRBodyTracker.xml +++ b/doc/classes/XRBodyTracker.xml @@ -1,5 +1,5 @@ - + A tracked body in XR. diff --git a/doc/classes/XRFaceModifier3D.xml b/doc/classes/XRFaceModifier3D.xml index 7a60e6db3467..8caa74cff7dc 100644 --- a/doc/classes/XRFaceModifier3D.xml +++ b/doc/classes/XRFaceModifier3D.xml @@ -1,5 +1,5 @@ - + A node for driving standard face meshes from [XRFaceTracker] weights. diff --git a/doc/classes/XRFaceTracker.xml b/doc/classes/XRFaceTracker.xml index 0212cc8fffe8..96ed137324da 100644 --- a/doc/classes/XRFaceTracker.xml +++ b/doc/classes/XRFaceTracker.xml @@ -1,5 +1,5 @@ - + A tracked face. diff --git a/scene/3d/xr_body_modifier_3d.cpp b/scene/3d/xr_body_modifier_3d.cpp index 3414ce13ae29..477241947aff 100644 --- a/scene/3d/xr_body_modifier_3d.cpp +++ b/scene/3d/xr_body_modifier_3d.cpp @@ -311,18 +311,22 @@ void XRBodyModifier3D::_update_skeleton() { return; } - // Read the relevant tracking data. + // Get the world and skeleton scale. + const float ws = xr_server->get_world_scale(); + const float ss = skeleton->get_motion_scale(); + + // Read the relevant tracking data. This applies the skeleton motion scale to + // the joint transforms, allowing the tracking data to be scaled to the skeleton. bool has_valid_data[XRBodyTracker::JOINT_MAX]; Transform3D transforms[XRBodyTracker::JOINT_MAX]; Transform3D inv_transforms[XRBodyTracker::JOINT_MAX]; - const float ws = xr_server->get_world_scale(); for (int joint = 0; joint < XRBodyTracker::JOINT_MAX; joint++) { BitField flags = tracker->get_joint_flags(static_cast(joint)); has_valid_data[joint] = flags.has_flag(XRBodyTracker::JOINT_FLAG_ORIENTATION_VALID) && flags.has_flag(XRBodyTracker::JOINT_FLAG_POSITION_VALID); if (has_valid_data[joint]) { transforms[joint] = tracker->get_joint_transform(static_cast(joint)); - transforms[joint].origin *= ws; + transforms[joint].origin *= ss; inv_transforms[joint] = transforms[joint].inverse(); } } @@ -353,8 +357,9 @@ void XRBodyModifier3D::_update_skeleton() { const int parent_joint = joints[joint].parent_joint; const Transform3D relative_transform = inv_transforms[parent_joint] * transforms[joint]; - // Update the bone position if enabled by update mode. - if (bone_update == BONE_UPDATE_FULL) { + // Update the bone position if enabled by update mode, or if the joint is the hips, to allow + // for climbing or crouching. + if (bone_update == BONE_UPDATE_FULL || joint == XRBodyTracker::JOINT_HIPS) { skeleton->set_bone_pose_position(joints[joint].bone, relative_transform.origin); } @@ -362,8 +367,10 @@ void XRBodyModifier3D::_update_skeleton() { skeleton->set_bone_pose_rotation(joints[joint].bone, Quaternion(relative_transform.basis)); } - // Transform to the skeleton pose. - set_transform(transforms[XRBodyTracker::JOINT_ROOT]); + // Transform to the tracking data root pose. This also applies the XR world-scale to allow + // scaling the avatars mesh and skeleton appropriately (if they are child nodes). + set_transform( + transforms[XRBodyTracker::JOINT_ROOT] * ws); // If tracking-state determines visibility then show the node. if (show_when_tracked) {