I don’t know if anyone else has tried to do this yet, but I found that it’s important to calibrate the Vive to the height of the player. Since UE4 uses centimeters and because it is superior, I’ll use that for my units of measurement.
For the Vive, my camera has to be placed at the feet of the in-game character. When the player puts the camera on their head, they raise the camera and displace it by the appropriate Z value. Let’s say you have a character avatar which stands at 170cm and their eye height is at about 165cm. When players play your game, they will be of various heights! What if the player height doesn’t match the avatar height? I happen to be 170cm, which is coincidentally the height of my character. However, what if I was 200cm or 140cm in height? It’s not reasonable to create avatars which are taller and shorter, so what is better to do is to adjust the players eye height to the eye height of the in-game avatar. Also, keep in mind that you will want to measure player arm lengths for really good motion controller animation stuff!
Measuring the Player:
So, I instruct the player to stand straight up and hold their arms straight down at their sides. When they are ready to calibrate, they pull both triggers of each hand controller at the same time. Since the Vive measures the HMD height as a total displacement from the floor, you can effectively grab the players height in centimeters off of the device position Z value! I also know the exact position of the hand controllers as a displacement from the ground, so we can also measure the arm lengths. If you want to be extra precise with arm lengths, you can instruct the player to hold arms at side for one calibration test, then hold them straight up for a second calibration test, and then hold them out in a T-pose for last calibration test.
You may also want to grab a ratio of the player height to the avatar height so that you can correctly animate the avatar bones.
Compensating for height
After you get the players eye height, you have to get a delta against the characters eye height. For my own testing, I placed a stool in the middle of the room (at character location so I know where it is in VR! be safe guys!) and gained 30cm in height displacement. This is useful for testing. Let’s assume that I have a +30cm Z value from the character eye height. My characters default camera location offset from the characters origin [0,0,0] is set to [0,0,-90] (character feet). Don’t change this value directly. Within the character construction script, I detect whether we’re using a Vive or a Rift and set the offset values accordingly. Now, what if a player is 30cm taller? To get the camera to the avatars eye height, you want to subtract 30cm from the base height, so [0,0,-90] - [0,0,30] becomes [0,0,-120]. When the player stands up straight, they’ll move through the height discrepency to hit avatar eye height. You will also want to apply this same height delta to the Z value of your motion controllers positions!
Compensating for initial rotation
One other really important part which I missed initially is that you want to grab the starting rotation of the avatar at the game start. This is going to be a global rotation offset which you need to apply to the HMD so that the player head position and the character head position and rotation match exactly. If your player start rotation is [0,0,0], this isn’t necessary – but you can’t guarantee or assume level designers will know this is important and you don’t want to tell them they need to use zero rotation.
Blueprint Pseudo-code:
FVector HMDOffset (default: [0,0,0])
If Vive: [0,0,-90]
If Rift: [0,0,70]
float GetHMDHeight()
return HMDDevice.Position.Z;
float GetAvatarEyeHeight()
return 165;
FVector PlayerHeightDelta = [0,0,GetHMDHeight - GetAvatarHeight];
Camera->SetRelativeLocation(HMDOffset - PlayerHeightDelta);
//construction script
const FRotator HMDRotationOffset = GetActorRotation();
FVector GetHMDWorldPos()
RotateVector(HMDDevice.Position, HMDRotationOffset) + GetActorLocation() + HMDOffset;
bool IsUsingRift()
return GetRawSensorData.Temperature > 0;
FTransform GetMotionController(bool left)
{
FTransform returnVal;
if(left)
{
returnVal.Position = (LeftMotionControllerComponent->GetWorldLocation() + HMDOffset) - PlayerHeightDelta;
returnVal.Rotation = LeftMotionControllerComponent->GetWorldRotation();
}
else
{
returnVal.Position = (RightMotionControllerComponent->GetWorldLocation() + HMDOffset) - PlayerHeightDelta;
returnVal.Rotation = RightMotionControllerComponent->GetWorldRotation();
}
return returnVal;
}
I hope this helps anyone speed up their head and hand tracking capabilities and to account for differences in player heights This should be generalized enough that it’s capable of supporting Oculus Touch whenever it becomes available.