How does VR controller position works?
I'm trying to understand what position I get when I try to get vr devicePosition/deviceRotation. Seems like every hmd model returns the position in a different way. I have also noticed that when using steam vr all models return positions in a common pivot, so that whatever the model you're using the your hand will feel right.
My real question here is if there's an "offsets table" that I could use to make all devicePosition/rotation return something that's similar and not completely different from one device to another. Is this documented anywhere? It's being very hard to make my hand model match in every platform without using steamvr, I'll have to have an offset for each device, which I'll have to deduce manually.
In this image attached I have the oculus rift s controller model for steam vr and the official model, they have quite a big offset.
Also, the same problem happens for windows mixed reality
I am having the same issue using OpenXR and the new Input System. All Oculus and Vive controllers work fine, but WMR and the Valve Index differ somehow, resulting in incorrect offsets for my hands :(
Answer by eblavender · Jan 19 at 10:51 AM
@Chimer0s I had to do this manually unfortunately, but i made this script that will set offsets for you based on the controller type. See image for values.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
public class OpenXRHandOffset : MonoBehaviour
{
[SerializeField] private Transform leftOffset, rightOffset;
[Header("Oculus")]
[SerializeField] private Vector3 oculusPosition;
[SerializeField] private Vector3 oculusRotation;
[Header("Windows MR")]
[SerializeField] private Vector3 windowsPosition;
[SerializeField] private Vector3 windowsRotation;
[Header("Index")]
[SerializeField] private Vector3 indexPosition;
[SerializeField] private Vector3 indexRotation;
[Header("Vive")]
[SerializeField] private Vector3 vivePosition;
[SerializeField] private Vector3 viveRotation;
void OnEnable()
{
InputDevices.deviceConnected += DeviceConnected;
List<InputDevice> devices = new List<InputDevice>();
InputDevices.GetDevices(devices);
foreach (var device in devices)
DeviceConnected(device);
}
void OnDisable()
{
InputDevices.deviceConnected -= DeviceConnected;
}
void DeviceConnected(InputDevice device)
{
// The Left Hand
if (device.characteristics == 0)
return;
if (device.name.Contains("Oculus"))
{
leftOffset.localPosition = new Vector3(-oculusPosition.x, oculusPosition.y, oculusPosition.z);
leftOffset.localEulerAngles = new Vector3(oculusRotation.x, -oculusRotation.y, -oculusRotation.z);
rightOffset.localPosition = oculusPosition;
rightOffset.localEulerAngles = oculusRotation;
}
else if (device.name.Contains("Windows"))
{
leftOffset.localPosition = new Vector3(-windowsPosition.x, windowsPosition.y, windowsPosition.z);
leftOffset.localEulerAngles = new Vector3(windowsRotation.x, -windowsRotation.y, -windowsRotation.z);
rightOffset.localPosition = windowsPosition;
rightOffset.localEulerAngles = windowsRotation;
}
else if (device.name.Contains("Index"))
{
leftOffset.localPosition = new Vector3(-indexPosition.x, indexPosition.y, indexPosition.z);
leftOffset.localEulerAngles = new Vector3(indexRotation.x, -indexRotation.y, -indexRotation.z);
rightOffset.localPosition = indexPosition;
rightOffset.localEulerAngles = indexRotation;
}
else if (device.name.Contains("Elite")) //Cosmos Elite
{
leftOffset.localPosition = new Vector3(-vivePosition.x, vivePosition.y, vivePosition.z);
leftOffset.localEulerAngles = new Vector3(viveRotation.x, -viveRotation.y, -viveRotation.z);
rightOffset.localPosition = vivePosition;
rightOffset.localEulerAngles = viveRotation;
}
else if (device.name.Contains("Cosmos")) //Cosmos
{
leftOffset.localPosition = new Vector3(-oculusPosition.x, oculusPosition.y, oculusPosition.z);
leftOffset.localEulerAngles = new Vector3(oculusRotation.x, -oculusRotation.y, -oculusRotation.z);
rightOffset.localPosition = oculusPosition;
rightOffset.localEulerAngles = oculusRotation;
}
else if (device.name.Contains("HTC")) // Vive
{
leftOffset.localPosition = new Vector3(-vivePosition.x, vivePosition.y, vivePosition.z);
leftOffset.localEulerAngles = new Vector3(viveRotation.x, -viveRotation.y, -viveRotation.z);
rightOffset.localPosition = vivePosition;
rightOffset.localEulerAngles = viveRotation;
}
else
{
print(device.name + " does not exist in the current offset list");
return;
}
OnDisable();
print(device.name);
}
}
Yeah I figured there wouldn't already be one. I actually came up with the same solution basically and have decided to get the values manually myself, as well. Thanks for sharing your solution and values!
Answer by Chimer0s · Jan 19 at 03:30 AM
Out of curiosity did you ever find the resource you were looking for with the offsets for each controller type? I'm in the same boat. I loved how SteamVR automatically aligned the controllers depending on their manufacturer. I'm disappointed to see that OpenXR doesn't.
Your answer
Follow this Question
Related Questions
Mechanics in VR? 0 Answers
Touch controllers Steam VR not showing 0 Answers
I can't access play mode with Oculus 0 Answers
(XR Input) Why does Oculus Rift work fine, but HTC Vive inputs stays at 0 ? 0 Answers