Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Backend.OpenXR.EyesSampleTime #358

Merged
merged 9 commits into from
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions Examples/StereoKitTest/Demos/DemoEyes.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using StereoKit;
using System;
using StereoKit;
using System.Collections.Generic;

class DemoEyes : ITest
Expand All @@ -11,13 +12,23 @@ class DemoEyes : ITest
List<LinePoint> points = new List<LinePoint>();
Vec3 previous;

public void Initialize() { }
long lastEyesSampleTime;
DateTime demoStartTime;
int uniqueSamplesCount;

public void Initialize()
{
demoStartTime = DateTime.UtcNow;
uniqueSamplesCount = 0;
lastEyesSampleTime = -1;
}
public void Shutdown () { }

public void Update()
{
Plane plane = new Plane(new Vec3(0.5f,0,-0.5f), V.XYZ(-0.5f,0,0.5f));
Mesh.Quad.Draw(Material.Default, Matrix.TRS(new Vec3(0.54f, 0, -0.468f), Quat.LookDir(plane.normal), 0.5f));
Matrix quadPose = Matrix.TRS(new Vec3(0.54f, 0, -0.468f), Quat.LookDir(plane.normal), 0.5f);
Mesh.Quad.Draw(Material.Default, quadPose);
if (Input.Eyes.Ray.Intersect(plane, out Vec3 at))
{
Color stateColor = Input.EyesTracked.IsActive()
Expand Down Expand Up @@ -46,5 +57,17 @@ public void Update()

Text.Add(title, titlePose);
Text.Add(description, descPose, V.XY(0.4f, 0), TextFit.Wrap, TextAlign.TopCenter, TextAlign.TopLeft);

if (Backend.XRType == BackendXRType.OpenXR)
{
if (Backend.OpenXR.EyesSampleTime != lastEyesSampleTime)
{
lastEyesSampleTime = Backend.OpenXR.EyesSampleTime;
uniqueSamplesCount++;
}

double sampleFrequency = uniqueSamplesCount / (DateTime.UtcNow - demoStartTime).TotalSeconds;
Text.Add($"Eye tracker sampling frequency: {sampleFrequency:0.#} Hz", Matrix.T(V.XYZ(0, -0.55f, -0.1f)) * quadPose);
}
}
}
2 changes: 1 addition & 1 deletion Examples/StereoKitTest/Demos/DemoQRCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// :CodeDoc: Guides 4 Using QR Codes
/// # Using QR Codes
///
/// QR codes are a super fast and easy way to to locate an object,
/// QR codes are a super fast and easy way to locate an object,
/// provide information from the environment, or `localize` two
/// devices to the same coordinate space! HoloLens 2 and WMR headsets
/// have a really convenient way to grab and use this data. They can use
Expand Down
1 change: 1 addition & 0 deletions StereoKit/Native/NativeAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ internal static class NativeAPI
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern ulong backend_openxr_get_session ();
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern ulong backend_openxr_get_space ();
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern long backend_openxr_get_time ();
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern long backend_openxr_get_eyes_sample_time();
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern IntPtr backend_openxr_get_function(string function_name);
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern int backend_openxr_ext_enabled (string extension_name);
[DllImport(dll, CharSet = cSet, CallingConvention = call)] public static extern void backend_openxr_ext_request (string extension_name);
Expand Down
4 changes: 4 additions & 0 deletions StereoKit/Systems/Backend.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ public static class OpenXR
/// frame, and is available after SK.Initialize.</summary>
public static long Time => NativeAPI.backend_openxr_get_time();

/// <summary>Type: XrTime. This is the OpenXR time of the eye tracker
/// sample associated with the current value of <see cref="Input.Eyes"/>.</summary>
public static long EyesSampleTime => NativeAPI.backend_openxr_get_eyes_sample_time();

