How To: Find the Player Wrist Position (Vive, Rift, Leap Motion)

If you are using full body avatars in VR, you’ll eventually find that you want to know exactly where the players wrist is located so you can match the avatar wrist to the same location via inverse kinematics. The wrist location is going to be the pivot point for the motion controller, so when a player turns their wrist, the motion controller pivots around this position.

My approach is to do a part of this in C++ code (which you can convert to blueprints if you want), and the second part is done in blueprints. The blueprint section is to handle the Leap Motion plugin. I created a function which returns the wrist position in world space, so my reasoning is that if the leap motion is connected and a hand is being tracked, we should return the wrist position reported by the leap motion because it has a camera which is looking at the physical wrist position. IF the leap motion isn’t tracking a hand, we will default to deriving the hand position from the motion controller position. This is super straight forward because we can pretty much assume that everyone holds the motion controllers exactly the same way, so we can apply a constant offset from the motion controller position and rotate it by the motion controller orientation. These constants are as follows:

**Vive Left: ** FVector(-13,-3, 0)
**Vive Right: ** FVector(-14, 3, 0)
**Rift Left: ** FVector(-9,-2, -4)
**Rift Right: ** FVector(-9, 2, -4)

Here is my C++ code to get the wrist position:



//Get the wrist position in world space location coordinates.
FVector AVRHead::GetWristWSL_Implementation(bool Left)
{

	if (UsingMotionControllers())
	{
		FVector Pos = (Left) ? LeftMC->GetComponentLocation() : RightMC->GetComponentLocation();
		FRotator Rot = (Left) ? LeftMC->GetComponentRotation() : RightMC->GetComponentRotation();

		FVector ForwardOffset = FVector(0, 0, 0);
		switch (DisplayType)
		{
			case EHMDDeviceType::HTCVive :
			{
				ForwardOffset = (Left) ? FVector(-14, -3, 0) : FVector(-14, 3, 0);
				break;
			}
			case EHMDDeviceType::OculusRift :
			{
				ForwardOffset = (Left) ? FVector(-9, -2, -4) : FVector(-9, 2, -4); 
				break;
			}
			default:break;
		}

		ForwardOffset = Rot.RotateVector(ForwardOffset);
		return Pos + ForwardOffset;
	}

	return FVector::ZeroVector;
}


Here is my blueprint implementation which extends the C++ version and adds support for the leap motion:


Basically, if the leap motion section of the blueprint fails, then we fall back to the C++ code and look for the motion controller positions and derive a location.

If there are no motion controllers or leap motion devices and we’re using a monitor, we’ll want to setup our animation blueprint to just use a premade animation with hands at the default position.

When you can accurately map the character wrist position to the player wrist position, you create a lot more immersion and presence in VR :slight_smile: You’ll probably also want to have a derived palm position (relative to wrist position) so that you can put any held objects to this location.