@@ -159,6 +159,9 @@ bool LunarWM_init(LunarWM *wm)
|
||||
wm->xr.local_space = wm->xr.view_space = XR_NULL_HANDLE;
|
||||
wm->xr.hand_tracking_system_properties.type
|
||||
= XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT;
|
||||
wm->xr.hand_tracking_system_properties.next = NULL;
|
||||
wm->xr.hand_tracking_system_properties.supportsHandTracking = XR_FALSE;
|
||||
wm->xr.hand_tracking_enabled = false;
|
||||
wm->renderer.camera.position = (Vector3) { 0, 0, 0 };
|
||||
wm->renderer.camera.target = (Vector3) { 0, 0, 1 };
|
||||
wm->renderer.camera.up = (Vector3) { 0, 1, 0 };
|
||||
@@ -340,10 +343,14 @@ void LunarWM_run(LunarWM *wm)
|
||||
return;
|
||||
}
|
||||
|
||||
if (wm->xr.hand_tracking_system_properties.supportsHandTracking) {
|
||||
if (wm->xr.hand_tracking_enabled) {
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
LunarWM_Hand *hand = &wm->xr.hands[i];
|
||||
bool const unobstructed = true;
|
||||
if (!wm->xr.LocateHandJointsEXT
|
||||
|| hand->hand_tracker == XR_NULL_HANDLE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
XrHandJointsMotionRangeInfoEXT mri = {
|
||||
.type = XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT,
|
||||
|
||||
@@ -353,18 +353,20 @@ static void render_3d(LunarWM *this, float /*dt*/)
|
||||
{
|
||||
LunarWM_render_windows(this, true);
|
||||
|
||||
for (int h = 0; h < 2; ++h) {
|
||||
auto *hand_info = &this->xr.hands[h];
|
||||
for (size_t k = 0; k < XR_HAND_JOINT_COUNT_EXT; ++k) {
|
||||
auto const *jl = &hand_info->joint_locations[k];
|
||||
Vector3 pos = {
|
||||
jl->pose.position.x,
|
||||
jl->pose.position.y,
|
||||
jl->pose.position.z,
|
||||
};
|
||||
pos = RecenterPoint(this, pos);
|
||||
DrawSphere(pos, jl->radius, (Color) { 255, 0, 0, 255 });
|
||||
}
|
||||
for (int h = 0; this->xr.hand_tracking_enabled && h < 2; ++h) {
|
||||
auto *hand_info = &this->xr.hands[h];
|
||||
if (hand_info->hand_tracker == XR_NULL_HANDLE)
|
||||
continue;
|
||||
for (size_t k = 0; k < XR_HAND_JOINT_COUNT_EXT; ++k) {
|
||||
auto const *jl = &hand_info->joint_locations[k];
|
||||
Vector3 pos = {
|
||||
jl->pose.position.x,
|
||||
jl->pose.position.y,
|
||||
jl->pose.position.z,
|
||||
};
|
||||
pos = RecenterPoint(this, pos);
|
||||
DrawSphere(pos, jl->radius, (Color) { 255, 0, 0, 255 });
|
||||
}
|
||||
}
|
||||
|
||||
Skybox_draw(this->renderer.skybox, this->renderer.camera.position);
|
||||
|
||||
@@ -234,6 +234,7 @@ typedef struct LunarWM {
|
||||
PFN_xrCreateHandTrackerEXT CreateHandTrackerEXT;
|
||||
PFN_xrDestroyHandTrackerEXT DestroyHandTrackerEXT;
|
||||
PFN_xrLocateHandJointsEXT LocateHandJointsEXT;
|
||||
bool hand_tracking_enabled;
|
||||
|
||||
Quaternion recenter_rot;
|
||||
Vector3 recenter_trans;
|
||||
|
||||
130
src/LunarWM_xr.c
130
src/LunarWM_xr.c
@@ -13,7 +13,6 @@ GLuint LunarWM_xr_get_swapchain_image(
|
||||
return wm->xr.swapchain_images[swapchain_images_i].a_imgs[index].image;
|
||||
}
|
||||
|
||||
|
||||
bool LunarWM_xr_init(LunarWM *this)
|
||||
{
|
||||
XrResult res = XR_SUCCESS;
|
||||
@@ -28,12 +27,15 @@ bool LunarWM_xr_init(LunarWM *this)
|
||||
strncpy(
|
||||
(char *)app_info.engineName, "LunarWM Engine", XR_MAX_ENGINE_NAME_SIZE);
|
||||
|
||||
char const *instance_extensions[] = {
|
||||
char const *required_instance_extensions[] = {
|
||||
XR_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
||||
XR_MNDX_EGL_ENABLE_EXTENSION_NAME,
|
||||
XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME,
|
||||
};
|
||||
char const *optional_instance_extensions[] = {
|
||||
XR_EXT_HAND_TRACKING_EXTENSION_NAME,
|
||||
};
|
||||
bool hand_tracking_ext_available = false;
|
||||
char const **v_active_instance_extensions = vector_create();
|
||||
|
||||
uint32_t extension_properties_count = 0;
|
||||
@@ -61,8 +63,9 @@ bool LunarWM_xr_init(LunarWM *this)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SZ(instance_extensions); i++) {
|
||||
char const *requested_instance_extension = instance_extensions[i];
|
||||
for (size_t i = 0; i < ARRAY_SZ(required_instance_extensions); i++) {
|
||||
char const *requested_instance_extension
|
||||
= required_instance_extensions[i];
|
||||
bool found = false;
|
||||
for (int j = 0; j < extension_properties_count; j++) {
|
||||
if (strcmp(requested_instance_extension,
|
||||
@@ -84,6 +87,33 @@ bool LunarWM_xr_init(LunarWM *this)
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SZ(optional_instance_extensions); i++) {
|
||||
char const *requested_instance_extension
|
||||
= optional_instance_extensions[i];
|
||||
bool found = false;
|
||||
for (int j = 0; j < extension_properties_count; j++) {
|
||||
if (strcmp(requested_instance_extension,
|
||||
extension_properties[j].extensionName)
|
||||
!= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vector_add(
|
||||
&v_active_instance_extensions, requested_instance_extension);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
wlr_log(WLR_INFO, "Optional OpenXR instance extension missing: %s",
|
||||
requested_instance_extension);
|
||||
} else if (strcmp(requested_instance_extension,
|
||||
XR_EXT_HAND_TRACKING_EXTENSION_NAME)
|
||||
== 0) {
|
||||
hand_tracking_ext_available = true;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
XrInstanceCreateInfo const ci = {
|
||||
.type = XR_TYPE_INSTANCE_CREATE_INFO,
|
||||
@@ -104,26 +134,45 @@ bool LunarWM_xr_init(LunarWM *this)
|
||||
}
|
||||
this->xr.instance = instance;
|
||||
|
||||
res = xrGetInstanceProcAddr(this->xr.instance, "xrCreateHandTrackerEXT",
|
||||
(PFN_xrVoidFunction *)&this->xr.CreateHandTrackerEXT);
|
||||
if (res != XR_SUCCESS) {
|
||||
wlr_log(
|
||||
WLR_ERROR, "Failed to get proc addr xrCreateHandTrackerEXT");
|
||||
return false;
|
||||
this->xr.CreateHandTrackerEXT = NULL;
|
||||
this->xr.DestroyHandTrackerEXT = NULL;
|
||||
this->xr.LocateHandJointsEXT = NULL;
|
||||
|
||||
if (hand_tracking_ext_available) {
|
||||
res = xrGetInstanceProcAddr(this->xr.instance,
|
||||
"xrCreateHandTrackerEXT",
|
||||
(PFN_xrVoidFunction *)&this->xr.CreateHandTrackerEXT);
|
||||
if (res != XR_SUCCESS) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Failed to get proc addr xrCreateHandTrackerEXT "
|
||||
"(optional): %d",
|
||||
res);
|
||||
hand_tracking_ext_available = false;
|
||||
}
|
||||
}
|
||||
res = xrGetInstanceProcAddr(this->xr.instance,
|
||||
"xrDestroyHandTrackerEXT",
|
||||
(PFN_xrVoidFunction *)&this->xr.DestroyHandTrackerEXT);
|
||||
if (res != XR_SUCCESS) {
|
||||
wlr_log(
|
||||
WLR_ERROR, "Failed to get proc addr xrDestroyHandTrackerEXT");
|
||||
return false;
|
||||
if (hand_tracking_ext_available) {
|
||||
res = xrGetInstanceProcAddr(this->xr.instance,
|
||||
"xrDestroyHandTrackerEXT",
|
||||
(PFN_xrVoidFunction *)&this->xr.DestroyHandTrackerEXT);
|
||||
if (res != XR_SUCCESS) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Failed to get proc addr xrDestroyHandTrackerEXT "
|
||||
"(optional): %d",
|
||||
res);
|
||||
hand_tracking_ext_available = false;
|
||||
}
|
||||
}
|
||||
res = xrGetInstanceProcAddr(this->xr.instance, "xrLocateHandJointsEXT",
|
||||
(PFN_xrVoidFunction *)&this->xr.LocateHandJointsEXT);
|
||||
if (res != XR_SUCCESS) {
|
||||
wlr_log(WLR_ERROR, "Failed to get proc addr xrLocateHandJointsEXT");
|
||||
return false;
|
||||
if (hand_tracking_ext_available) {
|
||||
res = xrGetInstanceProcAddr(this->xr.instance,
|
||||
"xrLocateHandJointsEXT",
|
||||
(PFN_xrVoidFunction *)&this->xr.LocateHandJointsEXT);
|
||||
if (res != XR_SUCCESS) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Failed to get proc addr xrLocateHandJointsEXT (optional): "
|
||||
"%d",
|
||||
res);
|
||||
hand_tracking_ext_available = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,9 +204,12 @@ bool LunarWM_xr_init(LunarWM *this)
|
||||
}
|
||||
|
||||
{
|
||||
this->xr.hand_tracking_enabled = hand_tracking_ext_available;
|
||||
XrSystemProperties system_props = {
|
||||
.type = XR_TYPE_SYSTEM_PROPERTIES,
|
||||
.next = &this->xr.hand_tracking_system_properties,
|
||||
.next = this->xr.hand_tracking_enabled
|
||||
? &this->xr.hand_tracking_system_properties
|
||||
: NULL,
|
||||
};
|
||||
res = xrGetSystemProperties(
|
||||
this->xr.instance, this->xr.system_id, &system_props);
|
||||
@@ -165,6 +217,13 @@ bool LunarWM_xr_init(LunarWM *this)
|
||||
wlr_log(WLR_ERROR, "xrGetSystemProperties failed: %d", res);
|
||||
return false;
|
||||
}
|
||||
if (this->xr.hand_tracking_enabled
|
||||
&& !this->xr.hand_tracking_system_properties.supportsHandTracking) {
|
||||
wlr_log(WLR_INFO,
|
||||
"Hand tracking extension present but system does not support "
|
||||
"it");
|
||||
this->xr.hand_tracking_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
XrGraphicsRequirementsOpenGLESKHR reqs = {
|
||||
@@ -609,7 +668,8 @@ bool LunarWM_xr_init(LunarWM *this)
|
||||
}
|
||||
}
|
||||
|
||||
{ // Create hand trackers
|
||||
if (this->xr.hand_tracking_enabled && this->xr.CreateHandTrackerEXT) {
|
||||
bool hand_trackers_created = true;
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
auto *hand = &this->xr.hands[i];
|
||||
|
||||
@@ -623,9 +683,29 @@ bool LunarWM_xr_init(LunarWM *this)
|
||||
this->xr.session, &ci, &hand->hand_tracker);
|
||||
if (res != XR_SUCCESS) {
|
||||
wlr_log(WLR_ERROR, "Failed to create hand tracker: %d", res);
|
||||
return false;
|
||||
hand_trackers_created = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hand_trackers_created) {
|
||||
if (this->xr.DestroyHandTrackerEXT) {
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
auto *hand = &this->xr.hands[i];
|
||||
if (hand->hand_tracker != XR_NULL_HANDLE) {
|
||||
this->xr.DestroyHandTrackerEXT(hand->hand_tracker);
|
||||
hand->hand_tracker = XR_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
this->xr.hand_tracking_enabled = false;
|
||||
}
|
||||
}
|
||||
if (!this->xr.hand_tracking_enabled) {
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
this->xr.hands[i].hand_tracker = XR_NULL_HANDLE;
|
||||
}
|
||||
this->xr.hand_tracking_system_properties.supportsHandTracking
|
||||
= XR_FALSE;
|
||||
}
|
||||
|
||||
free(extension_properties);
|
||||
|
||||
Reference in New Issue
Block a user