diff options
-rw-r--r-- | intern/ghost/intern/GHOST_XrSession.cpp | 45 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_xr_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_xr.c | 88 | ||||
-rw-r--r-- | source/blender/windowmanager/xr/intern/wm_xr_draw.c | 4 | ||||
-rw-r--r-- | source/blender/windowmanager/xr/intern/wm_xr_session.c | 18 |
5 files changed, 129 insertions, 27 deletions
diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp index 35280e77e22..263b2b6cfbd 100644 --- a/intern/ghost/intern/GHOST_XrSession.cpp +++ b/intern/ghost/intern/GHOST_XrSession.cpp @@ -120,7 +120,7 @@ static void create_reference_spaces(OpenXRSessionData &oxr, const GHOST_XrPose & XrReferenceSpaceCreateInfo create_info = {XR_TYPE_REFERENCE_SPACE_CREATE_INFO}; create_info.poseInReferenceSpace.orientation.w = 1.0f; - create_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL; + create_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE; #if 0 /* TODO * @@ -144,8 +144,47 @@ static void create_reference_spaces(OpenXRSessionData &oxr, const GHOST_XrPose & (void)base_pose; #endif - CHECK_XR(xrCreateReferenceSpace(oxr.session, &create_info, &oxr.reference_space), - "Failed to create reference space."); + XrResult result = xrCreateReferenceSpace(oxr.session, &create_info, &oxr.reference_space); + + if (XR_FAILED(result)) { + /* One of the rare cases where we don't want to immediately throw an exception on failure, + * since runtimes are not required to support the stage reference space. Although we need the + * stage reference space for absolute tracking, if the runtime doesn't support it then just + * fallback to the local space. */ + if (result == XR_ERROR_REFERENCE_SPACE_UNSUPPORTED) { + printf( + "Warning: XR runtime does not support stage reference space, disabling absolute " + "tracking.\n"); + + create_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL; + CHECK_XR(xrCreateReferenceSpace(oxr.session, &create_info, &oxr.reference_space), + "Failed to create local reference space."); + } + else { + throw GHOST_XrException("Failed to create stage reference space.", result); + } + } + else { + /* Check if tracking bounds are valid. Tracking bounds may be invalid if the user did not + * define a tracking space via the XR runtime. */ + XrExtent2Df extents; + CHECK_XR(xrGetReferenceSpaceBoundsRect(oxr.session, XR_REFERENCE_SPACE_TYPE_STAGE, &extents), + "Failed to get stage reference space bounds."); + if (extents.width == 0.0f || extents.height == 0.0f) { + printf( + "Warning: Invalid stage reference space bounds, disabling absolute tracking. To enable " + "absolute tracking, please define a tracking space via the XR runtime.\n"); + + /* Fallback to local space. */ + if (oxr.reference_space != XR_NULL_HANDLE) { + CHECK_XR(xrDestroySpace(oxr.reference_space), "Failed to destroy stage reference space."); + } + + create_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL; + CHECK_XR(xrCreateReferenceSpace(oxr.session, &create_info, &oxr.reference_space), + "Failed to create local reference space."); + } + } create_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW; CHECK_XR(xrCreateReferenceSpace(oxr.session, &create_info, &oxr.view_space), diff --git a/source/blender/makesdna/DNA_xr_types.h b/source/blender/makesdna/DNA_xr_types.h index 8e63760fef7..fc00d5eb839 100644 --- a/source/blender/makesdna/DNA_xr_types.h +++ b/source/blender/makesdna/DNA_xr_types.h @@ -50,6 +50,7 @@ typedef struct XrSessionSettings { typedef enum eXrSessionFlag { XR_SESSION_USE_POSITION_TRACKING = (1 << 0), + XR_SESSION_USE_ABSOLUTE_TRACKING = (1 << 1), } eXrSessionFlag; typedef enum eXRSessionBasePoseType { diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index 04a8500d136..56e8418972c 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -34,6 +34,63 @@ # include "WM_api.h" +# ifdef WITH_XR_OPENXR +static wmXrData *rna_XrSession_wm_xr_data_get(PointerRNA *ptr) +{ + /* Callers could also get XrSessionState pointer through ptr->data, but prefer if we just + * consistently pass wmXrData pointers to the WM_xr_xxx() API. */ + + BLI_assert((ptr->type == &RNA_XrSessionSettings) || (ptr->type == &RNA_XrSessionState)); + + wmWindowManager *wm = (wmWindowManager *)ptr->owner_id; + BLI_assert(wm && (GS(wm->id.name) == ID_WM)); + + return &wm->xr; +} +# endif + +static bool rna_XrSessionSettings_use_positional_tracking_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + return (xr->session_settings.flag & XR_SESSION_USE_POSITION_TRACKING) != 0; +# else + UNUSED_VARS(ptr); + return false; +# endif +} + +static void rna_XrSessionSettings_use_positional_tracking_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + SET_FLAG_FROM_TEST(xr->session_settings.flag, value, XR_SESSION_USE_POSITION_TRACKING); +# else + UNUSED_VARS(ptr, value); +# endif +} + +static bool rna_XrSessionSettings_use_absolute_tracking_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + return (xr->session_settings.flag & XR_SESSION_USE_ABSOLUTE_TRACKING) != 0; +# else + UNUSED_VARS(ptr); + return false; +# endif +} + +static void rna_XrSessionSettings_use_absolute_tracking_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + SET_FLAG_FROM_TEST(xr->session_settings.flag, value, XR_SESSION_USE_ABSOLUTE_TRACKING); +# else + UNUSED_VARS(ptr, value); +# endif +} + static bool rna_XrSessionState_is_running(bContext *C) { # ifdef WITH_XR_OPENXR @@ -55,25 +112,10 @@ static void rna_XrSessionState_reset_to_base_pose(bContext *C) # endif } -# ifdef WITH_XR_OPENXR -static wmXrData *rna_XrSessionState_wm_xr_data_get(PointerRNA *ptr) -{ - /* Callers could also get XrSessionState pointer through ptr->data, but prefer if we just - * consistently pass wmXrData pointers to the WM_xr_xxx() API. */ - - BLI_assert(ptr->type == &RNA_XrSessionState); - - wmWindowManager *wm = (wmWindowManager *)ptr->owner_id; - BLI_assert(wm && (GS(wm->id.name) == ID_WM)); - - return &wm->xr; -} -# endif - static void rna_XrSessionState_viewer_pose_location_get(PointerRNA *ptr, float *r_values) { # ifdef WITH_XR_OPENXR - const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr); + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); WM_xr_session_state_viewer_pose_location_get(xr, r_values); # else UNUSED_VARS(ptr); @@ -84,7 +126,7 @@ static void rna_XrSessionState_viewer_pose_location_get(PointerRNA *ptr, float * static void rna_XrSessionState_viewer_pose_rotation_get(PointerRNA *ptr, float *r_values) { # ifdef WITH_XR_OPENXR - const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr); + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); WM_xr_session_state_viewer_pose_rotation_get(xr, r_values); # else UNUSED_VARS(ptr); @@ -181,12 +223,22 @@ static void rna_def_xr_session_settings(BlenderRNA *brna) RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL); prop = RNA_def_property(srna, "use_positional_tracking", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", XR_SESSION_USE_POSITION_TRACKING); + RNA_def_property_boolean_funcs(prop, + "rna_XrSessionSettings_use_positional_tracking_get", + "rna_XrSessionSettings_use_positional_tracking_set"); RNA_def_property_ui_text( prop, "Positional Tracking", "Allow VR headsets to affect the location in virtual space, in addition to the rotation"); RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL); + + prop = RNA_def_property(srna, "use_absolute_tracking", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, + "rna_XrSessionSettings_use_absolute_tracking_get", + "rna_XrSessionSettings_use_absolute_tracking_set"); + RNA_def_property_ui_text( + prop, "Absolute Tracking", "Use unadjusted location/rotation as defined by the XR runtime"); + RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL); } static void rna_def_xr_session_state(BlenderRNA *brna) diff --git a/source/blender/windowmanager/xr/intern/wm_xr_draw.c b/source/blender/windowmanager/xr/intern/wm_xr_draw.c index 1f722855696..bef88505488 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_draw.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_draw.c @@ -61,10 +61,12 @@ static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data, copy_qt_qt(eye_pose.orientation_quat, draw_view->eye_pose.orientation_quat); copy_v3_v3(eye_pose.position, draw_view->eye_pose.position); - sub_v3_v3(eye_pose.position, draw_data->eye_position_ofs); if ((session_settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) { sub_v3_v3(eye_pose.position, draw_view->local_pose.position); } + if ((session_settings->flag & XR_SESSION_USE_ABSOLUTE_TRACKING) == 0) { + sub_v3_v3(eye_pose.position, draw_data->eye_position_ofs); + } perspective_m4_fov(r_proj_mat, draw_view->fov.angle_left, diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c index c9c158b9feb..b740cb27471 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_session.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c @@ -317,6 +317,7 @@ void wm_xr_session_state_update(const XrSessionSettings *settings, { GHOST_XrPose viewer_pose; const bool use_position_tracking = settings->flag & XR_SESSION_USE_POSITION_TRACKING; + const bool use_absolute_tracking = settings->flag & XR_SESSION_USE_ABSOLUTE_TRACKING; mul_qt_qtqt(viewer_pose.orientation_quat, draw_data->base_pose.orientation_quat, @@ -324,14 +325,16 @@ void wm_xr_session_state_update(const XrSessionSettings *settings, copy_v3_v3(viewer_pose.position, draw_data->base_pose.position); /* The local pose and the eye pose (which is copied from an earlier local pose) both are view * space, so Y-up. In this case we need them in regular Z-up. */ - viewer_pose.position[0] -= draw_data->eye_position_ofs[0]; - viewer_pose.position[1] += draw_data->eye_position_ofs[2]; - viewer_pose.position[2] -= draw_data->eye_position_ofs[1]; if (use_position_tracking) { viewer_pose.position[0] += draw_view->local_pose.position[0]; viewer_pose.position[1] -= draw_view->local_pose.position[2]; viewer_pose.position[2] += draw_view->local_pose.position[1]; } + if (!use_absolute_tracking) { + viewer_pose.position[0] -= draw_data->eye_position_ofs[0]; + viewer_pose.position[1] += draw_data->eye_position_ofs[2]; + viewer_pose.position[2] -= draw_data->eye_position_ofs[1]; + } copy_v3_v3(state->viewer_pose.position, viewer_pose.position); copy_qt_qt(state->viewer_pose.orientation_quat, viewer_pose.orientation_quat); @@ -451,9 +454,14 @@ static void wm_xr_session_controller_mats_update(const XrSessionSettings *settin float base_inv[4][4]; float tmp[4][4]; - zero_v3(view_ofs); if ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) { - add_v3_v3(view_ofs, state->prev_local_pose.position); + copy_v3_v3(view_ofs, state->prev_local_pose.position); + } + else { + zero_v3(view_ofs); + } + if ((settings->flag & XR_SESSION_USE_ABSOLUTE_TRACKING) == 0) { + add_v3_v3(view_ofs, state->prev_eye_position_ofs); } wm_xr_pose_to_viewmat(&state->prev_base_pose, base_inv); |