Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-09-30 01:36:51 +03:00
parent e8ee25cd88
commit 9b00e30b97
4 changed files with 128 additions and 38 deletions

View File

@@ -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,

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);