70 wmXrActionData *actiondata =
static_cast<wmXrActionData *
>(
event->customdata);
71 return (actiondata->ot == op->
type &&
88 screen =
static_cast<bScreen *
>(screen->id.next))
96 ED_view3d_xr_mirror_update(area, v3d, session_exists);
103 ED_view3d_xr_shading_update(wm, v3d, scene);
148 ot->name =
"Toggle VR Session";
149 ot->idname =
"WM_OT_xr_session_toggle";
151 "Open a view for use with virtual reality headsets, or close it if already "
197 if (actiondata->bimanual) {
199 copy_v3_v3(
data->mat_other_prev[3], actiondata->controller_loc_other);
200 data->bimanual_prev =
true;
203 data->bimanual_prev =
false;
209 const float scale =
len_v3(
R[0]);
210 float x_axis[3], y_axis[3];
224 const float nav_inv[4][4],
232 float prev_base[4][4], curr_base[4][4];
238 const float z_axis[3] = {0.0f, 0.0f, 1.0f};
246 else if (locz_lock) {
247 curr_base[3][2] = prev_base[3][2];
265 const float nav_mat[4][4],
266 const float nav_inv[4][4],
270 const bool nav_lock = (nav_mat && nav_inv);
271 float prev[4][4], curr[4][4];
273 if (!
data->rot_lock) {
283 if (!
data->loc_lock || nav_lock) {
285 copy_v3_v3(curr[3], actiondata->controller_loc);
290 nav_mat, nav_inv,
data->loc_lock,
data->locz_lock,
data->rotz_lock, prev, curr);
317 const float nav_mat[4][4],
318 const float nav_inv[4][4],
322 const bool nav_lock = (nav_mat && nav_inv);
323 float prev[4][4], curr[4][4];
327 if (!
data->rot_lock) {
329 float x_axis_prev[3], x_axis_curr[3], y_axis_prev[3], y_axis_curr[3], z_axis_prev[3],
331 float m0[3][3], m1[3][3];
337 sub_v3_v3v3(x_axis_curr, actiondata->controller_loc, actiondata->controller_loc_other);
358 if (!
data->loc_lock || nav_lock) {
362 add_v3_v3v3(curr[3], actiondata->controller_loc, actiondata->controller_loc_other);
366 if (!
data->scale_lock) {
376 sub_v3_v3v3(
v, actiondata->controller_loc, actiondata->controller_loc_other);
385 nav_mat, nav_inv,
data->loc_lock,
data->locz_lock,
data->rotz_lock, prev, curr);
414 const wmXrActionData *actiondata =
static_cast<const wmXrActionData *
>(
event->customdata);
437 return (actiondata->bimanual &&
data->bimanual_prev);
443 return (!actiondata->bimanual &&
data->bimanual_prev);
449 return data->loc_lock &&
data->rot_lock &&
data->scale_lock;
452 return data->loc_lock &&
data->rot_lock;
456 const wmXrActionData *actiondata,
460 GHOST_XrPose nav_pose;
462 float nav_mat[4][4], nav_inv[4][4], delta[4][4],
out[4][4];
464 const bool need_navinv = (
data->loc_lock ||
data->locz_lock ||
data->rotz_lock);
478 need_navinv ? nav_mat :
nullptr,
479 need_navinv ? nav_inv :
nullptr,
486 need_navinv ? nav_mat :
nullptr,
487 need_navinv ? nav_inv :
nullptr,
500 if (!
data->rot_lock) {
505 if (!
data->scale_lock && bimanual) {
514 if (actiondata->bimanual) {
515 if (!
data->bimanual_prev) {
519 copy_v3_v3(
data->mat_other_prev[3], actiondata->controller_loc_other);
521 data->bimanual_prev =
true;
524 if (
data->bimanual_prev) {
528 data->bimanual_prev =
false;
540 const wmXrActionData *actiondata =
static_cast<const wmXrActionData *
>(
event->customdata);
568 switch (event->
val) {
584 ot->name =
"XR Navigation Grab";
585 ot->idname =
"WM_OT_xr_navigation_grab";
586 ot->description =
"Navigate the VR scene by grabbing with controllers";
596 ot->srna,
"lock_location",
false,
"Lock Location",
"Prevent changes to viewer location");
598 ot->srna,
"lock_location_z",
false,
"Lock Elevation",
"Prevent changes to viewer elevation");
600 ot->srna,
"lock_rotation",
false,
"Lock Rotation",
"Prevent changes to viewer rotation");
604 "Lock Up Orientation",
605 "Prevent changes to viewer up orientation");
606 RNA_def_boolean(
ot->srna,
"lock_scale",
false,
"Lock Scale",
"Prevent changes to viewer scale");
634 if (
data->from_viewer) {
711 const wmXrActionData *actiondata)
714 float ray_length, axis[3];
720 if (
data->from_viewer) {
729 mul_qt_v3(actiondata->controller_rot, axis);
739 const float origin[3],
740 const float direction[3],
742 bool selectable_only,
781#define XR_DEFAULT_FLY_SPEED_MOVE 0.054f
824 const float ref_quat[4],
825 const float nav_mat[4][4],
829 float ref_axes[3][3];
877 float z_axis[3], projected[3];
891 const float viewer_mat[4][4],
892 const float nav_mat[4][4],
893 const float nav_inv[4][4],
898 float z_axis[3], m[3][3], prev[4][4], curr[4][4];
916 const float nav_rotation[4],
920 float base_eul[3], base_quatz[4];
961 const wmXrActionData *actiondata =
static_cast<const wmXrActionData *
>(
event->customdata);
966 bool turn, locz_lock, dir_lock, speed_frame_based;
967 bool speed_interp_cubic =
false;
968 float speed, speed_max, speed_p0[2], speed_p1[2];
969 GHOST_XrPose nav_pose;
970 float nav_mat[4][4], delta[4][4],
out[4][4];
986 speed_interp_cubic =
true;
989 speed_p0[0] = speed_p0[1] = 0.0f;
995 speed_interp_cubic =
true;
998 speed_p1[0] = speed_p1[1] = 1.0f;
1002 if (speed_max < speed) {
1007 switch (actiondata->type) {
1014 len_v2(actiondata->state);
1015 float speed_t = (actiondata->float_threshold < 1.0f) ?
1016 (
state - actiondata->float_threshold) /
1017 (1.0f - actiondata->float_threshold) :
1019 if (speed_interp_cubic) {
1020 float start[2], end[2], p[2];
1024 speed_p0[1] = speed + speed_p0[1] * (speed_max - speed);
1025 speed_p1[1] = speed + speed_p1[1] * (speed_max - speed);
1033 speed += speed_t * (speed_max - speed);
1043 if (!speed_frame_based) {
1045 speed *= time_now -
data->time_prev;
1047 data->time_prev = time_now;
1058 GHOST_XrPose viewer_pose;
1059 float viewer_mat[4][4], nav_inv[4][4];
1070 float nav_scale, ref_quat[4];
1100 copy_qt_qt(ref_quat, actiondata->controller_rot);
1135 ot->name =
"XR Navigation Fly";
1136 ot->idname =
"WM_OT_xr_navigation_fly";
1137 ot->description =
"Move/turn relative to the VR viewer or controller";
1147 {
XR_FLY_FORWARD,
"FORWARD", 0,
"Forward",
"Move along navigation forward axis"},
1148 {
XR_FLY_BACK,
"BACK", 0,
"Back",
"Move along navigation back axis"},
1149 {
XR_FLY_LEFT,
"LEFT", 0,
"Left",
"Move along navigation left axis"},
1150 {
XR_FLY_RIGHT,
"RIGHT", 0,
"Right",
"Move along navigation right axis"},
1151 {
XR_FLY_UP,
"UP", 0,
"Up",
"Move along navigation up axis"},
1152 {
XR_FLY_DOWN,
"DOWN", 0,
"Down",
"Move along navigation down axis"},
1157 "Turn counter-clockwise around navigation up axis"},
1158 {
XR_FLY_TURNRIGHT,
"TURNRIGHT", 0,
"Turn Right",
"Turn clockwise around navigation up axis"},
1163 "Move along viewer's forward axis"},
1164 {
XR_FLY_VIEWER_BACK,
"VIEWER_BACK", 0,
"Viewer Back",
"Move along viewer's back axis"},
1165 {
XR_FLY_VIEWER_LEFT,
"VIEWER_LEFT", 0,
"Viewer Left",
"Move along viewer's left axis"},
1166 {
XR_FLY_VIEWER_RIGHT,
"VIEWER_RIGHT", 0,
"Viewer Right",
"Move along viewer's right axis"},
1168 "CONTROLLER_FORWARD",
1170 "Controller Forward",
1171 "Move along controller's forward axis"},
1172 {0,
nullptr, 0,
nullptr,
nullptr},
1175 static const float default_speed_p0[2] = {0.0f, 0.0f};
1176 static const float default_speed_p1[2] = {1.0f, 1.0f};
1182 ot->srna,
"lock_location_z",
false,
"Lock Elevation",
"Prevent changes to viewer elevation");
1187 "Limit movement to viewer's initial direction");
1189 "speed_frame_based",
1191 "Frame Based Speed",
1192 "Apply fixed movement deltas every update");
1199 "Minimum move (turn) speed in meters (radians) per second or frame",
1208 "Maximum move (turn) speed in meters (radians) per second or frame",
1212 "speed_interpolation0",
1217 "Speed Interpolation 0",
1218 "First cubic spline control point between min/max speeds",
1222 "speed_interpolation1",
1227 "Speed Interpolation 1",
1228 "Second cubic spline control point between min/max speeds",
1243 const float origin[3],
1244 const float direction[3],
1246 bool selectable_only,
1247 const bool teleport_axes[3],
1256 const Object *ob =
nullptr;
1273 float nav_location[3], nav_rotation[4], viewer_location[3];
1274 float nav_axes[3][3], projected[3], v0[3], v1[3];
1275 float out[3] = {0.0f, 0.0f, 0.0f};
1285 for (
int a = 0; a < 3; ++a) {
1287 if (teleport_axes[a]) {
1338 const wmXrActionData *actiondata =
static_cast<const wmXrActionData *
>(
event->customdata);
1344 switch (event->
val) {
1349 bool selectable_only, teleport_axes[3];
1350 float teleport_t, teleport_ofs, ray_dist;
1383 ot->name =
"XR Navigation Teleport";
1384 ot->idname =
"WM_OT_xr_navigation_teleport";
1385 ot->description =
"Set VR viewer location to controller raycast hit location";
1394 static const bool default_teleport_axes[3] = {
true,
true,
true};
1399 default_teleport_axes,
1401 "Enabled teleport axes in navigation space");
1408 "Interpolation factor between viewer and hit locations",
1417 "Offset along hit normal to subtract from final location",
1424 "Only allow selectable objects to influence raycast result");
1431 "Maximum raycast distance",
1435 ot->srna,
"from_viewer",
false,
"From Viewer",
"Use viewer pose as raycast origin");
1443 "Raycast axis in controller/viewer space",
1470 bool reset_loc, reset_rot, reset_scale;
1479 float nav_rotation[4], nav_scale;
1504 float nav_location[3], nav_rotation[4], nav_scale;
1505 float nav_axes[3][3],
v[3];
1533 ot->name =
"XR Navigation Reset";
1534 ot->idname =
"WM_OT_xr_navigation_reset";
1535 ot->description =
"Reset VR navigation deltas relative to session base pose";
1542 RNA_def_boolean(
ot->srna,
"location",
true,
"Location",
"Reset location deltas");
1543 RNA_def_boolean(
ot->srna,
"rotation",
true,
"Rotation",
"Reset rotation deltas");
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
bool IDP_EqualsProperties(const IDProperty *prop1, const IDProperty *prop2) ATTR_WARN_UNUSED_RESULT
SpaceType * BKE_spacetype_from_id(int spaceid)
ARegionType * BKE_regiontype_from_id(const SpaceType *st, int regionid)
#define BLI_assert_unreachable()
#define BVH_RAYCAST_DIST_MAX
#define LISTBASE_FOREACH(type, var, list)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4(float mat[4][4])
void unit_m4(float m[4][4])
void quat_to_mat3(float m[3][3], const float q[4])
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
void axis_angle_to_quat_single(float q[4], char axis, float angle)
float normalize_qt(float q[4])
void quat_to_mat4(float m[4][4], const float q[4])
void mul_qt_v3(const float q[4], float r[3])
void quat_to_eul(float eul[3], const float quat[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
void mat4_to_quat(float q[4], const float mat[4][4])
void copy_qt_qt(float q[4], const float a[4])
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3(float r[3], const float a[3])
void interp_v2_v2v2v2v2_cubic(float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2], float u)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
void project_v3_v3v3_normalized(float out[3], const float p[3], const float v_proj[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Platform independent time functions.
double BLI_time_now_seconds(void)
#define BLT_I18NCONTEXT_NAVIGATION
@ SCE_SNAP_TARGET_ONLY_SELECTABLE
@ V3D_RUNTIME_XR_SESSION_ROOT
#define OPERATOR_RETVAL_CHECK(ret)
bool ED_operator_view3d_active(bContext *C)
void * ED_region_draw_cb_activate(ARegionType *art, void(*draw)(const bContext *, ARegion *, void *), void *customdata, int type)
#define REGION_DRAW_POST_VIEW
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_3D_POLYLINE_FLAT_COLOR
void GPU_point_size(float size)
void GPU_depth_test(eGPUDepthTest test)
void GPU_viewport_size_get_f(float coords[4])
Read Guarded memory(de)allocation.
#define ND_XR_DATA_CHANGED
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
void * MEM_callocN(size_t len, const char *str)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
void RNA_boolean_get_array(PointerRNA *ptr, const char *name, bool *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const bool *default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
float mat_other_prev[4][4]
wmOperatorStatus(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
struct wmOperatorType * type
XrSessionSettings session_settings
struct wmXrRuntimeData * runtime
wmXrSessionState session_state
GHOST_XrPose prev_base_pose
void WM_main_add_notifier(uint type, void *reference)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
Scene * WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen *screen)
bool wm_xr_init(wmWindowManager *wm)
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_scale_to_imat(const GHOST_XrPose *pose, float scale, float r_imat[4][4])
void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4])
static void orient_mat_z_normalized(float R[4][4], const float z_axis[3])
static void wm_xr_grab_init(wmOperator *op)
static void wm_xr_navigation_teleport(bContext *C, wmXrData *xr, const float origin[3], const float direction[3], float *ray_dist, bool selectable_only, const bool teleport_axes[3], float teleport_t, float teleport_ofs)
static void wm_xr_fly_init(wmOperator *op, const wmXrData *xr)
static void wm_xr_navigation_grab_bimanual_state_update(const wmXrActionData *actiondata, XrGrabData *data)
static void wm_xr_basenav_rotation_calc(const wmXrData *xr, const float nav_rotation[4], float r_rotation[4])
static wmOperatorStatus wm_xr_navigation_reset_exec(bContext *C, wmOperator *op)
static void wm_xr_grab_uninit(wmOperator *op)
static void WM_OT_xr_navigation_fly(wmOperatorType *ot)
static wmOperatorStatus wm_xr_navigation_teleport_exec(bContext *, wmOperator *)
static void wm_xr_navigation_grab_apply(wmXrData *xr, const wmXrActionData *actiondata, const XrGrabData *data, bool bimanual)
static void wm_xr_navlocks_apply(const float nav_mat[4][4], const float nav_inv[4][4], bool loc_lock, bool locz_lock, bool rotz_lock, float r_prev[4][4], float r_curr[4][4])
static bool wm_xr_navigation_grab_is_bimanual_ending(const wmXrActionData *actiondata, const XrGrabData *data)
static wmOperatorStatus wm_xr_navigation_fly_exec(bContext *, wmOperator *)
static void wm_xr_grab_compute_bimanual(const wmXrActionData *actiondata, const XrGrabData *data, const float nav_mat[4][4], const float nav_inv[4][4], bool reverse, float r_delta[4][4])
static void wm_xr_fly_uninit(wmOperator *op)
static bool wm_xr_operator_sessionactive(bContext *C)
#define XR_DEFAULT_FLY_SPEED_MOVE
static void wm_xr_raycast_uninit(wmOperator *op)
static wmOperatorStatus wm_xr_navigation_fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
void wm_xr_operatortypes_register()
static void wm_xr_raycast_update(wmOperator *op, const wmXrData *xr, const wmXrActionData *actiondata)
static bool wm_xr_navigation_grab_is_locked(const XrGrabData *data, const bool bimanual)
static void wm_xr_session_update_screen_on_exit_cb(const wmXrData *xr_data)
static wmOperatorStatus wm_xr_session_toggle_exec(bContext *C, wmOperator *)
static void wm_xr_session_update_screen(Main *bmain, const wmXrData *xr_data)
static bool wm_xr_operator_test_event(const wmOperator *op, const wmEvent *event)
static bool wm_xr_navigation_grab_can_do_bimanual(const wmXrActionData *actiondata, const XrGrabData *data)
static void WM_OT_xr_navigation_teleport(wmOperatorType *ot)
static void wm_xr_grab_update(wmOperator *op, const wmXrActionData *actiondata)
static void wm_xr_raycast(Scene *scene, Depsgraph *depsgraph, const float origin[3], const float direction[3], float *ray_dist, bool selectable_only, float r_location[3], float r_normal[3], int *r_index, const Object **r_ob, float r_obmat[4][4])
static const float g_xr_default_raycast_color[4]
static wmOperatorStatus wm_xr_navigation_grab_modal(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus wm_xr_navigation_teleport_modal(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus wm_xr_navigation_fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void WM_OT_xr_navigation_reset(wmOperatorType *ot)
static wmOperatorStatus wm_xr_navigation_teleport_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static const float g_xr_default_raycast_axis[3]
static wmOperatorStatus wm_xr_navigation_grab_exec(bContext *, wmOperator *)
static void WM_OT_xr_navigation_grab(wmOperatorType *ot)
@ XR_FLY_CONTROLLER_FORWARD
static void wm_xr_raycast_init(wmOperator *op)
static void wm_xr_raycast_draw(const bContext *, ARegion *, void *customdata)
static void wm_xr_grab_compute(const wmXrActionData *actiondata, const XrGrabData *data, const float nav_mat[4][4], const float nav_inv[4][4], bool reverse, float r_delta[4][4])
static void wm_xr_fly_compute_move(eXrFlyMode mode, float speed, const float ref_quat[4], const float nav_mat[4][4], bool locz_lock, float r_delta[4][4])
static void WM_OT_xr_session_toggle(wmOperatorType *ot)
static wmOperatorStatus wm_xr_navigation_grab_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void wm_xr_fly_compute_turn(eXrFlyMode mode, float speed, const float viewer_mat[4][4], const float nav_mat[4][4], const float nav_inv[4][4], float r_delta[4][4])
void WM_xr_session_state_nav_scale_set(wmXrData *xr, float scale)
bool WM_xr_session_state_nav_scale_get(const wmXrData *xr, float *r_scale)
void wm_xr_session_toggle(wmWindowManager *wm, wmWindow *session_root_win, wmXrSessionExitFn session_exit_fn)
bool WM_xr_session_state_nav_location_get(const wmXrData *xr, float r_location[3])
void WM_xr_session_state_nav_location_set(wmXrData *xr, const float location[3])
bool WM_xr_session_is_ready(const wmXrData *xr)
bool WM_xr_session_state_viewer_pose_location_get(const wmXrData *xr, float r_location[3])
bool WM_xr_session_exists(const wmXrData *xr)
void WM_xr_session_state_nav_rotation_set(wmXrData *xr, const float rotation[4])
bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_rotation[4])
bool WM_xr_session_state_nav_rotation_get(const wmXrData *xr, float r_rotation[4])