From 68de25650303428bce8c15787dcdcdc713d85ee9 Mon Sep 17 00:00:00 2001 From: Chickenbread Date: Tue, 27 Sep 2022 22:13:54 +0200 Subject: [PATCH] Some minor refactoring - Moved Magic Numbers for Openness to Constants - Refactored Openness Parsing to only do one Divison per execution - Added Check to not write Tracking data, while it's invalid or Calibrating - Added Check to stop outputting data, when told to stop by main App --- VarjoTrackingModule.cs | 86 +++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/VarjoTrackingModule.cs b/VarjoTrackingModule.cs index 54d5fa4..299fac6 100644 --- a/VarjoTrackingModule.cs +++ b/VarjoTrackingModule.cs @@ -13,7 +13,11 @@ namespace VRCFTVarjoModule // This class contains the overrides for any VRCFT Tracking Data struct functions public static class TrackingData { - // 2 for min and -1 for max, to ensure these Values get overwritten the first runthrough + // Magic numbers to disect the 0-1 Varjo Openness float into SRanipal Openness, Widen & Squeeze values + // Based on Testing from @Chickenbread; may need adjusting + private static readonly float EYE_SQUEEZE_THRESHOLD = 0.10f, EYE_WIDEN_THRESHOLD = 0.90f; + + // 999 for min and -1 for max, to ensure these Values get overwritten the first runthrough private static double _minPupilSize = 999, _maxPupilSize = -1; // This function parses the external module's single-eye data into a VRCFT-Parseable format @@ -37,36 +41,38 @@ public static void Update(ref Eye data, GazeRay external, float openness) // This function parses the external module's full-data data into multiple VRCFT-Parseable single-eye structs public static void Update(ref EyeTrackingData data, GazeData external, EyeMeasurements externalMeasurements) { - // VRCFaceTracking.Logger.Msg("Left Eye Openness: " + externalMeasurements.leftEyeOpenness + " | Right Eye Openness: " + externalMeasurements.rightEyeOpenness); - Update(ref data.Right, external.rightEye, externalMeasurements.rightEyeOpenness, external.rightStatus); - Update(ref data.Left, external.leftEye, externalMeasurements.leftEyeOpenness, external.leftStatus); - Update(ref data.Combined, external.gaze, (externalMeasurements.leftEyeOpenness + externalMeasurements.rightEyeOpenness) / 2); - - // Determines whether the pupil Size/Eye dilation - // If one is open and the other closed, we don't want the closed one to pull down the Values of the open one. - double pupilSize = 0; - // Casting the status as ints allows for easier comparison; as we need Compensated (2) or Tracked (3), that means >= 2 - if ((int)external.leftStatus >= 2 && (int)external.rightStatus >= 2) - { - pupilSize = (externalMeasurements.leftPupilDiameterInMM + externalMeasurements.rightPupilDiameterInMM) / 2; - } - else if ((int)external.rightStatus >= 2) + if (external.status == GazeStatus.Valid) { - pupilSize = externalMeasurements.rightPupilDiameterInMM; - } - else if ((int)external.leftStatus >= 2) - { - pupilSize = externalMeasurements.leftPupilDiameterInMM; - } + Update(ref data.Right, external.rightEye, externalMeasurements.rightEyeOpenness, external.rightStatus); + Update(ref data.Left, external.leftEye, externalMeasurements.leftEyeOpenness, external.leftStatus); + Update(ref data.Combined, external.gaze, (externalMeasurements.leftEyeOpenness + externalMeasurements.rightEyeOpenness) / 2); - // Only set the Eye Dilation, if we actually have Pupil data - if (pupilSize > 0) - { - data.EyesDilation = (float)calculateEyeDilation(ref pupilSize); + // Determines whether the pupil Size/Eye dilation + // If one is open and the other closed, we don't want the closed one to pull down the Values of the open one. + double pupilSize = 0; + // Casting the status as ints allows for easier comparison; as we need Compensated (2) or Tracked (3), that means >= 2 + if ((int)external.leftStatus >= 2 && (int)external.rightStatus >= 2) + { + pupilSize = (externalMeasurements.leftPupilDiameterInMM + externalMeasurements.rightPupilDiameterInMM) / 2; + } + else if ((int)external.rightStatus >= 2) + { + pupilSize = externalMeasurements.rightPupilDiameterInMM; + } + else if ((int)external.leftStatus >= 2) + { + pupilSize = externalMeasurements.leftPupilDiameterInMM; + } + + // Only set the Eye Dilation, if we actually have Pupil data + if (pupilSize > 0) + { + data.EyesDilation = (float)calculateEyeDilation(ref pupilSize); + } } } - // This Function is used to calculate the Eye Dilation based on the lowest and highest measured Pupil Size + // This function is used to calculate the Eye Dilation based on the lowest and highest measured Pupil Size private static double calculateEyeDilation(ref double pupilSize) { // Adjust the bounds if Pupil Size exceeds the last thought maximum bounds @@ -91,25 +97,26 @@ private static double calculateEyeDilation(ref double pupilSize) return (pupilSize - _minPupilSize) / (_maxPupilSize - _minPupilSize); } + // This function is used to disect the single Varjo Openness Float into the SRanipal Openness, Widen & Squeeze values + // As the three SRanipal Parameters are exclusive to one another (if one is between 0 or 1, the others have to be either 0 or 1), we only need to do maths for one parameter private static void parseOpenness(ref Eye data, float openness) { - data.Openness = Math.Min((openness - 0.15f) / 0.8f, 1); - - if (openness <= 0.15f) + if (openness <= EYE_SQUEEZE_THRESHOLD) { - data.Squeeze = (openness / -0.15f) + 1; + data.Squeeze = (openness / -EYE_SQUEEZE_THRESHOLD) + 1; + data.Openness = 0; + data.Widen = 0; } - else + else if (openness >= EYE_WIDEN_THRESHOLD) { data.Squeeze = 0; - } - - if (openness > 0.95f) - { - data.Widen = (openness - 0.95f) / 0.05f; + data.Openness = 1; + data.Widen = (openness - EYE_WIDEN_THRESHOLD) / (1 - EYE_WIDEN_THRESHOLD); } else { + data.Squeeze = 0; + data.Openness = (openness - EYE_SQUEEZE_THRESHOLD) / (EYE_WIDEN_THRESHOLD - EYE_SQUEEZE_THRESHOLD); data.Widen = 0; } } @@ -202,8 +209,11 @@ private unsafe void UpdateEyeImage() // The update function needs to be defined separately in case the user is running with the --vrcft-nothread launch parameter public void Update() { - tracker.Update(); - TrackingData.Update(ref UnifiedTrackingData.LatestEyeData, tracker.GetGazeData(), tracker.GetEyeMeasurements()); + if (Status.EyeState == ModuleState.Active) + { + tracker.Update(); + TrackingData.Update(ref UnifiedTrackingData.LatestEyeData, tracker.GetGazeData(), tracker.GetEyeMeasurements()); + } UpdateEyeImage(); }