mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 14:53:50 +02:00
v2019.08.19
This commit is contained in:
415
VRCXVR.cs
415
VRCXVR.cs
@@ -21,7 +21,7 @@ namespace VRCX
|
||||
{
|
||||
public static class VRCXVR
|
||||
{
|
||||
private static readonly object m_LockObject = new object();
|
||||
private static readonly ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
|
||||
private static List<string[]> m_Devices = new List<string[]>();
|
||||
private static Thread m_Thread;
|
||||
private static Device m_Device;
|
||||
@@ -29,6 +29,7 @@ namespace VRCX
|
||||
private static Texture2D m_Texture2;
|
||||
private static Browser m_Browser1;
|
||||
private static Browser m_Browser2;
|
||||
private static bool m_Active;
|
||||
private static float[] m_Rotation = { 0f, 0f, 0f };
|
||||
private static float[] m_Translation = { 0f, 0f, 0f };
|
||||
private static float[] m_L_Translation = { -7f / 100f, -5f / 100f, 6f / 100f };
|
||||
@@ -38,7 +39,7 @@ namespace VRCX
|
||||
|
||||
// NOTE
|
||||
// 메모리 릭 때문에 미리 생성해놓고 계속 사용함
|
||||
public static void Setup()
|
||||
public static void Init()
|
||||
{
|
||||
m_Device = new Device(DriverType.Hardware, DeviceCreationFlags.SingleThreaded | DeviceCreationFlags.BgraSupport);
|
||||
m_Texture1 = new Texture2D(m_Device, new Texture2DDescription()
|
||||
@@ -67,38 +68,139 @@ namespace VRCX
|
||||
});
|
||||
m_Browser1 = new Browser(m_Texture1, Application.StartupPath + "/html/vr.html?1");
|
||||
m_Browser2 = new Browser(m_Texture2, Application.StartupPath + "/html/vr.html?2");
|
||||
}
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
lock (m_LockObject)
|
||||
m_Thread = new Thread(() =>
|
||||
{
|
||||
if (m_Thread == null)
|
||||
var active = false;
|
||||
var e = new VREvent_t();
|
||||
var nextInit = DateTime.MinValue;
|
||||
var nextDeviceUpdate = DateTime.MinValue;
|
||||
var nextOverlay = DateTime.MinValue;
|
||||
var overlayIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
|
||||
var overlayVisible1 = false;
|
||||
var overlayVisible2 = false;
|
||||
var dashboardHandle = 0UL;
|
||||
var overlayHandle1 = 0UL;
|
||||
var overlayHandle2 = 0UL;
|
||||
while (m_Thread != null)
|
||||
{
|
||||
m_Thread = new Thread(ThreadProc);
|
||||
m_Thread.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
lock (m_LockObject)
|
||||
{
|
||||
var thread = m_Thread;
|
||||
if (thread != null)
|
||||
{
|
||||
m_Thread = null;
|
||||
try
|
||||
{
|
||||
thread.Interrupt();
|
||||
thread.Join();
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ThreadInterruptedException
|
||||
}
|
||||
if (m_Active)
|
||||
{
|
||||
m_Browser1.Render();
|
||||
m_Browser2.Render();
|
||||
var system = OpenVR.System;
|
||||
if (system == null)
|
||||
{
|
||||
if (DateTime.Now.CompareTo(nextInit) <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var _err = EVRInitError.None;
|
||||
system = OpenVR.Init(ref _err, EVRApplicationType.VRApplication_Overlay);
|
||||
nextInit = DateTime.Now.AddSeconds(5);
|
||||
if (system == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
active = true;
|
||||
}
|
||||
while (system.PollNextEvent(ref e, (uint)Marshal.SizeOf(e)))
|
||||
{
|
||||
var type = (EVREventType)e.eventType;
|
||||
if (type == EVREventType.VREvent_Quit)
|
||||
{
|
||||
active = false;
|
||||
OpenVR.Shutdown();
|
||||
nextInit = DateTime.Now.AddSeconds(10);
|
||||
system = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (system != null)
|
||||
{
|
||||
if (DateTime.Now.CompareTo(nextDeviceUpdate) >= 0)
|
||||
{
|
||||
overlayIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
|
||||
UpdateDevices(system, ref overlayIndex);
|
||||
if (overlayIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
|
||||
{
|
||||
nextOverlay = DateTime.Now.AddSeconds(10);
|
||||
}
|
||||
nextDeviceUpdate = DateTime.Now.AddSeconds(0.1);
|
||||
}
|
||||
var overlay = OpenVR.Overlay;
|
||||
if (overlay != null)
|
||||
{
|
||||
var dashboardVisible = overlay.IsDashboardVisible();
|
||||
var err = ProcessDashboard(overlay, ref dashboardHandle, dashboardVisible);
|
||||
if (err != EVROverlayError.None &&
|
||||
dashboardHandle != 0)
|
||||
{
|
||||
overlay.DestroyOverlay(dashboardHandle);
|
||||
dashboardHandle = 0;
|
||||
}
|
||||
err = ProcessOverlay1(overlay, ref overlayHandle1, ref overlayVisible1, dashboardVisible, overlayIndex, nextOverlay);
|
||||
if (err != EVROverlayError.None &&
|
||||
overlayHandle1 != 0)
|
||||
{
|
||||
overlay.DestroyOverlay(overlayHandle1);
|
||||
overlayHandle1 = 0;
|
||||
}
|
||||
err = ProcessOverlay2(overlay, ref overlayHandle2, ref overlayVisible2, dashboardVisible);
|
||||
if (err != EVROverlayError.None &&
|
||||
overlayHandle2 != 0)
|
||||
{
|
||||
overlay.DestroyOverlay(overlayHandle2);
|
||||
overlayHandle2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (active)
|
||||
{
|
||||
active = false;
|
||||
OpenVR.Shutdown();
|
||||
m_Lock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
m_Devices.Clear();
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_Lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
m_Thread.Start();
|
||||
}
|
||||
|
||||
public static void Exit()
|
||||
{
|
||||
var T = m_Thread;
|
||||
m_Thread = null;
|
||||
T.Interrupt();
|
||||
T.Join();
|
||||
m_Browser2.Dispose();
|
||||
m_Browser1.Dispose();
|
||||
m_Texture2.Dispose();
|
||||
m_Texture1.Dispose();
|
||||
m_Device.Dispose();
|
||||
}
|
||||
|
||||
public static void SetActive(bool active)
|
||||
{
|
||||
m_Active = active;
|
||||
}
|
||||
|
||||
public static void Refresh()
|
||||
@@ -109,86 +211,105 @@ namespace VRCX
|
||||
|
||||
public static string[][] GetDevices()
|
||||
{
|
||||
lock (m_Devices)
|
||||
m_Lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
return m_Devices.ToArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_Lock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateDevices(CVRSystem system, ref uint trackingIndex)
|
||||
private static void UpdateDevices(CVRSystem system, ref uint overlayIndex)
|
||||
{
|
||||
lock (m_Devices)
|
||||
m_Lock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
m_Devices.Clear();
|
||||
var sb = new StringBuilder(256);
|
||||
var state = new VRControllerState_t();
|
||||
for (var i = 0u; i < OpenVR.k_unMaxTrackedDeviceCount; ++i)
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_Lock.ExitWriteLock();
|
||||
}
|
||||
var sb = new StringBuilder(256);
|
||||
var state = new VRControllerState_t();
|
||||
for (var i = 0u; i < OpenVR.k_unMaxTrackedDeviceCount; ++i)
|
||||
{
|
||||
var devClass = system.GetTrackedDeviceClass(i);
|
||||
if (devClass == ETrackedDeviceClass.Controller ||
|
||||
devClass == ETrackedDeviceClass.GenericTracker)
|
||||
{
|
||||
var devClass = system.GetTrackedDeviceClass(i);
|
||||
if (devClass == ETrackedDeviceClass.Controller ||
|
||||
devClass == ETrackedDeviceClass.GenericTracker)
|
||||
var err = ETrackedPropertyError.TrackedProp_Success;
|
||||
var batteryPercentage = system.GetFloatTrackedDeviceProperty(i, ETrackedDeviceProperty.Prop_DeviceBatteryPercentage_Float, ref err);
|
||||
if (err != ETrackedPropertyError.TrackedProp_Success)
|
||||
{
|
||||
var err = ETrackedPropertyError.TrackedProp_Success;
|
||||
var batteryPercentage = system.GetFloatTrackedDeviceProperty(i, ETrackedDeviceProperty.Prop_DeviceBatteryPercentage_Float, ref err);
|
||||
if (err != ETrackedPropertyError.TrackedProp_Success)
|
||||
{
|
||||
batteryPercentage = 1f;
|
||||
}
|
||||
sb.Clear();
|
||||
system.GetStringTrackedDeviceProperty(i, ETrackedDeviceProperty.Prop_TrackingSystemName_String, sb, (uint)sb.Capacity, ref err);
|
||||
var isOculus = sb.ToString().IndexOf("oculus", StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
// Oculus : B/Y, Bit 1, Mask 2
|
||||
// Oculus : A/X, Bit 7, Mask 128
|
||||
// Vive : Menu, Bit 1, Mask 2,
|
||||
// Vive : Grip, Bit 2, Mask 4
|
||||
var role = system.GetControllerRoleForTrackedDeviceIndex(i);
|
||||
if (role == ETrackedControllerRole.LeftHand ||
|
||||
role == ETrackedControllerRole.RightHand)
|
||||
{
|
||||
if (system.GetControllerState(i, ref state, (uint)Marshal.SizeOf(state)) &&
|
||||
(state.ulButtonPressed & (isOculus ? 2u : 4u)) != 0)
|
||||
{
|
||||
if (role == ETrackedControllerRole.LeftHand)
|
||||
{
|
||||
Array.Copy(m_L_Translation, m_Translation, 3);
|
||||
Array.Copy(m_L_Rotation, m_Rotation, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(m_R_Translation, m_Translation, 3);
|
||||
Array.Copy(m_R_Rotation, m_Rotation, 3);
|
||||
}
|
||||
trackingIndex = i;
|
||||
}
|
||||
}
|
||||
var type = string.Empty;
|
||||
if (devClass == ETrackedDeviceClass.Controller)
|
||||
batteryPercentage = 1f;
|
||||
}
|
||||
sb.Clear();
|
||||
system.GetStringTrackedDeviceProperty(i, ETrackedDeviceProperty.Prop_TrackingSystemName_String, sb, (uint)sb.Capacity, ref err);
|
||||
var isOculus = sb.ToString().IndexOf("oculus", StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
// Oculus : B/Y, Bit 1, Mask 2
|
||||
// Oculus : A/X, Bit 7, Mask 128
|
||||
// Vive : Menu, Bit 1, Mask 2,
|
||||
// Vive : Grip, Bit 2, Mask 4
|
||||
var role = system.GetControllerRoleForTrackedDeviceIndex(i);
|
||||
if (role == ETrackedControllerRole.LeftHand ||
|
||||
role == ETrackedControllerRole.RightHand)
|
||||
{
|
||||
if (system.GetControllerState(i, ref state, (uint)Marshal.SizeOf(state)) &&
|
||||
(state.ulButtonPressed & (isOculus ? 2u : 4u)) != 0)
|
||||
{
|
||||
if (role == ETrackedControllerRole.LeftHand)
|
||||
{
|
||||
type = "leftController";
|
||||
}
|
||||
else if (role == ETrackedControllerRole.RightHand)
|
||||
{
|
||||
type = "rightController";
|
||||
Array.Copy(m_L_Translation, m_Translation, 3);
|
||||
Array.Copy(m_L_Rotation, m_Rotation, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = "controller";
|
||||
Array.Copy(m_R_Translation, m_Translation, 3);
|
||||
Array.Copy(m_R_Rotation, m_Rotation, 3);
|
||||
}
|
||||
overlayIndex = i;
|
||||
}
|
||||
else if (devClass == ETrackedDeviceClass.GenericTracker)
|
||||
}
|
||||
var type = string.Empty;
|
||||
if (devClass == ETrackedDeviceClass.Controller)
|
||||
{
|
||||
if (role == ETrackedControllerRole.LeftHand)
|
||||
{
|
||||
type = "tracker";
|
||||
type = "leftController";
|
||||
}
|
||||
m_Devices.Add(new[]
|
||||
else if (role == ETrackedControllerRole.RightHand)
|
||||
{
|
||||
type,
|
||||
system.IsTrackedDeviceConnected(i)
|
||||
? "connected"
|
||||
: "disconnected",
|
||||
(batteryPercentage * 100).ToString()
|
||||
});
|
||||
type = "rightController";
|
||||
}
|
||||
else
|
||||
{
|
||||
type = "controller";
|
||||
}
|
||||
}
|
||||
else if (devClass == ETrackedDeviceClass.GenericTracker)
|
||||
{
|
||||
type = "tracker";
|
||||
}
|
||||
var item = new[]
|
||||
{
|
||||
type,
|
||||
system.IsTrackedDeviceConnected(i)
|
||||
? "connected"
|
||||
: "disconnected",
|
||||
(batteryPercentage * 100).ToString()
|
||||
};
|
||||
m_Lock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
m_Devices.Add(item);
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_Lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,7 +388,7 @@ namespace VRCX
|
||||
return err;
|
||||
}
|
||||
|
||||
private static EVROverlayError ProcessOverlay1(CVROverlay overlay, ref ulong overlayHandle, ref bool overlayVisible, bool dashboardVisible, uint trackingIndex, DateTime nextRender)
|
||||
private static EVROverlayError ProcessOverlay1(CVROverlay overlay, ref ulong overlayHandle, ref bool overlayVisible, bool dashboardVisible, uint overlayIndex, DateTime nextOverlay)
|
||||
{
|
||||
var err = EVROverlayError.None;
|
||||
|
||||
@@ -304,7 +425,7 @@ namespace VRCX
|
||||
}
|
||||
}
|
||||
|
||||
if (trackingIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
|
||||
if (overlayIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
|
||||
{
|
||||
// http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices
|
||||
// Scaling-Rotation-Translation
|
||||
@@ -328,7 +449,7 @@ namespace VRCX
|
||||
m10 = m.M33,
|
||||
m11 = m.M43,
|
||||
};
|
||||
err = overlay.SetOverlayTransformTrackedDeviceRelative(overlayHandle, trackingIndex, ref hm34);
|
||||
err = overlay.SetOverlayTransformTrackedDeviceRelative(overlayHandle, overlayIndex, ref hm34);
|
||||
if (err != EVROverlayError.None)
|
||||
{
|
||||
return err;
|
||||
@@ -336,7 +457,7 @@ namespace VRCX
|
||||
}
|
||||
|
||||
if (!dashboardVisible &&
|
||||
DateTime.Now.CompareTo(nextRender) <= 0)
|
||||
DateTime.Now.CompareTo(nextOverlay) <= 0)
|
||||
{
|
||||
var texture = new Texture_t
|
||||
{
|
||||
@@ -462,123 +583,5 @@ namespace VRCX
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
private static void ThreadProc()
|
||||
{
|
||||
var e = new VREvent_t();
|
||||
var nextOpenVRInit = DateTime.MinValue;
|
||||
var nextDeviceInfoUpdate = DateTime.MinValue;
|
||||
var nextRender = DateTime.MinValue;
|
||||
var trackingIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
|
||||
var overlayVisible1 = false;
|
||||
var overlayVisible2 = false;
|
||||
var dashboardHandle = 0UL;
|
||||
var overlayHandle1 = 0UL;
|
||||
var overlayHandle2 = 0UL;
|
||||
|
||||
while (m_Thread != null)
|
||||
{
|
||||
m_Browser1.Render();
|
||||
m_Browser2.Render();
|
||||
|
||||
try
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ThreadInterruptedException
|
||||
}
|
||||
|
||||
var system = OpenVR.System;
|
||||
|
||||
if (system == null)
|
||||
{
|
||||
if (DateTime.Now.CompareTo(nextOpenVRInit) < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var _err = EVRInitError.None;
|
||||
system = OpenVR.Init(ref _err, EVRApplicationType.VRApplication_Overlay);
|
||||
nextOpenVRInit = DateTime.Now.AddSeconds(5);
|
||||
if (system == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while (system.PollNextEvent(ref e, (uint)Marshal.SizeOf(e)))
|
||||
{
|
||||
var type = (EVREventType)e.eventType;
|
||||
if (type == EVREventType.VREvent_Quit)
|
||||
{
|
||||
OpenVR.Shutdown();
|
||||
// VRChat이 실행 중일 때만 켜는 옵션이 생겨서 시간을 줄임
|
||||
nextOpenVRInit = DateTime.Now.AddSeconds(10);
|
||||
system = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (system == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DateTime.Now.CompareTo(nextDeviceInfoUpdate) >= 0)
|
||||
{
|
||||
trackingIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
|
||||
UpdateDevices(system, ref trackingIndex);
|
||||
if (trackingIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
|
||||
{
|
||||
nextRender = DateTime.Now.AddSeconds(10);
|
||||
}
|
||||
nextDeviceInfoUpdate = DateTime.Now.AddSeconds(0.1);
|
||||
}
|
||||
|
||||
var overlay = OpenVR.Overlay;
|
||||
|
||||
if (overlay == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var dashboardVisible = overlay.IsDashboardVisible();
|
||||
|
||||
var err = ProcessDashboard(overlay, ref dashboardHandle, dashboardVisible);
|
||||
|
||||
if (err != EVROverlayError.None &&
|
||||
dashboardHandle != 0)
|
||||
{
|
||||
overlay.DestroyOverlay(dashboardHandle);
|
||||
dashboardHandle = 0;
|
||||
}
|
||||
|
||||
err = ProcessOverlay1(overlay, ref overlayHandle1, ref overlayVisible1, dashboardVisible, trackingIndex, nextRender);
|
||||
|
||||
if (err != EVROverlayError.None &&
|
||||
overlayHandle1 != 0)
|
||||
{
|
||||
overlay.DestroyOverlay(overlayHandle1);
|
||||
overlayHandle1 = 0;
|
||||
}
|
||||
|
||||
err = ProcessOverlay2(overlay, ref overlayHandle2, ref overlayVisible2, dashboardVisible);
|
||||
|
||||
if (err != EVROverlayError.None &&
|
||||
overlayHandle2 != 0)
|
||||
{
|
||||
overlay.DestroyOverlay(overlayHandle2);
|
||||
overlayHandle2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
lock (m_Devices)
|
||||
{
|
||||
m_Devices.Clear();
|
||||
}
|
||||
|
||||
OpenVR.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user