Skip to content

Commit

Permalink
Added Backend.OpenXR.EyesSampleTime (#358)
Browse files Browse the repository at this point in the history
* Fix a very small typo (#289)

* added eyes sample time to backend

* moving some things

* revert my tests from the eye demo

* minor merge quirk

* minor comment edit

* added display of eye tracker sampling frequency to eyes demo

* small name change

Co-authored-by: TopperDEL <github_com@tparth.de>
  • Loading branch information
sandrist and TopperDEL committed Apr 8, 2022
1 parent 7eb6a58 commit 12fce24
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 5 deletions.
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

0 comments on commit 12fce24

Please sign in to comment.