// Update is called once per frame void Update() { if (state == State.RUNNING) { if (Input.location.status != LocationServiceStatus.Running) { state.SetState(State.STOPPED); Debug.LogError("Location should be running but now is: " + Input.location.status); onStopped.Invoke(); return; } if (!lastData.HasValue || !EqualLocation(Input.location.lastData, lastData.Value)) { lastData = Input.location.lastData; onNewData.Invoke(lastData.Value); } } }
protected void SafeLaunchEvent(object sender, DataGram data) { NewDataEvent?.Invoke(sender, data); }
/// <summary> /// On Update check if we need to invoke an action, process waiting data and if existing update the data access layer /// </summary> private void Update() { // Call the Unity update for the data access layer if it exists dataAccessLayer?.UnityUpdate(); // Check if there are new actions to be executed and if yes execute them if (actionQueue.Count > 0) { // Process all actions which are waiting to be processed // Note: This isn't 100% thread save as we could end in a loop when there are new actions coming in faster than we are processing them. // However, actions are added that rarely that we shouldn't run into issues. while (actionQueue.TryDequeue(out Action action)) { // Invoke the action from the queue action.Invoke(); } } // Check if there is new data to process and if yes process it if (dataQueue.Count > 0) { // Process all data which is waiting to be processed // Note: This isn't 100% thread save as we could end in a loop when there is still new data coming in faster than we are processing it. // However, data is added slowly enough that we shouldn't run into issues. while (dataQueue.TryDequeue(out GazeAPIData gazeAPIData)) { // Initialize the resulting data object with the API data GazeData gazeData = new GazeData(gazeAPIData); // Add the current frame time gazeData.FrameTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); // If we have valid gaze data process it if (gazeAPIData.GazeHasValue) { // Crate a gaze ray based on the gaze data Ray gazeRay = new Ray(gazeAPIData.GazeOrigin, gazeAPIData.GazeDirection); //// // The 3D gaze point is the actual position the wearer is looking at. // As everything apart from the eye tracking layers is visible, we have to collide the gaze with every layer except the eye tracking layers // Check if the gaze hits anything that isn't an AOI gazeData.GazePointHit = Physics.Raycast(gazeRay, out RaycastHit hitInfo, Mathf.Infinity, notEyeTrackingLayerMask); // If we hit something, write the hit info to the data if (gazeData.GazePointHit) { // Write all info from the hit to the data object gazeData.GazePoint = hitInfo.point; gazeData.GazePointName = hitInfo.collider.name; // Cache the transform of the game object which was hit Transform hitTransform = hitInfo.collider.transform; // Get the position of the hit in the local coordinates of the game object which was hit gazeData.GazePointOnHit = hitTransform.InverseTransformPoint(hitInfo.point); // Get the info about the object which was hit gazeData.GazePointHitPosition = hitTransform.position; gazeData.GazePointHitRotation = hitTransform.rotation.eulerAngles; gazeData.GazePointHitScale = hitTransform.lossyScale; // Update the position of the GazePoint visualization (only visible in the MRC view) GazePointVis.transform.position = hitInfo.point; // Get the position of the gaze point in the right and left eye if we have stereo rendering if (mainCamera.stereoActiveEye != Camera.MonoOrStereoscopicEye.Mono) { gazeData.GazePointLeftDisplay = mainCamera.WorldToScreenPoint(hitInfo.point, Camera.MonoOrStereoscopicEye.Left); gazeData.GazePointRightDisplay = mainCamera.WorldToScreenPoint(hitInfo.point, Camera.MonoOrStereoscopicEye.Right); } else { gazeData.GazePointLeftDisplay = null; gazeData.GazePointRightDisplay = null; } // Also get the mono position (and always do this) gazeData.GazePointMonoDisplay = mainCamera.WorldToScreenPoint(hitInfo.point, Camera.MonoOrStereoscopicEye.Mono); // Get the position of the gaze point on the webcam image gazeData.GazePointWebcam = webcamCamera.WorldToScreenPoint(hitInfo.point, Camera.MonoOrStereoscopicEye.Mono); } else { // Update the position of the GazePoint visualization (only visible in the MRC view) GazePointVis.transform.position = Vector3.zero; } //// // To check for AOIs we do a separate ray cast on the AOI layer // Check if the gaze hits a AOI gazeData.GazePointAOIHit = Physics.Raycast(gazeRay, out hitInfo, Mathf.Infinity, eyeTrackingAOILayerMask); // If we hit an AOI, write the hit info to data, otherwise simply leave it empty if (gazeData.GazePointAOIHit) { // Write all info from the hit to the data object gazeData.GazePointAOI = hitInfo.point; gazeData.GazePointAOIName = hitInfo.collider.name; // Cache the transform of the game object which was hit Transform hitTransform = hitInfo.collider.transform; // Get the position of the hit in the local coordinates of the game object which was hit gazeData.GazePointAOIOnHit = hitTransform.InverseTransformPoint(hitInfo.point); // Get the info about the object which was hit gazeData.GazePointAOIHitPosition = hitTransform.position; gazeData.GazePointAOIHitRotation = hitTransform.rotation.eulerAngles; gazeData.GazePointAOIHitScale = hitTransform.lossyScale; // Get the position of the gaze point on the web cam image gazeData.GazePointAOIWebcam = webcamCamera.WorldToScreenPoint(hitInfo.point, Camera.MonoOrStereoscopicEye.Mono); } } // Get the position of the game objects we want to log // Create new data array gazeData.positionInfos = new PositionInfo[PositionLoggedGameObjects.Count]; // Go through every game object and log its position for (int i = 0; i < PositionLoggedGameObjects.Count; i++) { // Check if the game object still exists gazeData.positionInfos[i].positionValid = PositionLoggedGameObjects[i] != null; // If it still exists log its position if (gazeData.positionInfos[i].positionValid) { // Name gazeData.positionInfos[i].gameObjectName = PositionLoggedGameObjects[i].name; // Position Vector3 position = PositionLoggedGameObjects[i].transform.position; gazeData.positionInfos[i].xPosition = position.x; gazeData.positionInfos[i].yPosition = position.y; gazeData.positionInfos[i].zPosition = position.z; // Rotation Vector3 rotation = PositionLoggedGameObjects[i].transform.rotation.eulerAngles; gazeData.positionInfos[i].xRotation = rotation.x; gazeData.positionInfos[i].yRotation = rotation.y; gazeData.positionInfos[i].zRotation = rotation.z; // Scale Vector3 scale = PositionLoggedGameObjects[i].transform.lossyScale; gazeData.positionInfos[i].xScale = scale.x; gazeData.positionInfos[i].yScale = scale.y; gazeData.positionInfos[i].zScale = scale.z; } } // Invoke new data event NewDataEvent?.Invoke(gazeData); } } }