/// <summary>This tells if an OpenXR extension has been requested
/// and successfully loaded by the runtime. This MUST only be
/// called after SK.Initialize.</summary>
Expand Down
1 change: 1 addition & 0 deletions StereoKitC/stereokit.h
Original file line number Diff line number Diff line change
Expand Up @@ -1897,6 +1897,7 @@ SK_API openxr_handle_t backend_openxr_get_instance();
SK_API openxr_handle_t backend_openxr_get_session ();
SK_API openxr_handle_t backend_openxr_get_space ();
SK_API int64_t backend_openxr_get_time ();
SK_API int64_t backend_openxr_get_eyes_sample_time();
SK_API void *backend_openxr_get_function(const char *function_name);
SK_API bool32_t backend_openxr_ext_enabled (const char *extension_name);
SK_API void backend_openxr_ext_request (const char *extension_name);
Expand Down
26 changes: 26 additions & 0 deletions StereoKitC/systems/platform/openxr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ XrSpace xr_stage_space = {};
XrSpace xr_head_space = {};
XrSystemId xr_system_id = XR_NULL_SYSTEM_ID;
XrTime xr_time = 0;
XrTime xr_eyes_sample_time = 0;

array_t<const char*> xr_exts_user = {};
array_t<uint64_t> xr_exts_loaded = {};
Expand Down Expand Up @@ -701,6 +702,23 @@ bool32_t openxr_get_space(XrSpace space, pose_t *out_pose, XrTime time) {

///////////////////////////////////////////

bool32_t openxr_get_gaze_space(pose_t* out_pose, XrTime &out_gaze_sample_time, XrTime time) {
if (time == 0) time = xr_time;

XrEyeGazeSampleTimeEXT gaze_sample_time = { XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT };
XrSpaceLocation space_location = { XR_TYPE_SPACE_LOCATION, &gaze_sample_time };
XrResult res = xrLocateSpace(xr_gaze_space, xr_app_space, time, &space_location);
if (XR_UNQUALIFIED_SUCCESS(res) && openxr_loc_valid(space_location)) {
memcpy(&out_pose->position, &space_location.pose.position, sizeof(vec3));
memcpy(&out_pose->orientation, &space_location.pose.orientation, sizeof(quat));
out_gaze_sample_time = gaze_sample_time.time;
return true;
}
return false;
}

///////////////////////////////////////////

pose_t world_from_spatial_graph(uint8_t spatial_graph_node_id[16], bool32_t dynamic, int64_t qpc_time) {
if (!xr_session) {
log_warn("No OpenXR session available for converting spatial graph nodes!");
Expand Down Expand Up @@ -897,6 +915,14 @@ int64_t backend_openxr_get_time() {

///////////////////////////////////////////

int64_t backend_openxr_get_eyes_sample_time() {
if (backend_xr_get_type() != backend_xr_type_openxr)
log_err("backend_openxr_ functions only work when OpenXR is the backend!");
return xr_eyes_sample_time;
}

///////////////////////////////////////////

void *backend_openxr_get_function(const char *function_name) {
if (backend_xr_get_type() != backend_xr_type_openxr)
log_err("backend_openxr_ functions only work when OpenXR is the backend!");
Expand Down
3 changes: 3 additions & 0 deletions StereoKitC/systems/platform/openxr.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,13 @@ void openxr_poll_actions ();

void *openxr_get_luid ();
bool32_t openxr_get_space(XrSpace space, pose_t *out_pose, XrTime time = 0);
bool32_t openxr_get_gaze_space(pose_t* out_pose, XrTime& out_gaze_sample_time, XrTime time = 0);
const char* openxr_string (XrResult result);

extern XrSpace xrc_space_grip[2];
extern XrSpace xr_app_space;
extern XrSpace xr_head_space;
extern XrSpace xr_gaze_space;
extern XrInstance xr_instance;
extern XrSession xr_session;
extern XrSessionState xr_session_state;
Expand All @@ -153,6 +155,7 @@ extern bool xr_has_depth_lsr;
extern bool xr_has_bounds;
extern bool xr_has_single_pass;
extern XrTime xr_time;
extern XrTime xr_eyes_sample_time;
extern vec2 xr_bounds_size;
extern pose_t xr_bounds_pose;
extern pose_t xr_bounds_pose_local;
Expand Down
2 changes: 1 addition & 1 deletion StereoKitC/systems/platform/openxr_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ void oxri_update_poses() {
action_info.action = xrc_action_eyes;
xrGetActionStatePose(xr_session, &action_info, &action_pose);

if (action_pose.isActive && openxr_get_space(xr_gaze_space, &input_eyes_pose_local)) {
if (action_pose.isActive && openxr_get_gaze_space(&input_eyes_pose_local, xr_eyes_sample_time)) {
input_eyes_pose_world.position = root * input_eyes_pose_local.position;
input_eyes_pose_world.orientation = root_q * input_eyes_pose_local.orientation;

Expand Down