Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bone update option to OpenXRHand to allow preserving original hand scale #87240

Merged
merged 1 commit into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions modules/openxr/doc_classes/OpenXRHand.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
This node enables OpenXR's hand tracking functionality. The node should be a child node of an [XROrigin3D] node, tracking will update its position to the player's tracked hand Palm joint location (the center of the middle finger's metacarpal bone). This node also updates the skeleton of a properly skinned hand or avatar model.
If the skeleton is a hand (one of the hand bones is the root node of the skeleton), then the skeleton will be placed relative to the hand palm location and the hand mesh and skeleton should be children of the OpenXRHand node.
If the hand bones are part of a full skeleton, then the root of the hand will keep its location with the assumption that IK is used to position the hand and arm.
By default the skeleton hand bones are repositioned to match the size of the tracked hand. To preserve the modeled bone sizes change [member bone_update] to apply rotation only.
</description>
<tutorials>
</tutorials>
<members>
<member name="bone_update" type="int" setter="set_bone_update" getter="get_bone_update" enum="OpenXRHand.BoneUpdate" default="0">
Specify the type of updates to perform on the bone.
</member>
<member name="hand" type="int" setter="set_hand" getter="get_hand" enum="OpenXRHand.Hands" default="0">
Specifies whether this node tracks the left or right hand of the player.
</member>
Expand Down Expand Up @@ -52,5 +56,14 @@
<constant name="SKELETON_RIG_MAX" value="2" enum="SkeletonRig">
Maximum supported hands.
</constant>
<constant name="BONE_UPDATE_FULL" value="0" enum="BoneUpdate">
The skeletons bones are fully updated (both position and rotation) to match the tracked bones.
</constant>
<constant name="BONE_UPDATE_ROTATION_ONLY" value="1" enum="BoneUpdate">
The skeletons bones are only rotated to align with the tracked bones, preserving bone length.
</constant>
<constant name="BONE_UPDATE_MAX" value="2" enum="BoneUpdate">
Maximum supported bone update mode.
</constant>
</constants>
</class>
26 changes: 24 additions & 2 deletions modules/openxr/scene/openxr_hand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,14 @@ void OpenXRHand::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_skeleton_rig", "skeleton_rig"), &OpenXRHand::set_skeleton_rig);
ClassDB::bind_method(D_METHOD("get_skeleton_rig"), &OpenXRHand::get_skeleton_rig);

ClassDB::bind_method(D_METHOD("set_bone_update", "bone_update"), &OpenXRHand::set_bone_update);
ClassDB::bind_method(D_METHOD("get_bone_update"), &OpenXRHand::get_bone_update);

ADD_PROPERTY(PropertyInfo(Variant::INT, "hand", PROPERTY_HINT_ENUM, "Left,Right"), "set_hand", "get_hand");
ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_range", PROPERTY_HINT_ENUM, "Unobstructed,Conform to controller"), "set_motion_range", "get_motion_range");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "hand_skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton3D"), "set_hand_skeleton", "get_hand_skeleton");
ADD_PROPERTY(PropertyInfo(Variant::INT, "skeleton_rig", PROPERTY_HINT_ENUM, "OpenXR,Humanoid"), "set_skeleton_rig", "get_skeleton_rig");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_update", PROPERTY_HINT_ENUM, "Full,Rotation Only"), "set_bone_update", "get_bone_update");

BIND_ENUM_CONSTANT(HAND_LEFT);
BIND_ENUM_CONSTANT(HAND_RIGHT);
Expand All @@ -65,6 +69,10 @@ void OpenXRHand::_bind_methods() {
BIND_ENUM_CONSTANT(SKELETON_RIG_OPENXR);
BIND_ENUM_CONSTANT(SKELETON_RIG_HUMANOID);
BIND_ENUM_CONSTANT(SKELETON_RIG_MAX);

BIND_ENUM_CONSTANT(BONE_UPDATE_FULL);
BIND_ENUM_CONSTANT(BONE_UPDATE_ROTATION_ONLY);
BIND_ENUM_CONSTANT(BONE_UPDATE_MAX);
}

OpenXRHand::OpenXRHand() {
Expand Down Expand Up @@ -134,6 +142,16 @@ OpenXRHand::SkeletonRig OpenXRHand::get_skeleton_rig() const {
return skeleton_rig;
}

void OpenXRHand::set_bone_update(BoneUpdate p_bone_update) {
ERR_FAIL_INDEX(p_bone_update, BONE_UPDATE_MAX);

bone_update = p_bone_update;
}

OpenXRHand::BoneUpdate OpenXRHand::get_bone_update() const {
return bone_update;
}

Skeleton3D *OpenXRHand::get_skeleton() {
if (!has_node(hand_skeleton)) {
return nullptr;
Expand Down Expand Up @@ -346,8 +364,12 @@ void OpenXRHand::_update_skeleton() {
const Quaternion q = inv_quaternions[parent_joint] * quaternions[joint];
const Vector3 p = inv_quaternions[parent_joint].xform(positions[joint] - positions[parent_joint]);

// and set our pose
skeleton->set_bone_pose_position(joints[joint].bone, p);
// Update the bone position if enabled by update mode.
if (bone_update == BONE_UPDATE_FULL) {
skeleton->set_bone_pose_position(joints[joint].bone, p);
}

// Always update the bone rotation.
skeleton->set_bone_pose_rotation(joints[joint].bone, q);
}

Expand Down
11 changes: 11 additions & 0 deletions modules/openxr/scene/openxr_hand.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ class OpenXRHand : public Node3D {
SKELETON_RIG_MAX
};

enum BoneUpdate {
BONE_UPDATE_FULL,
BONE_UPDATE_ROTATION_ONLY,
BONE_UPDATE_MAX
};

private:
struct JointData {
int bone = -1;
Expand All @@ -74,6 +80,7 @@ class OpenXRHand : public Node3D {
MotionRange motion_range = MOTION_RANGE_UNOBSTRUCTED;
NodePath hand_skeleton;
SkeletonRig skeleton_rig = SKELETON_RIG_OPENXR;
BoneUpdate bone_update = BONE_UPDATE_FULL;

JointData joints[XR_HAND_JOINT_COUNT_EXT];

Expand Down Expand Up @@ -101,11 +108,15 @@ class OpenXRHand : public Node3D {
void set_skeleton_rig(SkeletonRig p_skeleton_rig);
SkeletonRig get_skeleton_rig() const;

void set_bone_update(BoneUpdate p_bone_update);
BoneUpdate get_bone_update() const;

void _notification(int p_what);
};

VARIANT_ENUM_CAST(OpenXRHand::Hands)
VARIANT_ENUM_CAST(OpenXRHand::MotionRange)
VARIANT_ENUM_CAST(OpenXRHand::SkeletonRig)
VARIANT_ENUM_CAST(OpenXRHand::BoneUpdate)

#endif // OPENXR_HAND_H
Loading