private void RecordDatum(bool immediate) { // If recording is stopped (which is it by default), loop back around next frame. if (!shouldRecord) { return; } if (!immediate) // we run in the same thread as unity we can update the transformations in a synchronized way { UpdateFoveInterfaceMatrices(false); } bool frameMarked; Result <string> gazedObjectName; Matrix4x4 transformMat; Vector3 hmdPosition; Quaternion hmdOrientation; lock (unityThreadData) { switch (gazeCoordinateSpace) { case CoordinateSpace.World: transformMat = unityThreadData.HMDToWorld; break; case CoordinateSpace.Local: transformMat = unityThreadData.HMDToLocal; break; default: transformMat = Matrix4x4.identity; break; } frameMarked = unityThreadData.markKeyDown; gazedObjectName = unityThreadData.gazedObject; hmdPosition = unityThreadData.HMDPosition; hmdOrientation = unityThreadData.HMDOrientation; } var eyeOffsets = FoveManager.GetEyeOffsets(); var eyeVectorL = FoveManager.GetHmdGazeVector(Eye.Left); var eyeVectorR = FoveManager.GetHmdGazeVector(Eye.Right); Stereo <Result <Ray> > eyeRays; eyeRays.left = Utils.CalculateWorldGazeVector(ref transformMat, ref eyeOffsets.value.left, ref eyeVectorL); eyeRays.right = Utils.CalculateWorldGazeVector(ref transformMat, ref eyeOffsets.value.right, ref eyeVectorR); var gazeDepth = FoveManager.GetCombinedGazeDepth(); var combinedRay = FoveManager.GetHmdCombinedGazeRay(); combinedRay.value.origin = transformMat.MultiplyPoint(combinedRay.value.origin); combinedRay.value.direction = transformMat.MultiplyVector(combinedRay.value.direction).normalized; var pupilRadiusLeft = FoveManager.GetPupilRadius(Eye.Left); var pupilRadiusRight = FoveManager.GetPupilRadius(Eye.Right); var eyeStateL = FoveManager.GetEyeState(Eye.Left); var eyeStateR = FoveManager.GetEyeState(Eye.Right); var eyeTorsionL = FoveManager.GetEyeTorsion(Eye.Left); var eyeTorsionR = FoveManager.GetEyeTorsion(Eye.Right); // If you add new fields, be sure to write them here. var datum = new Datum { AppTime = (float)stopwatch.Elapsed.TotalSeconds, UserMark = frameMarked, GazedObjectName = gazedObjectName, HeadsetPosition = new Result <Vector3>(hmdPosition), HeadsetOrientation = new Result <Quaternion>(hmdOrientation), CombinedRay = combinedRay, GazeDepth = gazeDepth, EyeRays = eyeRays, EyesState = new Stereo <Result <EyeState> >(eyeStateL, eyeStateR), PupilsRadius = new Stereo <Result <float> >(pupilRadiusLeft, pupilRadiusRight), EyeTorsions = new Stereo <Result <float> >(eyeTorsionL, eyeTorsionR), UserPresence = FoveManager.IsUserPresent(), UserAttentionShift = FoveManager.IsUserShiftingAttention(), IPD = FoveManager.GetUserIPD(), IOD = FoveManager.GetUserIOD(), EyeballRadius = new Stereo <Result <float> >(FoveManager.GetEyeballRadius(Eye.Left), FoveManager.GetEyeballRadius(Eye.Right)), ScreenGaze = new Stereo <Result <Vector2> >(FoveManager.GetGazeScreenPosition(Eye.Left), FoveManager.GetGazeScreenPosition(Eye.Right)), EyeShape = new Stereo <Result <Fove.Unity.EyeShape> >(FoveManager.GetEyeShape(Eye.Left), FoveManager.GetEyeShape(Eye.Right)), PupilShape = new Stereo <Result <Fove.Unity.PupilShape> >(FoveManager.GetPupilShape(Eye.Left), FoveManager.GetPupilShape(Eye.Right)), }; dataSlice.Add(datum); if (dataSlice.Count >= writeAtDataCount) { flushData(); } }