st/oxr: implement XR_EXT_plane_detection

Co-Authored-By: Christoph Haag <christoph.haag@collabora.com>
Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2439>
This commit is contained in:
Simon ZeniandChristoph Haag authored and Korcan Hussein committed 2025-04-22 11:39:45 +01:00
1 parent f4c1b6716a
commit df047b54cc
12 files changed
+503 -2

No files matched your search

+2
View File
@@ -364,6 +364,7 @@ option(XRT_FEATURE_OPENXR_HAND_TRACKING_EXT "Enable XR_EXT_hand_tracking" ON)
option(XRT_FEATURE_OPENXR_HEADLESS "Enable XR_MND_headless" ON)
option(XRT_FEATURE_OPENXR_OVERLAY "Enable XR_EXTX_overlay" ON)
option(XRT_FEATURE_OPENXR_PERFORMANCE_SETTINGS "Enable XR_EXT_performance_settings" OFF)
option(XRT_FEATURE_OPENXR_PLANE_DETECTION "Enable XR_EXT_plane_detection" OFF)
option(XRT_FEATURE_OPENXR_VISIBILITY_MASK "Enable XR_KHR_visibility_mask" ON)
option(XRT_FEATURE_OPENXR_VULKAN_SWAPCHAIN_FORMAT_LIST "Enable XR_KHR_vulkan_swapchain_format_list" ON)
option(XRT_FEATURE_OPENXR_XDEV_SPACE "Enable XR_MNDX_xdev_space" ON)
@@ -621,6 +622,7 @@ message(STATUS "# FEATURE_OPENXR_LAYER_FB_SETTINGS: ${XRT_FEATUR
message(STATUS "# FEATURE_OPENXR_LAYER_FB_PASSTHROUGH: ${XRT_FEATURE_OPENXR_LAYER_FB_PASSTHROUGH}")
message(STATUS "# FEATURE_OPENXR_OVERLAY: ${XRT_FEATURE_OPENXR_OVERLAY}")
message(STATUS "# FEATURE_OPENXR_PERFORMANCE_SETTINGS: ${XRT_FEATURE_OPENXR_PERFORMANCE_SETTINGS}")
message(STATUS "# FEATURE_OPENXR_PLANE_DETECTION: ${XRT_FEATURE_OPENXR_PLANE_DETECTION}")
message(STATUS "# FEATURE_OPENXR_SPACE_LOCAL_FLOOR: ${XRT_FEATURE_OPENXR_SPACE_LOCAL_FLOOR}")
message(STATUS "# FEATURE_OPENXR_SPACE_UNBOUNDED: ${XRT_FEATURE_OPENXR_SPACE_UNBOUNDED}")
message(STATUS "# FEATURE_OPENXR_VISIBILITY_MASK: ${XRT_FEATURE_OPENXR_VISIBILITY_MASK}")
+1
View File
@@ -0,0 +1 @@
Adds support for XR_EXT_plane_detection extension
+1
View File
@@ -82,6 +82,7 @@ EXTENSIONS = (
['XR_HTC_facial_tracking', 'XRT_FEATURE_OPENXR_FACIAL_TRACKING_HTC'],
['XR_META_touch_controller_plus', 'XRT_FEATURE_OPENXR_INTERACTION_TOUCH_PLUS'],
['XR_ML_ml2_controller_interaction', 'XRT_FEATURE_OPENXR_INTERACTION_ML2'],
['XR_EXT_plane_detection', 'XRT_FEATURE_OPENXR_PLANE_DETECTION'],
['XR_MND_headless', 'XRT_FEATURE_OPENXR_HEADLESS'],
['XR_MND_swapchain_usage_input_attachment_bit'],
['XR_MSFT_hand_interaction', 'XRT_FEATURE_OPENXR_INTERACTION_MSFT_HAND'],
@@ -66,6 +66,7 @@
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_SETTINGS
#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_PASSTHROUGH
#cmakedefine XRT_FEATURE_OPENXR_OVERLAY
#cmakedefine XRT_FEATURE_OPENXR_PLANE_DETECTION
#cmakedefine XRT_FEATURE_OPENXR_SPACE_LOCAL_FLOOR
#cmakedefine XRT_FEATURE_OPENXR_SPACE_UNBOUNDED
#cmakedefine XRT_FEATURE_OPENXR_VISIBILITY_MASK
+27 -2
View File
@@ -571,7 +571,6 @@ oxr_xrGetDisplayRefreshRateFB(XrSession session, float *displayRefreshRate);
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrRequestDisplayRefreshRateFB(XrSession session, float displayRefreshRate);
//! OpenXR API function @ep{xrLocateSpacesKHR}
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrLocateSpacesKHR(XrSession session, const XrSpacesLocateInfoKHR *locateInfo, XrSpaceLocationsKHR *spaceLocations);
@@ -580,6 +579,33 @@ oxr_xrLocateSpacesKHR(XrSession session, const XrSpacesLocateInfoKHR *locateInfo
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrLocateSpaces(XrSession session, const XrSpacesLocateInfo *locateInfo, XrSpaceLocations *spaceLocations);
#ifdef OXR_HAVE_EXT_plane_detection
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrCreatePlaneDetectorEXT(XrSession session,
const XrPlaneDetectorCreateInfoEXT *createInfo,
XrPlaneDetectorEXT *planeDetector);
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrDestroyPlaneDetectorEXT(XrPlaneDetectorEXT planeDetector);
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrBeginPlaneDetectionEXT(XrPlaneDetectorEXT planeDetector, const XrPlaneDetectorBeginInfoEXT *beginInfo);
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrGetPlaneDetectionStateEXT(XrPlaneDetectorEXT planeDetector, XrPlaneDetectionStateEXT *state);
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrGetPlaneDetectionsEXT(XrPlaneDetectorEXT planeDetector,
const XrPlaneDetectorGetInfoEXT *info,
XrPlaneDetectorLocationsEXT *locations);
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrGetPlanePolygonBufferEXT(XrPlaneDetectorEXT planeDetector,
uint64_t planeId,
uint32_t polygonBufferIndex,
XrPlaneDetectorPolygonBufferEXT *polygonBuffer);
#endif // OXR_HAVE_EXT_plane_detection
/*
*
* oxr_api_passthrough.c
@@ -708,7 +734,6 @@ XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrCreateXDevSpaceMNDX(XrSession session, const XrCreateXDevSpaceInfoMNDX *createInfo, XrSpace *space);
#endif
/*!
* @}
*/
@@ -275,6 +275,15 @@ handle_non_null(struct oxr_instance *inst, struct oxr_logger *log, const char *n
ENTRY_IF_EXT(xrPassthroughStartFB, FB_passthrough);
#endif // OXR_HAVE_FB_passthrough
#ifdef OXR_HAVE_EXT_plane_detection
ENTRY_IF_EXT(xrCreatePlaneDetectorEXT, EXT_plane_detection);
ENTRY_IF_EXT(xrDestroyPlaneDetectorEXT, EXT_plane_detection);
ENTRY_IF_EXT(xrBeginPlaneDetectionEXT, EXT_plane_detection);
ENTRY_IF_EXT(xrGetPlaneDetectionStateEXT, EXT_plane_detection);
ENTRY_IF_EXT(xrGetPlaneDetectionsEXT, EXT_plane_detection);
ENTRY_IF_EXT(xrGetPlanePolygonBufferEXT, EXT_plane_detection);
#endif
#ifdef OXR_HAVE_EXT_debug_utils
ENTRY_IF_EXT(xrSetDebugUtilsObjectNameEXT, EXT_debug_utils);
ENTRY_IF_EXT(xrCreateDebugUtilsMessengerEXT, EXT_debug_utils);
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include "math/m_space.h"
#include "xrt/xrt_compiler.h"
#include "util/u_debug.h"
@@ -699,3 +700,378 @@ oxr_xrSetAndroidApplicationThreadKHR(XrSession session, XrAndroidThreadTypeKHR t
}
#endif
#ifdef OXR_HAVE_EXT_plane_detection
static XrResult
oxr_plane_detector_destroy_cb(struct oxr_logger *log, struct oxr_handle_base *hb)
{
struct oxr_plane_detector_ext *pd = (struct oxr_plane_detector_ext *)hb;
free(pd->xr_locations);
if (pd->detection_id > 0) {
enum xrt_result xret = xrt_device_destroy_plane_detection_ext(pd->xdev, pd->detection_id);
if (xret != XRT_SUCCESS) {
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE,
"Internal error in xrDestroyPlaneDetectorEXT: %d", xret);
}
}
xrt_plane_detections_ext_clear(&pd->detections);
free(pd);
return XR_SUCCESS;
}
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrCreatePlaneDetectorEXT(XrSession session,
const XrPlaneDetectorCreateInfoEXT *createInfo,
XrPlaneDetectorEXT *planeDetector)
{
struct oxr_session *sess;
struct oxr_logger log;
OXR_VERIFY_SESSION_AND_INIT_LOG(&log, session, sess, "xrCreatePlaneDetectorEXT");
OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(&log, createInfo, XR_TYPE_PLANE_DETECTOR_CREATE_INFO_EXT);
OXR_VERIFY_EXTENSION(&log, sess->sys->inst, EXT_plane_detection);
//! @todo support planes on other devices
struct xrt_device *xdev = GET_XDEV_BY_ROLE(sess->sys, head);
if (!xdev->planes_supported) {
return XR_ERROR_FEATURE_UNSUPPORTED;
}
if (createInfo->flags != 0 && createInfo->flags != XR_PLANE_DETECTOR_ENABLE_CONTOUR_BIT_EXT) {
//! @todo: Disabled to allow Monado forks with internal extensions to have more values.
return oxr_error(&log, XR_ERROR_VALIDATION_FAILURE, "Invalid plane detector creation flags: %lx",
createInfo->flags);
}
struct oxr_plane_detector_ext *out_pd = NULL;
OXR_ALLOCATE_HANDLE_OR_RETURN(&log, out_pd, OXR_XR_DEBUG_PLANEDET, oxr_plane_detector_destroy_cb,
&sess->handle);
out_pd->sess = sess;
if ((createInfo->flags & XR_PLANE_DETECTOR_ENABLE_CONTOUR_BIT_EXT) != 0) {
out_pd->flags |= XRT_PLANE_DETECTOR_FLAGS_CONTOUR_EXT;
}
out_pd->xdev = xdev;
// no plane detection started on creation
out_pd->state = XR_PLANE_DETECTION_STATE_NONE_EXT;
out_pd->detection_id = 0;
out_pd->xr_locations = NULL;
*planeDetector = oxr_plane_detector_to_openxr(out_pd);
return XR_SUCCESS;
}
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrDestroyPlaneDetectorEXT(XrPlaneDetectorEXT planeDetector)
{
struct oxr_logger log;
struct oxr_plane_detector_ext *pd;
OXR_VERIFY_PLANE_DETECTOR_AND_INIT_LOG(&log, planeDetector, pd, "xrDestroyPlaneDetectorEXT");
return oxr_handle_destroy(&log, &pd->handle);
}
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrBeginPlaneDetectionEXT(XrPlaneDetectorEXT planeDetector, const XrPlaneDetectorBeginInfoEXT *beginInfo)
{
struct oxr_logger log;
struct oxr_plane_detector_ext *pd;
struct oxr_space *spc;
OXR_VERIFY_PLANE_DETECTOR_AND_INIT_LOG(&log, planeDetector, pd, "xrBeginPlaneDetectionEXT");
OXR_VERIFY_SPACE_NOT_NULL(&log, beginInfo->baseSpace, spc);
OXR_VERIFY_ARG_NOT_ZERO(&log, beginInfo->maxPlanes);
OXR_VERIFY_POSE(&log, beginInfo->boundingBoxPose);
if (beginInfo->time < 1) {
return oxr_error(&log, XR_ERROR_TIME_INVALID, "Time %" PRId64 " invalid", beginInfo->time);
}
if (!pd->xdev->planes_supported) {
return XR_ERROR_FEATURE_UNSUPPORTED;
}
if (beginInfo->orientationCount > 0) {
OXR_VERIFY_ARG_NOT_NULL(&log, beginInfo->orientations);
}
// BoundingBox, pose is relative to baseSpace spc
struct xrt_pose T_base_bb = {
.orientation =
{
.x = beginInfo->boundingBoxPose.orientation.x,
.y = beginInfo->boundingBoxPose.orientation.y,
.z = beginInfo->boundingBoxPose.orientation.z,
.w = beginInfo->boundingBoxPose.orientation.w,
},
.position =
{
.x = beginInfo->boundingBoxPose.position.x,
.y = beginInfo->boundingBoxPose.position.y,
.z = beginInfo->boundingBoxPose.position.z,
},
};
// Get plane tracker xdev relation in bounding box baseSpc too. The inverse of this relation is the transform
// from baseSpace spc to xdev space and can transform bounding box pose into xdev space.
struct xrt_space_relation T_base_xdev; // What we get, xdev in base space.
XrResult ret = oxr_space_locate_device(&log, pd->xdev, spc, beginInfo->time, &T_base_xdev);
if (ret != XR_SUCCESS) {
return ret;
}
if (T_base_xdev.relation_flags == 0) {
return XR_ERROR_SPACE_NOT_LOCATABLE_EXT;
}
struct xrt_space_relation T_xdev_bb; // This is what we want, BoundingBox in xdev space.
struct xrt_relation_chain xrc = {0};
m_relation_chain_push_pose_if_not_identity(&xrc, &T_base_bb); // T_base_bb
m_relation_chain_push_inverted_relation(&xrc, &T_base_xdev); // T_xdev_base
m_relation_chain_resolve(&xrc, &T_xdev_bb);
if (T_xdev_bb.relation_flags == 0) {
return XR_ERROR_SPACE_NOT_LOCATABLE_EXT;
}
struct xrt_plane_detector_begin_info_ext query;
// the plane detector id is the raw handle (in our implementation: pointer to xrt_plane_detector)
query.detector_flags = pd->flags;
//! @todo be more graceful
if (beginInfo->orientationCount > XRT_MAX_PLANE_ORIENTATIONS_EXT) {
return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, "Too many plane orientations");
}
if (beginInfo->semanticTypeCount > XRT_MAX_PLANE_SEMANTIC_TYPE_EXT) {
return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, "Too many plane semantic types");
}
query.orientation_count = beginInfo->orientationCount;
for (uint32_t i = 0; i < beginInfo->orientationCount; i++) {
// 1:1 mapped
query.orientations[i] = (enum xrt_plane_detector_orientation_ext)beginInfo->orientations[i];
}
query.semantic_type_count = beginInfo->semanticTypeCount;
for (uint32_t i = 0; i < beginInfo->semanticTypeCount; i++) {
// 1:1 mapped
query.semantic_types[i] = (enum xrt_plane_detector_semantic_type_ext)beginInfo->semanticTypes[i];
}
query.max_planes = beginInfo->maxPlanes;
query.min_area = beginInfo->minArea;
// extents are invariant under pose transforms
query.bounding_box_extent.x = beginInfo->boundingBoxExtent.width;
query.bounding_box_extent.y = beginInfo->boundingBoxExtent.height;
query.bounding_box_extent.z = beginInfo->boundingBoxExtent.depth;
query.bounding_box_pose = T_xdev_bb.pose;
enum xrt_result xret;
// The xrt backend tracks plane detections to be able to clean up when the client dies.
// Because it tracks them as standalone objects, it can not know that this plane detection is replacing a
// previous one. Therefore we need to explicitly destroy the previous detection.
if (pd->detection_id > 0) {
xret = xrt_device_destroy_plane_detection_ext(pd->xdev, pd->detection_id);
if (xret != XRT_SUCCESS) {
return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE,
"Internal error in xrBeginPlaneDetectionEXT: Failed to destroy previous plane "
"detection: %d",
xret);
}
}
xret = xrt_device_begin_plane_detection_ext(pd->xdev, &query, pd->detection_id, &pd->detection_id);
if (xret != XRT_SUCCESS) {
return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, "Internal error in xrBeginPlaneDetectionEXT: %d",
xret);
}
xrt_plane_detections_ext_clear(&pd->detections);
// This makes sure a call to xrGetPlaneDetectionsEXT won't see a previous state, in particular a previous DONE.
pd->state = XR_PLANE_DETECTION_STATE_PENDING_EXT;
return XR_SUCCESS;
}
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrGetPlaneDetectionStateEXT(XrPlaneDetectorEXT planeDetector, XrPlaneDetectionStateEXT *state)
{
struct oxr_logger log;
struct oxr_plane_detector_ext *pd;
enum xrt_result xret;
OXR_VERIFY_PLANE_DETECTOR_AND_INIT_LOG(&log, planeDetector, pd, "xrGetPlaneDetectionsEXT");
enum xrt_plane_detector_state_ext xstate = 0;
xret = xrt_device_get_plane_detection_state_ext(pd->xdev, pd->detection_id, &xstate);
if (xret != XRT_SUCCESS) {
return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, "Internal error in xrGetPlaneDetectionStateEXT: %d",
xret);
}
*state = (XrPlaneDetectionStateEXT)xstate; // 1:1 mapped
pd->state = *state;
return XR_SUCCESS;
}
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrGetPlaneDetectionsEXT(XrPlaneDetectorEXT planeDetector,
const XrPlaneDetectorGetInfoEXT *info,
XrPlaneDetectorLocationsEXT *locations)
{
struct oxr_logger log;
struct oxr_plane_detector_ext *pd;
struct oxr_space *spc;
enum xrt_result xret;
OXR_VERIFY_PLANE_DETECTOR_AND_INIT_LOG(&log, planeDetector, pd, "xrGetPlaneDetectionsEXT");
OXR_VERIFY_SPACE_NOT_NULL(&log, info->baseSpace, spc);
if (info->time < 1) {
return oxr_error(&log, XR_ERROR_TIME_INVALID, "Time %" PRId64 " invalid", info->time);
}
if (!pd->xdev->planes_supported) {
return XR_ERROR_FEATURE_UNSUPPORTED;
}
if (pd->state != XR_PLANE_DETECTION_STATE_DONE_EXT) {
locations->planeLocationCountOutput = 0;
return XR_ERROR_CALL_ORDER_INVALID;
}
xret = xrt_device_get_plane_detections_ext(pd->xdev, pd->detection_id, &pd->detections);
if (xret != XRT_SUCCESS) {
return oxr_error(&log, XR_ERROR_RUNTIME_FAILURE, "Internal error in xrGetPlaneDetectionsEXT: %d", xret);
}
struct xrt_space_relation T_base_xdev; // What we get, xdev in base space.
XrResult ret = oxr_space_locate_device(&log, pd->xdev, spc, info->time, &T_base_xdev);
if (ret != XR_SUCCESS) {
return ret;
}
if (T_base_xdev.relation_flags == 0) {
return XR_ERROR_SPACE_NOT_LOCATABLE_EXT;
}
// create dynamic array for two call idiom
U_ARRAY_REALLOC_OR_FREE(pd->xr_locations, XrPlaneDetectorLocationEXT, pd->detections.location_count);
if (pd->detections.location_count == 0) {
pd->xr_locations = NULL;
}
// populate pd->xr_locations from pd->detections.locations, also transform plane poses into baseSpace.
for (uint32_t i = 0; i < pd->detections.location_count; i++) {
pd->xr_locations[i].planeId = pd->detections.locations[i].planeId;
pd->xr_locations[i].extents.width = pd->detections.locations[i].extents.x;
pd->xr_locations[i].extents.height = pd->detections.locations[i].extents.y;
// 1:1 mapped
pd->xr_locations[i].orientation =
(XrPlaneDetectorOrientationEXT)pd->detections.locations[i].orientation;
pd->xr_locations[i].semanticType =
(XrPlaneDetectorSemanticTypeEXT)pd->detections.locations[i].semantic_type;
pd->xr_locations[i].polygonBufferCount = pd->detections.locations[i].polygon_buffer_count;
// The plane poses are returned in the xdev's space.
struct xrt_space_relation T_xdev_plane = pd->detections.locations[i].relation;
// Get the plane pose in the base space.
struct xrt_space_relation T_base_plane;
struct xrt_relation_chain xrc = {0};
m_relation_chain_push_relation(&xrc, &T_xdev_plane);
m_relation_chain_push_relation(&xrc, &T_base_xdev);
m_relation_chain_resolve(&xrc, &T_base_plane);
OXR_XRT_POSE_TO_XRPOSEF(T_base_plane.pose, pd->xr_locations[i].pose);
pd->xr_locations[i].locationFlags = 0;
if ((T_base_plane.relation_flags & XRT_SPACE_RELATION_ORIENTATION_VALID_BIT) != 0) {
pd->xr_locations[i].locationFlags |= XR_SPACE_LOCATION_ORIENTATION_VALID_BIT;
}
if ((T_base_plane.relation_flags & XRT_SPACE_RELATION_POSITION_VALID_BIT) != 0) {
pd->xr_locations[i].locationFlags |= XR_SPACE_LOCATION_POSITION_VALID_BIT;
}
if ((T_base_plane.relation_flags & XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT) != 0) {
pd->xr_locations[i].locationFlags |= XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT;
}
if ((T_base_plane.relation_flags & XRT_SPACE_RELATION_POSITION_TRACKED_BIT) != 0) {
pd->xr_locations[i].locationFlags |= XR_SPACE_LOCATION_POSITION_TRACKED_BIT;
}
}
OXR_TWO_CALL_HELPER(&log, locations->planeLocationCapacityInput, &locations->planeLocationCountOutput,
locations->planeLocations, pd->detections.location_count, pd->xr_locations, XR_SUCCESS);
return XR_SUCCESS;
}
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrGetPlanePolygonBufferEXT(XrPlaneDetectorEXT planeDetector,
uint64_t planeId,
uint32_t polygonBufferIndex,
XrPlaneDetectorPolygonBufferEXT *polygonBuffer)
{
struct oxr_logger log;
struct oxr_plane_detector_ext *pd;
OXR_VERIFY_PLANE_DETECTOR_AND_INIT_LOG(&log, planeDetector, pd, "xrGetPlaneDetectionsEXT");
//! @todo can't reasonably retrieve a polygon without having retrieved plane data first.
if (pd->state != XR_PLANE_DETECTION_STATE_DONE_EXT) {
return oxr_error(&log, XR_ERROR_VALIDATION_FAILURE,
"xrGetPlanePolygonBufferEXT called but plane detector state is %d", pd->state);
}
// find the index of the plane in both pd->locations and pd->polygons_ptr arrays.
uint32_t plane_index = UINT32_MAX;
for (uint32_t i = 0; i < pd->detections.location_count; i++) {
if (pd->detections.locations[i].planeId == planeId) {
plane_index = i;
break;
}
}
if (plane_index == UINT32_MAX) {
return oxr_error(&log, XR_ERROR_VALIDATION_FAILURE, "Invalid plane id %" PRId64, planeId);
}
if (polygonBufferIndex + 1 > pd->detections.locations[plane_index].polygon_buffer_count) {
return oxr_error(&log, XR_ERROR_VALIDATION_FAILURE, "Invalid polygon buffer index %u (> %u)",
polygonBufferIndex, pd->detections.locations[plane_index].polygon_buffer_count - 1);
}
uint32_t polygons_start_index = pd->detections.polygon_info_start_index[plane_index];
uint32_t polygon_index = polygons_start_index + polygonBufferIndex;
uint32_t vertices_start_index = pd->detections.polygon_infos[polygon_index].vertices_start_index;
// xrt_vec2 should mapped 1:1 to XrVector2f
XrVector2f *polygon_vertices = (XrVector2f *)&pd->detections.vertices[vertices_start_index];
uint32_t vertex_count = pd->detections.polygon_infos[polygon_index].vertex_count;
OXR_TWO_CALL_HELPER(&log, polygonBuffer->vertexCapacityInput, &polygonBuffer->vertexCountOutput,
polygonBuffer->vertices, vertex_count, polygon_vertices, XR_SUCCESS);
}
#endif // OXR_HAVE_EXT_plane_detection
@@ -90,6 +90,8 @@ struct oxr_subaction_paths;
OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_body_tracker_fb, BTRACKER, name, new_thing->sess->sys->inst)
#define OXR_VERIFY_XDEVLIST_AND_INIT_LOG(log, thing, new_thing, name) \
OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_xdev_list, XDEVLIST, name, new_thing->sess->sys->inst)
#define OXR_VERIFY_PLANE_DETECTOR_AND_INIT_LOG(log, thing, new_thing, name) \
OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_plane_detector_ext, PLANEDET, name, new_thing->sess->sys->inst)
// clang-format on
#define OXR_VERIFY_INSTANCE_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_instance, INSTANCE);
+2
View File
@@ -32,6 +32,8 @@
// body tracker
#define OXR_XR_DEBUG_BTRACKER (*(uint64_t *)"oxrbtra\0")
#define OXR_XR_DEBUG_XDEVLIST (*(uint64_t *)"oxrxdli\0")
// plane detection
#define OXR_XR_DEBUG_PLANEDET (*(uint64_t *)"oxrplan\0")
// clang-format on
/*!
@@ -577,6 +577,17 @@
#endif
/*
* XR_EXT_plane_detection
*/
#if defined(XR_EXT_plane_detection) && defined(XRT_FEATURE_OPENXR_PLANE_DETECTION)
#define OXR_HAVE_EXT_plane_detection
#define OXR_EXTENSION_SUPPORT_EXT_plane_detection(_) _(EXT_plane_detection, EXT_PLANE_DETECTION)
#else
#define OXR_EXTENSION_SUPPORT_EXT_plane_detection(_)
#endif
/*
* XR_MND_headless
*/
@@ -820,6 +831,7 @@
OXR_EXTENSION_SUPPORT_HTC_facial_tracking(_) \
OXR_EXTENSION_SUPPORT_META_touch_controller_plus(_) \
OXR_EXTENSION_SUPPORT_ML_ml2_controller_interaction(_) \
OXR_EXTENSION_SUPPORT_EXT_plane_detection(_) \
OXR_EXTENSION_SUPPORT_MND_headless(_) \
OXR_EXTENSION_SUPPORT_MND_swapchain_usage_input_attachment_bit(_) \
OXR_EXTENSION_SUPPORT_MSFT_hand_interaction(_) \
+56
View File
@@ -130,6 +130,7 @@ struct oxr_facial_tracker_htc;
struct oxr_face_tracker2_fb;
struct oxr_body_tracker_fb;
struct oxr_xdev_list;
struct oxr_plane_detector_ext;
#define XRT_MAX_HANDLE_CHILDREN 256
#define OXR_MAX_BINDINGS_PER_ACTION 32
@@ -381,6 +382,19 @@ oxr_hand_tracker_to_openxr(struct oxr_hand_tracker *hand_tracker)
return XRT_CAST_PTR_TO_OXR_HANDLE(XrHandTrackerEXT, hand_tracker);
}
#ifdef OXR_HAVE_EXT_plane_detection
/*!
* To go back to a OpenXR object.
*
* @relates oxr_plane_detector
*/
static inline XrPlaneDetectorEXT
oxr_plane_detector_to_openxr(struct oxr_plane_detector_ext *plane_detector)
{
return XRT_CAST_PTR_TO_OXR_HANDLE(XrPlaneDetectorEXT, plane_detector);
}
#endif // OXR_HAVE_EXT_plane_detection
/*!
* To go back to a OpenXR object.
*
@@ -2839,6 +2853,48 @@ struct oxr_xdev_list
};
#endif // OXR_HAVE_MNDX_xdev_space
#ifdef OXR_HAVE_EXT_plane_detection
/*!
* A Plane Detector.
*
* Parent type/handle is @ref oxr_session
*
*
* @obj{XrPlaneDetectorEXT}
* @extends oxr_handle_base
*/
struct oxr_plane_detector_ext
{
//! Common structure for things referred to by OpenXR handles.
struct oxr_handle_base handle;
//! Owner of this anchor.
struct oxr_session *sess;
//! Plane detector flags.
enum xrt_plane_detector_flags_ext flags;
//! The last known state of this plane detector.
XrPlaneDetectionStateEXT state;
//! Whether the last DONE plane detection has been retrieved from the xdev.
bool retrieved;
//! The device that this plane detector belongs to.
struct xrt_device *xdev;
//! Detected planes. xrt_plane_detector_locations_ext::relation is kept in xdev space and not updated.
struct xrt_plane_detections_ext detections;
//! Corresponds to xrt_plane_detections_ext::locations, but with OpenXR types and transformed into target space.
//! Enables two call idiom.
XrPlaneDetectorLocationEXT *xr_locations;
//! A globally unique id for the current plane detection or 0, generated by the xrt_device.
uint64_t detection_id;
};
#endif // OXR_HAVE_EXT_plane_detection
/*!
* @}
*/
+14
View File
@@ -508,6 +508,20 @@ oxr_system_get_properties(struct oxr_logger *log, struct oxr_system *sys, XrSyst
}
#endif // OXR_HAVE_MNDX_xdev_space
#ifdef OXR_HAVE_EXT_plane_detection
XrSystemPlaneDetectionPropertiesEXT *plane_detection_props = NULL;
if (sys->inst->extensions.EXT_plane_detection) {
plane_detection_props = OXR_GET_OUTPUT_FROM_CHAIN(
properties, XR_TYPE_SYSTEM_PLANE_DETECTION_PROPERTIES_EXT, XrSystemPlaneDetectionPropertiesEXT);
}
if (plane_detection_props) {
// for now these are mapped 1:1
plane_detection_props->supportedFeatures =
(XrPlaneDetectionCapabilityFlagsEXT)xdev->plane_capability_flags;
}
#endif // OXR_HAVE_EXT_plane_detection
return XR_SUCCESS;
}