Arms IK puts the model's wrist on the controller's aim-pose origin (the controller tip) #20
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type: bug (VR feel), needs headset confirmation Priority: medium Area:
scenes/player_rig.tscn,src/player/player_rig.gd,src/player/arms_view.gdSummary
The rig's hand nodes track the OpenXR aim pose, and
ArmsViewputs the model'sHandbone (the wrist) exactly on that pose's origin, with no positional offset.The aim origin is where the pointing ray starts, usually at the front tip of the controller. So the rendered wrist sits near the front of the controller, roughly where the player's fingers are. The whole model hand sits forward of the real hand by something like a hand's length, and the forearm reads correspondingly long.
Evidence
scenes/player_rig.tscn:21-23and:33-35: both controllers use the aim pose.src/player/arms_view.gd:187,:216and:230: the controller origin becomes the IK target, and the solved wrist goes on it.HAND_OFFSET(arms_view.gd:58-61) is a rotation only, and its comment (:54-57) calls it a "blind first guess". It carries over the old HandView rotations from4c9256d, which were set for the aim pose (hand pitched about 60 degrees below the aim ray).What the poses mean. From the OpenXR 1.0 spec, Standard pose identifiers:
What the vendored XR Tools does with the same choice:
addons/godot-xr-tools/hands/scenes/lowpoly/left_hand_low.tscn:47: its stock hand mesh sits atTransform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, -0.05, 0.15), 15 cm back, 5 cm down and 3 cm to the side of the controller origin. That is the offset XR Tools computes at runtime for an aim-pose parent: the aim offset inaddons/godot-xr-tools/xr_tools.gd:352-357combined with the base offset inaddons/godot-xr-tools/hands/hand.gd:146. The comment atxr_tools.gd:352-353says those aim offsets are no longer reliable on many headsets.addons/godot-xr-tools/hands/hand_palm_offset.gd:81raises a configuration warning on aim-pose controllers, saying the aim pose "is no longer suitable for hand position" and suggesting the grip pose.DEAD AIR applies neither the offset nor the grip pose.
Proposed fix
Keep the aim pose for what it is for, the laser pointers and movement providers, and drive the arms from the grip pose.
player_rig.tscn, add grip-tracking controllers next to the existing ones. The action map already has agrip_poseaction for both hands (openxr_action_map.tres:163).player_rig.gd, feed those to the arms. Input reads (get_float) go through the tracker, not the pose, so finger curl keeps working from the grip nodes.arms_view.gd, put the wrist behind the palm instead of on it. Add a per-sideWRIST_OFFSETin grip space and apply it before solving:Then re-tune
HAND_OFFSETfor grip space. Its current values were set against the aim pose's axes (see the4c9256dnote above).The offset values are deliberately left at zero here. The grip axes are defined relative to the hand, but the right numbers depend on this model's wrist-to-palm proportions, so measure rather than guess.
Once the target sits at the real wrist, re-check
ARM_LENGTH_SCALE(1.2,arms_view.gd:52). It came in with1dd3cf2as the fix for hands stopping short, and today part of the extra reach it buys is spent reaching a target that sits too far forward. With a correct target, the same multiplier may leave elbows too straight. It is Zach's carried-over Resonite setting, so this is a feel check, not a change request.Timing
Tuning needs a headset and should happen after PR #14 lands, since #14 changes the same rig: the arms anchor in
player_rig.gd, plus the chest offset insideArmsView.solve_sidethat the #14 review agreed on and that has not been pushed yet. Offsets measured earlier would be measured against a moving target.How to verify
In the headset, with the arms visible:
The debug bridge's
solve_arm(addons/da_debug_bridge/debug_bridge.gd:358) takes a world-space target and callsArmsView.solve_sidedirectly, so it skipsupdate_armsand is unaffected by the fix. The bridge has no command to set a controller pose, so it can't reproduce the bug on its own. A camera-POV bridge screenshot can still compare the two placements if you pass the old and new wrist positions as targets yourself.