182 lines
4.9 KiB
C#
182 lines
4.9 KiB
C#
using System.Linq;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
using Valve.VR;
|
|
|
|
namespace LIV.SDK.Unity
|
|
{
|
|
[AddComponentMenu("LIV/ExternalCamera")]
|
|
public class ExternalCamera : MonoBehaviour
|
|
{
|
|
private TrackedDevicePose_t _trackedDevicePose;
|
|
|
|
private TrackedDevicePose_t[] _devices = new TrackedDevicePose_t[64];
|
|
|
|
private TrackedDevicePose_t[] _gameDevices = new TrackedDevicePose_t[64];
|
|
|
|
public bool IsValid
|
|
{
|
|
get
|
|
{
|
|
return OpenVRTrackedDeviceId != uint.MaxValue;
|
|
}
|
|
}
|
|
|
|
public uint OpenVRTrackedDeviceId { get; protected set; }
|
|
|
|
private void OnEnable()
|
|
{
|
|
InvokeRepeating("UpdateOpenVRDevice", 0.5f, 0.5f);
|
|
UpdateOpenVRDevice();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
CancelInvoke("UpdateOpenVRDevice");
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
UpdateCamera();
|
|
}
|
|
|
|
private void OnPreCull()
|
|
{
|
|
UpdateCamera();
|
|
}
|
|
|
|
private void UpdateCamera()
|
|
{
|
|
if (OpenVRTrackedDeviceId == uint.MaxValue)
|
|
{
|
|
return;
|
|
}
|
|
UpdateOpenVRPose();
|
|
if (!_trackedDevicePose.bDeviceIsConnected)
|
|
{
|
|
UpdateOpenVRDevice();
|
|
if (OpenVRTrackedDeviceId == uint.MaxValue)
|
|
{
|
|
return;
|
|
}
|
|
UpdateOpenVRPose();
|
|
}
|
|
UpdateTransform(_trackedDevicePose.mDeviceToAbsoluteTracking);
|
|
}
|
|
|
|
private void UpdateOpenVRPose()
|
|
{
|
|
if (OpenVR.Compositor.GetLastPoses(_devices, _gameDevices) == EVRCompositorError.None)
|
|
{
|
|
_trackedDevicePose = _devices[OpenVRTrackedDeviceId];
|
|
}
|
|
}
|
|
|
|
private void UpdateTransform(HmdMatrix34_t deviceToAbsolute)
|
|
{
|
|
Matrix4x4 identity = Matrix4x4.identity;
|
|
identity[0, 0] = deviceToAbsolute.m0;
|
|
identity[0, 1] = deviceToAbsolute.m1;
|
|
identity[0, 2] = 0f - deviceToAbsolute.m2;
|
|
identity[0, 3] = deviceToAbsolute.m3;
|
|
identity[1, 0] = deviceToAbsolute.m4;
|
|
identity[1, 1] = deviceToAbsolute.m5;
|
|
identity[1, 2] = 0f - deviceToAbsolute.m6;
|
|
identity[1, 3] = deviceToAbsolute.m7;
|
|
identity[2, 0] = 0f - deviceToAbsolute.m8;
|
|
identity[2, 1] = 0f - deviceToAbsolute.m9;
|
|
identity[2, 2] = deviceToAbsolute.m10;
|
|
identity[2, 3] = 0f - deviceToAbsolute.m11;
|
|
base.transform.localPosition = identity.GetPosition();
|
|
base.transform.localRotation = identity.GetRotation();
|
|
}
|
|
|
|
private void UpdateOpenVRDevice()
|
|
{
|
|
OpenVRTrackedDeviceId = IdentifyExternalCameraDevice();
|
|
}
|
|
|
|
private uint IdentifyExternalCameraDevice()
|
|
{
|
|
EVRCompositorError lastPoses = OpenVR.Compositor.GetLastPoses(_devices, _gameDevices);
|
|
if (lastPoses != EVRCompositorError.None)
|
|
{
|
|
Debug.Log("Encountered an error whilst looking for the external camera: " + lastPoses);
|
|
return uint.MaxValue;
|
|
}
|
|
var source = (from candidate in _devices.Select((TrackedDevicePose_t pose, int index) => new
|
|
{
|
|
pose = pose,
|
|
index = (uint)index
|
|
})
|
|
where candidate.pose.bDeviceIsConnected
|
|
select new
|
|
{
|
|
pose = candidate.pose,
|
|
index = candidate.index,
|
|
deviceClass = OpenVR.System.GetTrackedDeviceClass(candidate.index)
|
|
} into candidate
|
|
where candidate.deviceClass == ETrackedDeviceClass.Controller || candidate.deviceClass == ETrackedDeviceClass.GenericTracker
|
|
select new
|
|
{
|
|
pose = candidate.pose,
|
|
index = candidate.index,
|
|
deviceClass = candidate.deviceClass,
|
|
deviceRole = OpenVR.System.GetControllerRoleForTrackedDeviceIndex(candidate.index),
|
|
modelNumber = GetStringTrackedDeviceProperty(candidate.index, ETrackedDeviceProperty.Prop_ModelNumber_String),
|
|
renderModel = GetStringTrackedDeviceProperty(candidate.index, ETrackedDeviceProperty.Prop_RenderModelName_String)
|
|
}).OrderByDescending(candidate =>
|
|
{
|
|
if (candidate.modelNumber == "LIV Virtual Camera")
|
|
{
|
|
return 10;
|
|
}
|
|
if (candidate.modelNumber == "Virtual Controller Device")
|
|
{
|
|
return 9;
|
|
}
|
|
if (candidate.deviceClass == ETrackedDeviceClass.GenericTracker)
|
|
{
|
|
return 5;
|
|
}
|
|
if (candidate.deviceClass == ETrackedDeviceClass.Controller)
|
|
{
|
|
if (candidate.renderModel == "{htc}vr_tracker_vive_1_0")
|
|
{
|
|
return 8;
|
|
}
|
|
if (candidate.deviceRole == ETrackedControllerRole.OptOut)
|
|
{
|
|
return 7;
|
|
}
|
|
if (candidate.deviceRole == ETrackedControllerRole.Invalid)
|
|
{
|
|
return 6;
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
});
|
|
var anon = source.FirstOrDefault();
|
|
return (anon == null) ? uint.MaxValue : anon.index;
|
|
}
|
|
|
|
private static string GetStringTrackedDeviceProperty(uint device, ETrackedDeviceProperty property)
|
|
{
|
|
StringBuilder stringBuilder = new StringBuilder(1024);
|
|
ETrackedPropertyError pError = ETrackedPropertyError.TrackedProp_Success;
|
|
OpenVR.System.GetStringTrackedDeviceProperty(device, property, stringBuilder, 1024u, ref pError);
|
|
switch (pError)
|
|
{
|
|
case ETrackedPropertyError.TrackedProp_Success:
|
|
return stringBuilder.ToString();
|
|
case ETrackedPropertyError.TrackedProp_UnknownProperty:
|
|
return string.Empty;
|
|
default:
|
|
Debug.Log("Encountered an error whilst reading a tracked device property: " + pError);
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|