#if !PICO_OPENXR_SDK
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICE:All information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
namespace Unity.XR.PXR
{
public class PXR_EyeTracking
{
///
/// Gets the PosMatrix of the head.
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// A Matrix4x4 value returned by the result.
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetHeadPosMatrix(out Matrix4x4 matrix)
{
matrix = Matrix4x4.identity;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
Vector3 headPos = Vector3.zero;
if (!device.TryGetFeatureValue(CommonUsages.devicePosition, out headPos))
{
Debug.LogError("PXRLog Failed at GetHeadPosMatrix Pos");
return false;
}
Quaternion headRot = Quaternion.identity;
if (!device.TryGetFeatureValue(CommonUsages.deviceRotation, out headRot))
{
Debug.LogError("PXRLog Failed at GetHeadPosMatrix Rot");
return false;
}
matrix = Matrix4x4.TRS(headPos, headRot, Vector3.one);
return true;
}
static InputDevice curDevice;
///
/// Gets the input device for eye tracking data.
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// The input device returned by the result.
///
/// * `true`: success
/// * `false`: failure
///
static bool GetEyeTrackingDevice(out InputDevice device)
{
if (curDevice!= null&& curDevice.isValid)
{
device = curDevice;
return true;
}
device = default;
if (!PXR_Manager.Instance.eyeTracking)
return false;
List devices = new List();
InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.EyeTracking | InputDeviceCharacteristics.HeadMounted, devices);
if (devices.Count == 0)
{
Debug.LogError("PXRLog Failed at GetEyeTrackingDevice devices.Count");
return false;
}
device = devices[0];
curDevice = device;
if (!device.isValid)
{
Debug.LogError("PXRLog Failed at GetEyeTrackingDevice device.isValid");
}
return device.isValid;
}
///
/// Gets the position of the center of the eyes in the Unity camera coordinate system (unit: meter).
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// Returns a vector3 value which is divided by 1000. To get the original value, multiply the returned value by 1000. Unit: millimeter.
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetCombineEyeGazePoint(out Vector3 point)
{
point = Vector3.zero;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.combineEyePoint, out point))
{
Debug.Log("PXRLog Failed at GetCombineEyeGazePoint point");
return false;
}
return true;
}
///
/// Gets the direction of binocular combined gaze in the Unity camera coordinate system.
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// Returns a vector3 value which is divided by 1000. To get the original value, multiply the returned value by 1000. Unit: millimeter.
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetCombineEyeGazeVector(out Vector3 vector)
{
vector = Vector3.zero;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.combineEyeVector, out vector))
{
Debug.LogError("PXRLog Failed at GetCombineEyeGazeVector vector");
return false;
}
return true;
}
///
/// Gets the openness/closeness of the left eye.
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// A float value returned by the result. The value ranges from `0.0` to `1.0`. `0.0` incicates completely closed, `1.0` indicates completely open.
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetLeftEyeGazeOpenness(out float openness)
{
openness = 0;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.leftEyeOpenness, out openness))
{
Debug.LogError("PXRLog Failed at GetLeftEyeGazeOpenness openness");
return false;
}
return true;
}
///
/// Gets the openness/closeness of the right eye.
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// A float value returned by the result. The value ranges from `0.0` to `1.0`. `0.0` indicates completely closed, `1.0` indicates completely open.
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetRightEyeGazeOpenness(out float openness)
{
openness = 0;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.rightEyeOpenness, out openness))
{
Debug.LogError("PXRLog Failed at GetRightEyeGazeOpenness openness");
return false;
}
return true;
}
///
/// Gets whether the data of the current left eye is available.
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// An int value returned by the result. Below are the `EyePoseStatus` enumerations:
/// - GazePointValid = (1 << 0),
/// - GazeVectorValid = (1 << 1),
/// - EyeOpennessValid = (1 << 2),
/// - EyePupilDilationValid = (1 << 3),
/// - EyePositionGuideValid = (1 << 4),
/// - EyePupilPositionValid = (1 << 5),
/// - EyeConvergenceDistanceValid = (1 << 6),
/// - EyeGazePointValid = (1 << 7),
/// - EyeGazeVectorValid = (1 << 8),
/// - PupilDistanceValid = (1 << 9),
/// - ConvergenceDistanceValid = (1 << 10),
/// - PupilDiameterValid = (1 << 11),
///
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetLeftEyePoseStatus(out uint status)
{
status = 0;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.leftEyePoseStatus, out status))
{
Debug.LogError("PXRLog Failed at GetLeftEyePoseStatus status");
return false;
}
return true;
}
///
/// Gets whether the data of the current right eye is available.
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// An int value returned by the result. Below are the `EyePoseStatus` enumerations:
/// - GazePointValid = (1 << 0),
/// - GazeVectorValid = (1 << 1),
/// - EyeOpennessValid = (1 << 2),
/// - EyePupilDilationValid = (1 << 3),
/// - EyePositionGuideValid = (1 << 4),
/// - EyePupilPositionValid = (1 << 5),
/// - EyeConvergenceDistanceValid = (1 << 6),
/// - EyeGazePointValid = (1 << 7),
/// - EyeGazeVectorValid = (1 << 8),
/// - PupilDistanceValid = (1 << 9),
/// - ConvergenceDistanceValid = (1 << 10),
/// - PupilDiameterValid = (1 << 11),
///
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetRightEyePoseStatus(out uint status)
{
status = 0;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.rightEyePoseStatus, out status))
{
Debug.LogError("PXRLog Failed at GetRightEyePoseStatus status");
return false;
}
return true;
}
///
/// Gets whether the data of the combined eye is available.
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// An int value returned by the result:
/// `0`: not available
/// `1`: available
///
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetCombinedEyePoseStatus(out uint status)
{
status = 0;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.combinedEyePoseStatus, out status))
{
Debug.LogError("PXRLog Failed at GetCombinedEyePoseStatus status");
return false;
}
return true;
}
///
/// Gets the position of the left eye in a coordinate system. The upper-right point of the sensor is taken as the origin (0, 0) and the lower-left point is taken as (1, 1).
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// A vector3 value returned by the result.
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetLeftEyePositionGuide(out Vector3 position)
{
position = Vector3.zero;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.leftEyePositionGuide, out position))
{
Debug.LogError("PXRLog Failed at GetLeftEyePositionGuide pos");
return false;
}
return true;
}
///
/// Gets the position of the right eye in a coordinate system. The upper-right point of the sensor is taken as the origin (0, 0) and the lower-left point is taken as (1, 1).
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// A vector3 value returned by the result.
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetRightEyePositionGuide(out Vector3 position)
{
position = Vector3.zero;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.rightEyePositionGuide, out position))
{
Debug.LogError("PXRLog Failed at GetRightEyePositionGuide pos");
return false;
}
return true;
}
///
/// Gets the foveated gaze direction (i.e., the central point of fixed foveated rendering).
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// A vector3 value returned by the result.
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetFoveatedGazeDirection(out Vector3 direction)
{
direction = Vector3.zero;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.foveatedGazeDirection, out direction))
{
Debug.LogError("PXRLog Failed at GetFoveatedGazeDirection direction");
return false;
}
return true;
}
///
/// Gets whether the current foveated gaze tracking data is available.
/// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
///
/// An int value returned by the result:
/// * `0`: not available
/// * `1`: available
///
///
/// * `true`: success
/// * `false`: failure
///
public static bool GetFoveatedGazeTrackingState(out uint state)
{
state = 0;
if (!PXR_Manager.Instance.eyeTracking)
return false;
if (!GetEyeTrackingDevice(out InputDevice device))
return false;
if (!device.TryGetFeatureValue(PXR_Usages.foveatedGazeTrackingState, out state))
{
Debug.LogError("PXRLog Failed at GetFoveatedGazeTrackingState state");
return false;
}
return true;
}
}
}
#endif