From 277124d650041803e28a22905273594971f87995 Mon Sep 17 00:00:00 2001 From: nullpon <4980756+nullpon16tera@users.noreply.github.com> Date: Thu, 9 Apr 2026 21:40:10 +0900 Subject: [PATCH 1/5] =?UTF-8?q?=E9=81=85=E5=BB=B6=E3=81=AE=E5=86=8D?= =?UTF-8?q?=E8=AA=BF=E6=95=B4=E3=81=A8=E3=83=88=E3=83=A9=E3=83=83=E3=82=AB?= =?UTF-8?q?=E3=83=BC=E5=89=B2=E3=82=8A=E5=BD=93=E3=81=A6=E3=81=8Cdefault?= =?UTF-8?q?=E3=81=AE=E3=81=A8=E3=81=8D=E3=81=AE=E3=83=87=E3=83=90=E3=82=A4?= =?UTF-8?q?=E3=82=B9=E3=81=AE=E5=8F=96=E5=BE=97=E6=96=B9=E6=B3=95=E3=82=92?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/TrackedDeviceManager.cs | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/AlternativePlay/Models/TrackedDeviceManager.cs b/AlternativePlay/Models/TrackedDeviceManager.cs index 8b55f93..4df7353 100644 --- a/AlternativePlay/Models/TrackedDeviceManager.cs +++ b/AlternativePlay/Models/TrackedDeviceManager.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Text; using UnityEngine; +using UnityEngine.XR; using Valve.VR; using Zenject; using static Valve.VR.IVRSystem; @@ -84,7 +85,9 @@ public void LoadTrackedDeviceProperties() /// public void PollTrackedDevices() { - const float predictionBiasSeconds = 0.0255f; + const float minPredictionSeconds = 0.0f; + const float maxPredictionSeconds = 0.1f; + const float predictionBiasSeconds = 0.0225f; // Calculate time to predict into the future float secondsSinceLastVsync = 0.0f; @@ -99,6 +102,9 @@ public void PollTrackedDevices() float predictedSecondsFromNow = frameDuration - secondsSinceLastVsync + fVsyncToPhotons; predictedSecondsFromNow += predictionBiasSeconds; + if (predictedSecondsFromNow < minPredictionSeconds) { predictedSecondsFromNow = minPredictionSeconds; } + if (predictedSecondsFromNow > maxPredictionSeconds) { predictedSecondsFromNow = maxPredictionSeconds; } + // Get all tracked device poses from OpenVR API TrackedDevicePose_t[] trackedDevicePoseArray = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; this.openVRManager.System.GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin.TrackingUniverseStanding, predictedSecondsFromNow, trackedDevicePoseArray); @@ -137,6 +143,12 @@ public OpenVRDeviceInfo GetInputDeviceFromSerial(string serial) public Pose? GetPoseFromLeftController() { + if (TryGetOpenXrControllerPose(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left, out Pose openXrPose)) + { + return openXrPose; + } + + if (this.openVRManager?.System == null) { return null; } uint index = this.openVRManager.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand); var device = this.TrackedDevices.ElementAtOrDefault((int)index); @@ -147,14 +159,40 @@ public OpenVRDeviceInfo GetInputDeviceFromSerial(string serial) public Pose? GetPoseFromRightController() { + if (TryGetOpenXrControllerPose(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right, out Pose openXrPose)) + { + return openXrPose; + } + + if (this.openVRManager?.System == null) { return null; } uint index = this.openVRManager.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand); - var device = this.TrackedDevices.ElementAtOrDefault((int)index); + var device = this.TrackedDevices.FirstOrDefault(d => d.Index == (int)index); if (device == null) { return null; } return device.Pose; } + private static bool TryGetOpenXrControllerPose(InputDeviceCharacteristics characteristics, out Pose pose) + { + var devices = new List(); + InputDevices.GetDevicesWithCharacteristics(characteristics, devices); + + foreach (var device in devices) + { + bool hasPosition = device.TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 position); + bool hasRotation = device.TryGetFeatureValue(CommonUsages.deviceRotation, out Quaternion rotation); + if (hasPosition && hasRotation) + { + pose = new Pose(position, rotation); + return true; + } + } + + pose = default; + return false; + } + /// /// This method calls on to compute the tracked position /// given the serial number of the tracker. From ee40893d5d261a30012c388646eeacc424c7071b Mon Sep 17 00:00:00 2001 From: nullpon <4980756+nullpon16tera@users.noreply.github.com> Date: Sat, 11 Apr 2026 02:35:32 +0900 Subject: [PATCH 2/5] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E3=82=B3?= =?UTF-8?q?=E3=83=BC=E3=83=89=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AlternativePlay/Models/TrackedDeviceManager.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/AlternativePlay/Models/TrackedDeviceManager.cs b/AlternativePlay/Models/TrackedDeviceManager.cs index 4df7353..582ae0c 100644 --- a/AlternativePlay/Models/TrackedDeviceManager.cs +++ b/AlternativePlay/Models/TrackedDeviceManager.cs @@ -148,7 +148,6 @@ public OpenVRDeviceInfo GetInputDeviceFromSerial(string serial) return openXrPose; } - if (this.openVRManager?.System == null) { return null; } uint index = this.openVRManager.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand); var device = this.TrackedDevices.ElementAtOrDefault((int)index); @@ -164,7 +163,6 @@ public OpenVRDeviceInfo GetInputDeviceFromSerial(string serial) return openXrPose; } - if (this.openVRManager?.System == null) { return null; } uint index = this.openVRManager.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand); var device = this.TrackedDevices.FirstOrDefault(d => d.Index == (int)index); From 3a2d5b9decb168cada80a983bf0e9e695dee7ebf Mon Sep 17 00:00:00 2001 From: nullpon <4980756+nullpon16tera@users.noreply.github.com> Date: Sat, 11 Apr 2026 17:11:03 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=E3=81=99=E3=81=B9=E3=81=A6OpenXR=E7=8A=B6?= =?UTF-8?q?=E6=85=8B=E3=81=AB=E3=81=AA=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F?= =?UTF-8?q?=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3=E3=81=97=E3=81=BE=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/TrackedDeviceManager.cs | 59 ++++++++++++------- AlternativePlay/SaberDeviceManager.cs | 10 +++- 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/AlternativePlay/Models/TrackedDeviceManager.cs b/AlternativePlay/Models/TrackedDeviceManager.cs index 582ae0c..fa9f2b2 100644 --- a/AlternativePlay/Models/TrackedDeviceManager.cs +++ b/AlternativePlay/Models/TrackedDeviceManager.cs @@ -38,6 +38,7 @@ public class TrackedDeviceManager #pragma warning restore CS0649 public List TrackedDevices { get; private set; } = new List(); + public List OpenXrDevices { get; private set; } = new List(); /// /// Updates the list of valid tracked devices and their properties only. Use to get the @@ -143,11 +144,6 @@ public OpenVRDeviceInfo GetInputDeviceFromSerial(string serial) public Pose? GetPoseFromLeftController() { - if (TryGetOpenXrControllerPose(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left, out Pose openXrPose)) - { - return openXrPose; - } - uint index = this.openVRManager.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand); var device = this.TrackedDevices.ElementAtOrDefault((int)index); @@ -158,11 +154,6 @@ public OpenVRDeviceInfo GetInputDeviceFromSerial(string serial) public Pose? GetPoseFromRightController() { - if (TryGetOpenXrControllerPose(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right, out Pose openXrPose)) - { - return openXrPose; - } - uint index = this.openVRManager.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand); var device = this.TrackedDevices.FirstOrDefault(d => d.Index == (int)index); @@ -171,20 +162,48 @@ public OpenVRDeviceInfo GetInputDeviceFromSerial(string serial) return device.Pose; } - private static bool TryGetOpenXrControllerPose(InputDeviceCharacteristics characteristics, out Pose pose) + /// + /// Unity XR 入力(OpenXR 起動時など)から左手コントローラの pose のみを取得する。取得できなければ null。 + /// + public Pose? GetPoseFromOpenXrLeftController() + { + if (TryGetOpenXrControllerPose(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left, out Pose pose)) + { + return pose; + } + + return null; + } + + /// + /// Unity XR 入力(OpenXR 起動時など)から右手コントローラの pose のみを取得する。取得できなければ null。 + /// + public Pose? GetPoseFromOpenXrRightController() + { + if (TryGetOpenXrControllerPose(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right, out Pose pose)) + { + return pose; + } + + return null; + } + + private bool TryGetOpenXrControllerPose(InputDeviceCharacteristics characteristics, out Pose pose) { - var devices = new List(); + List devices = this.OpenXrDevices; InputDevices.GetDevicesWithCharacteristics(characteristics, devices); - foreach (var device in devices) + var device = devices.FirstOrDefault(d => + d.TryGetFeatureValue(CommonUsages.devicePosition, out _) && + d.TryGetFeatureValue(CommonUsages.deviceRotation, out _) + ); + + if (device.isValid) { - bool hasPosition = device.TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 position); - bool hasRotation = device.TryGetFeatureValue(CommonUsages.deviceRotation, out Quaternion rotation); - if (hasPosition && hasRotation) - { - pose = new Pose(position, rotation); - return true; - } + device.TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 position); + device.TryGetFeatureValue(CommonUsages.deviceRotation, out Quaternion rotation); + pose = new Pose(position, rotation); + return true; } pose = default; diff --git a/AlternativePlay/SaberDeviceManager.cs b/AlternativePlay/SaberDeviceManager.cs index d73db38..f962a36 100644 --- a/AlternativePlay/SaberDeviceManager.cs +++ b/AlternativePlay/SaberDeviceManager.cs @@ -26,6 +26,12 @@ public class SaberDeviceManager : MonoBehaviour private Pose savedRightController; private Pose savedRightSaber; private bool calibrated; + private bool leftRuntimeOffsetReady; + private bool rightRuntimeOffsetReady; + private Vector3 leftRuntimeLocalOffsetPosition; + private Quaternion leftRuntimeLocalOffsetRotation; + private Vector3 rightRuntimeLocalOffsetPosition; + private Quaternion rightRuntimeLocalOffsetRotation; private void Start() { @@ -61,7 +67,7 @@ public Pose GetLeftSaberPose(TrackerConfigData configData) if (!this.calibrated) return new Pose(); // Return adjusted position from the saber - Pose controllerPose = this.trackedDeviceManager.GetPoseFromLeftController() ?? new Pose(); + Pose controllerPose = this.trackedDeviceManager.GetPoseFromOpenXrLeftController() ?? this.trackedDeviceManager.GetPoseFromLeftController() ?? new Pose(); Pose adjustedControllerPose = this.AdjustForPlayerOrigin(controllerPose); return TrackedDeviceManager.GetTrackedObjectPose(this.savedLeftSaber, this.savedLeftController, adjustedControllerPose); } @@ -87,7 +93,7 @@ public Pose GetRightSaberPose(TrackerConfigData configData) if (!this.calibrated) return new Pose(); // Return adjusted position from the saber - Pose controllerPose = this.trackedDeviceManager.GetPoseFromRightController() ?? new Pose(); + Pose controllerPose = this.trackedDeviceManager.GetPoseFromOpenXrRightController() ?? this.trackedDeviceManager.GetPoseFromRightController() ?? new Pose(); Pose adjustedControllerPose = this.AdjustForPlayerOrigin(controllerPose); return TrackedDeviceManager.GetTrackedObjectPose(this.savedRightSaber, this.savedRightController, adjustedControllerPose); } From ede95484c631911cb767d8beaf05e39ef27070a9 Mon Sep 17 00:00:00 2001 From: nullpon <4980756+nullpon16tera@users.noreply.github.com> Date: Sat, 11 Apr 2026 17:21:05 +0900 Subject: [PATCH 4/5] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AlternativePlay/Models/TrackedDeviceManager.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/AlternativePlay/Models/TrackedDeviceManager.cs b/AlternativePlay/Models/TrackedDeviceManager.cs index fa9f2b2..2a9b894 100644 --- a/AlternativePlay/Models/TrackedDeviceManager.cs +++ b/AlternativePlay/Models/TrackedDeviceManager.cs @@ -162,9 +162,6 @@ public OpenVRDeviceInfo GetInputDeviceFromSerial(string serial) return device.Pose; } - /// - /// Unity XR 入力(OpenXR 起動時など)から左手コントローラの pose のみを取得する。取得できなければ null。 - /// public Pose? GetPoseFromOpenXrLeftController() { if (TryGetOpenXrControllerPose(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left, out Pose pose)) @@ -175,9 +172,6 @@ public OpenVRDeviceInfo GetInputDeviceFromSerial(string serial) return null; } - /// - /// Unity XR 入力(OpenXR 起動時など)から右手コントローラの pose のみを取得する。取得できなければ null。 - /// public Pose? GetPoseFromOpenXrRightController() { if (TryGetOpenXrControllerPose(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right, out Pose pose)) From 5395e21f444f972ff4c36503d8159b77f8110fd7 Mon Sep 17 00:00:00 2001 From: nullpon <4980756+nullpon16tera@users.noreply.github.com> Date: Sat, 11 Apr 2026 17:31:39 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E5=AE=9A?= =?UTF-8?q?=E6=95=B0=E3=81=8C=E6=AE=8B=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F?= =?UTF-8?q?=E3=81=AE=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AlternativePlay/SaberDeviceManager.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/AlternativePlay/SaberDeviceManager.cs b/AlternativePlay/SaberDeviceManager.cs index f962a36..856f306 100644 --- a/AlternativePlay/SaberDeviceManager.cs +++ b/AlternativePlay/SaberDeviceManager.cs @@ -26,12 +26,6 @@ public class SaberDeviceManager : MonoBehaviour private Pose savedRightController; private Pose savedRightSaber; private bool calibrated; - private bool leftRuntimeOffsetReady; - private bool rightRuntimeOffsetReady; - private Vector3 leftRuntimeLocalOffsetPosition; - private Quaternion leftRuntimeLocalOffsetRotation; - private Vector3 rightRuntimeLocalOffsetPosition; - private Quaternion rightRuntimeLocalOffsetRotation; private void Start() {