diff options
Diffstat (limited to 'source/blender/windowmanager/xr/intern/wm_xr_session.c')
-rw-r--r-- | source/blender/windowmanager/xr/intern/wm_xr_session.c | 187 |
1 files changed, 152 insertions, 35 deletions
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c index 9f53db1347c..3224869b04a 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_session.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c @@ -66,11 +66,20 @@ static void wm_xr_session_create_cb(void) Main *bmain = G_MAIN; wmWindowManager *wm = bmain->wm.first; wmXrData *xr_data = &wm->xr; + wmXrSessionState *state = &xr_data->runtime->session_state; + XrSessionSettings *settings = &xr_data->session_settings; /* Get action set data from Python. */ BKE_callback_exec_null(bmain, BKE_CB_EVT_XR_SESSION_START_PRE); wm_xr_session_actions_init(xr_data); + + /* Initialize navigation. */ + WM_xr_session_state_navigation_reset(state); + if (settings->base_scale < FLT_EPSILON) { + settings->base_scale = 1.0f; + } + state->prev_base_scale = settings->base_scale; } static void wm_xr_session_controller_data_free(wmXrSessionState *state) @@ -128,8 +137,10 @@ void wm_xr_session_toggle(wmWindowManager *wm, wmXrData *xr_data = &wm->xr; if (WM_xr_session_exists(xr_data)) { - GHOST_XrSessionEnd(xr_data->runtime->context); + /* Must set first, since #GHOST_XrSessionEnd() may immediately free the runtime. */ xr_data->runtime->session_state.is_started = false; + + GHOST_XrSessionEnd(xr_data->runtime->context); } else { GHOST_XrSessionBeginInfo begin_info; @@ -167,7 +178,8 @@ bool WM_xr_session_is_ready(const wmXrData *xr) static void wm_xr_session_base_pose_calc(const Scene *scene, const XrSessionSettings *settings, - GHOST_XrPose *r_base_pose) + GHOST_XrPose *r_base_pose, + float *r_base_scale) { const Object *base_pose_object = ((settings->base_pose_type == XR_BASE_POSE_OBJECT) && settings->base_pose_object) ? @@ -198,6 +210,8 @@ static void wm_xr_session_base_pose_calc(const Scene *scene, copy_v3_fl(r_base_pose->position, 0.0f); axis_angle_to_quat_single(r_base_pose->orientation_quat, 'X', M_PI_2); } + + *r_base_scale = settings->base_scale; } static void wm_xr_session_draw_data_populate(wmXrData *xr_data, @@ -213,7 +227,8 @@ static void wm_xr_session_draw_data_populate(wmXrData *xr_data, r_draw_data->xr_data = xr_data; r_draw_data->surface_data = g_xr_surface->customdata; - wm_xr_session_base_pose_calc(r_draw_data->scene, settings, &r_draw_data->base_pose); + wm_xr_session_base_pose_calc( + r_draw_data->scene, settings, &r_draw_data->base_pose, &r_draw_data->base_scale); } wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm, @@ -291,7 +306,7 @@ static wmXrSessionStateEvent wm_xr_session_state_to_event(const wmXrSessionState return SESSION_STATE_EVENT_NONE; } -void wm_xr_session_draw_data_update(const wmXrSessionState *state, +void wm_xr_session_draw_data_update(wmXrSessionState *state, const XrSessionSettings *settings, const GHOST_XrDrawViewInfo *draw_view, wmXrDrawData *draw_data) @@ -319,6 +334,8 @@ void wm_xr_session_draw_data_update(const wmXrSessionState *state, else { copy_v3_fl(draw_data->eye_position_ofs, 0.0f); } + /* Reset navigation. */ + WM_xr_session_state_navigation_reset(state); break; case SESSION_STATE_EVENT_POSITION_TRACKING_TOGGLE: if (use_position_tracking) { @@ -348,29 +365,32 @@ void wm_xr_session_state_update(const XrSessionSettings *settings, wmXrSessionState *state) { 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, - draw_view->local_pose.orientation_quat); - 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. */ - 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); - wm_xr_pose_to_imat(&viewer_pose, state->viewer_viewmat); + float viewer_mat[4][4], base_mat[4][4], nav_mat[4][4]; + + /* Calculate viewer matrix. */ + copy_qt_qt(viewer_pose.orientation_quat, draw_view->local_pose.orientation_quat); + if ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) { + zero_v3(viewer_pose.position); + } + else { + copy_v3_v3(viewer_pose.position, draw_view->local_pose.position); + } + if ((settings->flag & XR_SESSION_USE_ABSOLUTE_TRACKING) == 0) { + sub_v3_v3(viewer_pose.position, draw_data->eye_position_ofs); + } + wm_xr_pose_to_mat(&viewer_pose, viewer_mat); + + /* Apply base pose and navigation. */ + wm_xr_pose_scale_to_mat(&draw_data->base_pose, draw_data->base_scale, base_mat); + wm_xr_pose_scale_to_mat(&state->nav_pose_prev, state->nav_scale_prev, nav_mat); + mul_m4_m4m4(state->viewer_mat_base, base_mat, viewer_mat); + mul_m4_m4m4(viewer_mat, nav_mat, state->viewer_mat_base); + + /* Save final viewer pose and viewmat. */ + mat4_to_loc_quat(state->viewer_pose.position, state->viewer_pose.orientation_quat, viewer_mat); + wm_xr_pose_scale_to_imat( + &state->viewer_pose, draw_data->base_scale * state->nav_scale_prev, state->viewer_viewmat); + /* No idea why, but multiplying by two seems to make it match the VR view more. */ state->focal_len = 2.0f * fov_to_focallength(draw_view->fov.angle_right - draw_view->fov.angle_left, @@ -378,7 +398,10 @@ void wm_xr_session_state_update(const XrSessionSettings *settings, copy_v3_v3(state->prev_eye_position_ofs, draw_data->eye_position_ofs); memcpy(&state->prev_base_pose, &draw_data->base_pose, sizeof(state->prev_base_pose)); + state->prev_base_scale = draw_data->base_scale; memcpy(&state->prev_local_pose, &draw_view->local_pose, sizeof(state->prev_local_pose)); + copy_v3_v3(state->prev_eye_position_ofs, draw_data->eye_position_ofs); + state->prev_settings_flag = settings->flag; state->prev_base_pose_type = settings->base_pose_type; state->prev_base_pose_object = settings->base_pose_object; @@ -503,6 +526,74 @@ bool WM_xr_session_state_controller_aim_rotation_get(const wmXrData *xr, return true; } +bool WM_xr_session_state_nav_location_get(const wmXrData *xr, float r_location[3]) +{ + if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) { + zero_v3(r_location); + return false; + } + + copy_v3_v3(r_location, xr->runtime->session_state.nav_pose.position); + return true; +} + +void WM_xr_session_state_nav_location_set(wmXrData *xr, const float location[3]) +{ + if (WM_xr_session_exists(xr)) { + copy_v3_v3(xr->runtime->session_state.nav_pose.position, location); + xr->runtime->session_state.is_navigation_dirty = true; + } +} + +bool WM_xr_session_state_nav_rotation_get(const wmXrData *xr, float r_rotation[4]) +{ + if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) { + unit_qt(r_rotation); + return false; + } + + copy_qt_qt(r_rotation, xr->runtime->session_state.nav_pose.orientation_quat); + return true; +} + +void WM_xr_session_state_nav_rotation_set(wmXrData *xr, const float rotation[4]) +{ + if (WM_xr_session_exists(xr)) { + BLI_ASSERT_UNIT_QUAT(rotation); + copy_qt_qt(xr->runtime->session_state.nav_pose.orientation_quat, rotation); + xr->runtime->session_state.is_navigation_dirty = true; + } +} + +bool WM_xr_session_state_nav_scale_get(const wmXrData *xr, float *r_scale) +{ + if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) { + *r_scale = 1.0f; + return false; + } + + *r_scale = xr->runtime->session_state.nav_scale; + return true; +} + +void WM_xr_session_state_nav_scale_set(wmXrData *xr, float scale) +{ + if (WM_xr_session_exists(xr)) { + /* Clamp to reasonable values. */ + CLAMP(scale, xr->session_settings.clip_start, xr->session_settings.clip_end); + xr->runtime->session_state.nav_scale = scale; + xr->runtime->session_state.is_navigation_dirty = true; + } +} + +void WM_xr_session_state_navigation_reset(wmXrSessionState *state) +{ + zero_v3(state->nav_pose.position); + unit_qt(state->nav_pose.orientation_quat); + state->nav_scale = 1.0f; + state->is_navigation_dirty = true; +} + /* -------------------------------------------------------------------- */ /** \name XR-Session Actions * @@ -522,16 +613,21 @@ void wm_xr_session_actions_init(wmXrData *xr) static void wm_xr_session_controller_pose_calc(const GHOST_XrPose *raw_pose, const float view_ofs[3], const float base_mat[4][4], + const float nav_mat[4][4], GHOST_XrPose *r_pose, - float r_mat[4][4]) + float r_mat[4][4], + float r_mat_base[4][4]) { float m[4][4]; /* Calculate controller matrix in world space. */ wm_xr_pose_to_mat(raw_pose, m); - /* Apply eye position and base pose offsets. */ + /* Apply eye position offset. */ sub_v3_v3(m[3], view_ofs); - mul_m4_m4m4(r_mat, base_mat, m); + + /* Apply base pose and navigation. */ + mul_m4_m4m4(r_mat_base, base_mat, m); + mul_m4_m4m4(r_mat, nav_mat, r_mat_base); /* Save final pose. */ mat4_to_loc_quat(r_pose->position, r_pose->orientation_quat, r_mat); @@ -547,7 +643,7 @@ static void wm_xr_session_controller_data_update(const XrSessionSettings *settin BLI_assert(grip_action->count_subaction_paths == BLI_listbase_count(&state->controllers)); unsigned int subaction_idx = 0; - float view_ofs[3], base_mat[4][4]; + float view_ofs[3], base_mat[4][4], nav_mat[4][4]; if ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) { copy_v3_v3(view_ofs, state->prev_local_pose.position); @@ -559,19 +655,24 @@ static void wm_xr_session_controller_data_update(const XrSessionSettings *settin add_v3_v3(view_ofs, state->prev_eye_position_ofs); } - wm_xr_pose_to_mat(&state->prev_base_pose, base_mat); + wm_xr_pose_scale_to_mat(&state->prev_base_pose, state->prev_base_scale, base_mat); + wm_xr_pose_scale_to_mat(&state->nav_pose, state->nav_scale, nav_mat); LISTBASE_FOREACH_INDEX (wmXrController *, controller, &state->controllers, subaction_idx) { wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)grip_action->states)[subaction_idx], view_ofs, base_mat, + nav_mat, &controller->grip_pose, - controller->grip_mat); + controller->grip_mat, + controller->grip_mat_base); wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)aim_action->states)[subaction_idx], view_ofs, base_mat, + nav_mat, &controller->aim_pose, - controller->aim_mat); + controller->aim_mat, + controller->aim_mat_base); if (!controller->model) { /* Notify GHOST to load/continue loading the controller model data. This can be called more @@ -1094,10 +1195,26 @@ void wm_xr_session_actions_update(wmWindowManager *wm) return; } + XrSessionSettings *settings = &xr->session_settings; GHOST_XrContextHandle xr_context = xr->runtime->context; wmXrSessionState *state = &xr->runtime->session_state; wmXrActionSet *active_action_set = state->active_action_set; + if (state->is_navigation_dirty) { + memcpy(&state->nav_pose_prev, &state->nav_pose, sizeof(state->nav_pose_prev)); + state->nav_scale_prev = state->nav_scale; + state->is_navigation_dirty = false; + + /* Update viewer pose with any navigation changes since the last actions sync so that data + * is correct for queries. */ + float m[4][4], viewer_mat[4][4]; + wm_xr_pose_scale_to_mat(&state->nav_pose, state->nav_scale, m); + mul_m4_m4m4(viewer_mat, m, state->viewer_mat_base); + mat4_to_loc_quat(state->viewer_pose.position, state->viewer_pose.orientation_quat, viewer_mat); + wm_xr_pose_scale_to_imat( + &state->viewer_pose, settings->base_scale * state->nav_scale, state->viewer_viewmat); + } + int ret = GHOST_XrSyncActions(xr_context, active_action_set ? active_action_set->name : NULL); if (!ret) { return; @@ -1108,7 +1225,7 @@ void wm_xr_session_actions_update(wmWindowManager *wm) wmWindow *win = wm_xr_session_root_window_or_fallback_get(wm, xr->runtime); if (active_action_set->controller_grip_action && active_action_set->controller_aim_action) { - wm_xr_session_controller_data_update(&xr->session_settings, + wm_xr_session_controller_data_update(settings, active_action_set->controller_grip_action, active_action_set->controller_aim_action, xr_context, |