/* SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup wm */ #pragma once #include "CLG_log.h" #include "wm_xr.h" struct wmXrActionSet; typedef struct wmXrSessionState { bool is_started; /** Last known viewer pose (centroid of eyes, in world space) stored for queries. */ GHOST_XrPose viewer_pose; /** The last known view matrix, calculated from above's viewer pose. */ float viewer_viewmat[4][4]; /** The last known viewer matrix, without navigation applied. */ float viewer_mat_base[4][4]; float focal_len; /** Copy of XrSessionSettings.base_pose_ data to detect changes that need * resetting to base pose. */ char prev_base_pose_type; /* #eXRSessionBasePoseType */ Object *prev_base_pose_object; /** Copy of XrSessionSettings.flag created on the last draw call, stored to detect changes. */ int prev_settings_flag; /** Copy of wmXrDrawData.base_pose. */ GHOST_XrPose prev_base_pose; /** Copy of wmXrDrawData.base_scale. */ float prev_base_scale; /** Copy of GHOST_XrDrawViewInfo.local_pose. */ GHOST_XrPose prev_local_pose; /** Copy of wmXrDrawData.eye_position_ofs. */ float prev_eye_position_ofs[3]; bool force_reset_to_base_pose; bool is_view_data_set; /** Current navigation transforms. */ GHOST_XrPose nav_pose; float nav_scale; /** Navigation transforms from the last actions sync, used to calculate the viewer/controller * poses. */ GHOST_XrPose nav_pose_prev; float nav_scale_prev; bool is_navigation_dirty; /** Last known controller data. */ ListBase controllers; /* #wmXrController */ /** The currently active action set that will be updated on calls to * wm_xr_session_actions_update(). If NULL, all action sets will be treated as active and * updated. */ struct wmXrActionSet *active_action_set; } wmXrSessionState; typedef struct wmXrRuntimeData { GHOST_XrContextHandle context; /** The window the session was started in. Stored to be able to follow its view-layer. This may * be an invalid reference, i.e. the window may have been closed. */ wmWindow *session_root_win; /** Off-screen area used for XR events. */ struct ScrArea *area; /** Although this struct is internal, RNA gets a handle to this for state information queries. */ wmXrSessionState session_state; wmXrSessionExitFn exit_fn; ListBase actionmaps; /* #XrActionMap */ short actactionmap; short selactionmap; } wmXrRuntimeData; typedef struct wmXrViewportPair { struct wmXrViewportPair *next, *prev; struct GPUOffScreen *offscreen; struct GPUViewport *viewport; } wmXrViewportPair; typedef struct { /** Off-screen buffers/viewports for each view. */ ListBase viewports; /* #wmXrViewportPair */ /** Dummy region type for controller draw callback. */ struct ARegionType *controller_art; /** Controller draw callback handle. */ void *controller_draw_handle; } wmXrSurfaceData; typedef struct wmXrDrawData { struct Scene *scene; struct Depsgraph *depsgraph; wmXrData *xr_data; wmXrSurfaceData *surface_data; /** The pose (location + rotation) to which eye deltas will be applied to when drawing (world * space). With positional tracking enabled, it should be the same as the base pose, when * disabled it also contains a location delta from the moment the option was toggled. */ GHOST_XrPose base_pose; /** Base scale (uniform, world space). */ float base_scale; /** Offset to _substract_ from the OpenXR eye and viewer pose to get the wanted effective pose * (e.g. a pose exactly at the landmark position). */ float eye_position_ofs[3]; /* Local/view space. */ } wmXrDrawData; typedef struct wmXrController { struct wmXrController *next, *prev; /** OpenXR user path identifier. */ char subaction_path[64]; /* XR_MAX_USER_PATH_LENGTH */ /** Pose (in world space) that represents the user's hand when holding the controller. */ GHOST_XrPose grip_pose; float grip_mat[4][4]; float grip_mat_base[4][4]; /** Pose (in world space) that represents the controller's aiming source. */ GHOST_XrPose aim_pose; float aim_mat[4][4]; float aim_mat_base[4][4]; /** Controller model. */ struct GPUBatch *model; } wmXrController; typedef struct wmXrAction { char *name; eXrActionType type; unsigned int count_subaction_paths; char **subaction_paths; /** States for each subaction path. */ void *states; /** Previous states, stored to determine XR events. */ void *states_prev; /** Input thresholds/regions for each subaction path. */ float *float_thresholds; eXrAxisFlag *axis_flags; /** The currently active subaction path (if any) for modal actions. */ const char *active_modal_path; /** Operator to be called on XR events. */ struct wmOperatorType *ot; IDProperty *op_properties; /** Haptics. */ char *haptic_name; int64_t haptic_duration; float haptic_frequency; float haptic_amplitude; /** Flags. */ eXrOpFlag op_flag; eXrActionFlag action_flag; eXrHapticFlag haptic_flag; } wmXrAction; typedef struct wmXrHapticAction { struct wmXrHapticAction *next, *prev; wmXrAction *action; const char *subaction_path; int64_t time_start; } wmXrHapticAction; typedef struct wmXrActionSet { char *name; /** XR pose actions that determine the controller grip/aim transforms. */ wmXrAction *controller_grip_action; wmXrAction *controller_aim_action; /** Currently active modal actions. */ ListBase active_modal_actions; /** Currently active haptic actions. */ ListBase active_haptic_actions; } wmXrActionSet; /* wm_xr.c */ wmXrRuntimeData *wm_xr_runtime_data_create(void); void wm_xr_runtime_data_free(wmXrRuntimeData **runtime); /* wm_xr_session.c */ void wm_xr_session_data_free(wmXrSessionState *state); wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm, const wmXrRuntimeData *runtime_data); void wm_xr_session_draw_data_update(wmXrSessionState *state, const XrSessionSettings *settings, const GHOST_XrDrawViewInfo *draw_view, wmXrDrawData *draw_data); /** * Update information that is only stored for external state queries. E.g. for Python API to * request the current (as in, last known) viewer pose. * Controller data and action sets will be updated separately via wm_xr_session_actions_update(). */ void wm_xr_session_state_update(const XrSessionSettings *settings, const wmXrDrawData *draw_data, const GHOST_XrDrawViewInfo *draw_view, wmXrSessionState *state); bool wm_xr_session_surface_offscreen_ensure(wmXrSurfaceData *surface_data, const GHOST_XrDrawViewInfo *draw_view); void *wm_xr_session_gpu_binding_context_create(void); void wm_xr_session_gpu_binding_context_destroy(GHOST_ContextHandle context); void wm_xr_session_actions_init(wmXrData *xr); void wm_xr_session_actions_update(wmWindowManager *wm); void wm_xr_session_controller_data_populate(const wmXrAction *grip_action, const wmXrAction *aim_action, wmXrData *xr); void wm_xr_session_controller_data_clear(wmXrSessionState *state); /* wm_xr_draw.c */ void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]); void wm_xr_pose_scale_to_mat(const GHOST_XrPose *pose, float scale, float r_mat[4][4]); void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4]); void wm_xr_pose_scale_to_imat(const GHOST_XrPose *pose, float scale, float r_imat[4][4]); /** * \brief Draw a viewport for a single eye. * * This is the main viewport drawing function for VR sessions. It's assigned to Ghost-XR as a * callback (see GHOST_XrDrawViewFunc()) and executed for each view (read: eye). */ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata); void wm_xr_draw_controllers(const struct bContext *C, struct ARegion *region, void *customdata);