Blender  V3.3
wm_xr_session.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BKE_callbacks.h"
8 #include "BKE_context.h"
9 #include "BKE_global.h"
10 #include "BKE_idprop.h"
11 #include "BKE_main.h"
12 #include "BKE_scene.h"
13 #include "BKE_screen.h"
14 
15 #include "BLI_listbase.h"
16 #include "BLI_math.h"
17 
18 #include "DEG_depsgraph.h"
19 #include "DEG_depsgraph_query.h"
20 
21 #include "DNA_camera_types.h"
22 #include "DNA_space_types.h"
23 
24 #include "DRW_engine.h"
25 
26 #include "ED_screen.h"
27 #include "ED_space_api.h"
28 
29 #include "GHOST_C-api.h"
30 
31 #include "GPU_batch.h"
32 #include "GPU_viewport.h"
33 
34 #include "MEM_guardedalloc.h"
35 
36 #include "PIL_time.h"
37 
38 #include "WM_api.h"
39 #include "WM_types.h"
40 
41 #include "wm_event_system.h"
42 #include "wm_surface.h"
43 #include "wm_window.h"
44 #include "wm_xr_intern.h"
45 
47 static CLG_LogRef LOG = {"wm.xr"};
48 
49 /* -------------------------------------------------------------------- */
50 
51 static void wm_xr_session_create_cb(void)
52 {
53  Main *bmain = G_MAIN;
54  wmWindowManager *wm = bmain->wm.first;
55  wmXrData *xr_data = &wm->xr;
57  XrSessionSettings *settings = &xr_data->session_settings;
58 
59  /* Get action set data from Python. */
61 
63 
64  /* Initialize navigation. */
66  if (settings->base_scale < FLT_EPSILON) {
67  settings->base_scale = 1.0f;
68  }
69  state->prev_base_scale = settings->base_scale;
70 }
71 
73 {
74  ListBase *lb = &state->controllers;
76 
77  while ((c = BLI_pophead(lb))) {
78  if (c->model) {
79  GPU_batch_discard(c->model);
80  }
81  BLI_freelinkN(lb, c);
82  }
83 }
84 
86 {
88 }
89 
90 static void wm_xr_session_exit_cb(void *customdata)
91 {
92  wmXrData *xr_data = customdata;
93  if (!xr_data->runtime) {
94  return;
95  }
96 
97  xr_data->runtime->session_state.is_started = false;
98 
99  if (xr_data->runtime->exit_fn) {
100  xr_data->runtime->exit_fn(xr_data);
101  }
102 
103  /* Free the entire runtime data (including session state and context), to play safe. */
104  wm_xr_runtime_data_free(&xr_data->runtime);
105 }
106 
108  GHOST_XrSessionBeginInfo *r_begin_info)
109 {
110  /* Callback for when the session is created. This is needed to create and bind OpenXR actions
111  * after the session is created but before it is started. */
112  r_begin_info->create_fn = wm_xr_session_create_cb;
113 
114  /* WM-XR exit function, does some own stuff and calls callback passed to wm_xr_session_toggle(),
115  * to allow external code to execute its own session-exit logic. */
116  r_begin_info->exit_fn = wm_xr_session_exit_cb;
117  r_begin_info->exit_customdata = xr_data;
118 }
119 
121  wmWindow *session_root_win,
122  wmXrSessionExitFn session_exit_fn)
123 {
124  wmXrData *xr_data = &wm->xr;
125 
126  if (WM_xr_session_exists(xr_data)) {
127  /* Must set first, since #GHOST_XrSessionEnd() may immediately free the runtime. */
128  xr_data->runtime->session_state.is_started = false;
129 
130  GHOST_XrSessionEnd(xr_data->runtime->context);
131  }
132  else {
133  GHOST_XrSessionBeginInfo begin_info;
134 
135  xr_data->runtime->session_root_win = session_root_win;
136  xr_data->runtime->session_state.is_started = true;
137  xr_data->runtime->exit_fn = session_exit_fn;
138 
139  wm_xr_session_begin_info_create(xr_data, &begin_info);
140  GHOST_XrSessionStart(xr_data->runtime->context, &begin_info);
141  }
142 }
143 
145 {
146  return xr->runtime && xr->runtime->context && xr->runtime->session_state.is_started;
147 }
148 
150 {
152 }
153 
155 {
156  return WM_xr_session_exists(xr) && GHOST_XrSessionIsRunning(xr->runtime->context);
157 }
158 
160  const XrSessionSettings *settings,
161  GHOST_XrPose *r_base_pose,
162  float *r_base_scale)
163 {
164  const Object *base_pose_object = ((settings->base_pose_type == XR_BASE_POSE_OBJECT) &&
165  settings->base_pose_object) ?
166  settings->base_pose_object :
167  scene->camera;
168 
169  if (settings->base_pose_type == XR_BASE_POSE_CUSTOM) {
170  float tmp_quatx[4], tmp_quatz[4];
171 
172  copy_v3_v3(r_base_pose->position, settings->base_pose_location);
173  axis_angle_to_quat_single(tmp_quatx, 'X', M_PI_2);
174  axis_angle_to_quat_single(tmp_quatz, 'Z', settings->base_pose_angle);
175  mul_qt_qtqt(r_base_pose->orientation_quat, tmp_quatz, tmp_quatx);
176  }
177  else if (base_pose_object) {
178  float tmp_quat[4];
179  float tmp_eul[3];
180 
181  mat4_to_loc_quat(r_base_pose->position, tmp_quat, base_pose_object->obmat);
182 
183  /* Only use rotation around Z-axis to align view with floor. */
184  quat_to_eul(tmp_eul, tmp_quat);
185  tmp_eul[0] = M_PI_2;
186  tmp_eul[1] = 0;
187  eul_to_quat(r_base_pose->orientation_quat, tmp_eul);
188  }
189  else {
190  copy_v3_fl(r_base_pose->position, 0.0f);
191  axis_angle_to_quat_single(r_base_pose->orientation_quat, 'X', M_PI_2);
192  }
193 
194  *r_base_scale = settings->base_scale;
195 }
196 
198  Scene *scene,
200  wmXrDrawData *r_draw_data)
201 {
202  const XrSessionSettings *settings = &xr_data->session_settings;
203 
204  memset(r_draw_data, 0, sizeof(*r_draw_data));
205  r_draw_data->scene = scene;
206  r_draw_data->depsgraph = depsgraph;
207  r_draw_data->xr_data = xr_data;
208  r_draw_data->surface_data = g_xr_surface->customdata;
209 
211  r_draw_data->scene, settings, &r_draw_data->base_pose, &r_draw_data->base_scale);
212 }
213 
215  const wmXrRuntimeData *runtime_data)
216 {
217  if (runtime_data->session_root_win &&
218  BLI_findindex(&wm->windows, runtime_data->session_root_win) != -1) {
219  /* Root window is still valid, use it. */
220  return runtime_data->session_root_win;
221  }
222  /* Otherwise, fallback. */
223  return wm->windows.first;
224 }
225 
234  Scene **r_scene,
235  Depsgraph **r_depsgraph)
236 {
238 
239  /* Follow the scene & view layer shown in the root 3D View. */
241  ViewLayer *view_layer = WM_window_get_active_view_layer(root_win);
242 
244  BLI_assert(scene && view_layer && depsgraph);
245  *r_scene = scene;
246  *r_depsgraph = depsgraph;
247 }
248 
249 typedef enum wmXrSessionStateEvent {
255 
257  const XrSessionSettings *settings)
258 {
259  if (state->force_reset_to_base_pose) {
260  return true;
261  }
262  return ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) &&
263  ((state->prev_base_pose_type != settings->base_pose_type) ||
264  (state->prev_base_pose_object != settings->base_pose_object));
265 }
266 
268  const XrSessionSettings *settings)
269 {
270  if (!state->is_view_data_set) {
272  }
275  }
276 
277  const bool position_tracking_toggled = ((state->prev_settings_flag &
279  (settings->flag & XR_SESSION_USE_POSITION_TRACKING));
280  if (position_tracking_toggled) {
282  }
283 
285 }
286 
288  const XrSessionSettings *settings,
289  const GHOST_XrDrawViewInfo *draw_view,
290  wmXrDrawData *draw_data)
291 {
293  const bool use_position_tracking = (settings->flag & XR_SESSION_USE_POSITION_TRACKING);
294 
295  switch (event) {
297  if (use_position_tracking) {
298  /* We want to start the session exactly at landmark position.
299  * Run-times may have a non-[0,0,0] starting position that we have to subtract for that. */
300  copy_v3_v3(draw_data->eye_position_ofs, draw_view->local_pose.position);
301  }
302  else {
303  copy_v3_fl(draw_data->eye_position_ofs, 0.0f);
304  }
305  break;
306  /* This should be triggered by the VR add-on if a landmark changes. */
308  if (use_position_tracking) {
309  /* Switch exactly to base pose, so use eye offset to cancel out current position delta. */
310  copy_v3_v3(draw_data->eye_position_ofs, draw_view->local_pose.position);
311  }
312  else {
313  copy_v3_fl(draw_data->eye_position_ofs, 0.0f);
314  }
315  /* Reset navigation. */
317  break;
319  if (use_position_tracking) {
320  /* Keep the current position, and let the user move from there. */
321  copy_v3_v3(draw_data->eye_position_ofs, state->prev_eye_position_ofs);
322  }
323  else {
324  /* Back to the exact base-pose position. */
325  copy_v3_fl(draw_data->eye_position_ofs, 0.0f);
326  }
327  break;
329  /* Keep previous offset when positional tracking is disabled. */
330  copy_v3_v3(draw_data->eye_position_ofs, state->prev_eye_position_ofs);
331  break;
332  }
333 }
334 
336  const wmXrDrawData *draw_data,
337  const GHOST_XrDrawViewInfo *draw_view,
339 {
340  GHOST_XrPose viewer_pose;
341  float viewer_mat[4][4], base_mat[4][4], nav_mat[4][4];
342 
343  /* Calculate viewer matrix. */
344  copy_qt_qt(viewer_pose.orientation_quat, draw_view->local_pose.orientation_quat);
345  if ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) {
346  zero_v3(viewer_pose.position);
347  }
348  else {
349  copy_v3_v3(viewer_pose.position, draw_view->local_pose.position);
350  }
351  if ((settings->flag & XR_SESSION_USE_ABSOLUTE_TRACKING) == 0) {
352  sub_v3_v3(viewer_pose.position, draw_data->eye_position_ofs);
353  }
354  wm_xr_pose_to_mat(&viewer_pose, viewer_mat);
355 
356  /* Apply base pose and navigation. */
357  wm_xr_pose_scale_to_mat(&draw_data->base_pose, draw_data->base_scale, base_mat);
358  wm_xr_pose_scale_to_mat(&state->nav_pose_prev, state->nav_scale_prev, nav_mat);
359  mul_m4_m4m4(state->viewer_mat_base, base_mat, viewer_mat);
360  mul_m4_m4m4(viewer_mat, nav_mat, state->viewer_mat_base);
361 
362  /* Save final viewer pose and viewmat. */
363  mat4_to_loc_quat(state->viewer_pose.position, state->viewer_pose.orientation_quat, viewer_mat);
365  &state->viewer_pose, draw_data->base_scale * state->nav_scale_prev, state->viewer_viewmat);
366 
367  /* No idea why, but multiplying by two seems to make it match the VR view more. */
368  state->focal_len = 2.0f *
369  fov_to_focallength(draw_view->fov.angle_right - draw_view->fov.angle_left,
371 
372  copy_v3_v3(state->prev_eye_position_ofs, draw_data->eye_position_ofs);
373  memcpy(&state->prev_base_pose, &draw_data->base_pose, sizeof(state->prev_base_pose));
374  state->prev_base_scale = draw_data->base_scale;
375  memcpy(&state->prev_local_pose, &draw_view->local_pose, sizeof(state->prev_local_pose));
376  copy_v3_v3(state->prev_eye_position_ofs, draw_data->eye_position_ofs);
377 
378  state->prev_settings_flag = settings->flag;
379  state->prev_base_pose_type = settings->base_pose_type;
380  state->prev_base_pose_object = settings->base_pose_object;
381  state->is_view_data_set = true;
382  /* Assume this was already done through wm_xr_session_draw_data_update(). */
383  state->force_reset_to_base_pose = false;
384 }
385 
387 {
388  return xr->runtime ? &xr->runtime->session_state : NULL;
389 }
390 
392 {
393  return xr->runtime ? xr->runtime->area : NULL;
394 }
395 
396 bool WM_xr_session_state_viewer_pose_location_get(const wmXrData *xr, float r_location[3])
397 {
399  zero_v3(r_location);
400  return false;
401  }
402 
403  copy_v3_v3(r_location, xr->runtime->session_state.viewer_pose.position);
404  return true;
405 }
406 
407 bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_rotation[4])
408 {
410  unit_qt(r_rotation);
411  return false;
412  }
413 
414  copy_v4_v4(r_rotation, xr->runtime->session_state.viewer_pose.orientation_quat);
415  return true;
416 }
417 
419  float r_viewmat[4][4],
420  float *r_focal_len)
421 {
423  unit_m4(r_viewmat);
424  *r_focal_len = 0.0f;
425  return false;
426  }
427 
429  *r_focal_len = xr->runtime->session_state.focal_len;
430 
431  return true;
432 }
433 
435  unsigned int subaction_idx,
436  float r_location[3])
437 {
439  (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) {
440  zero_v3(r_location);
441  return false;
442  }
443 
445  subaction_idx);
447  copy_v3_v3(r_location, controller->grip_pose.position);
448  return true;
449 }
450 
452  unsigned int subaction_idx,
453  float r_rotation[4])
454 {
456  (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) {
457  unit_qt(r_rotation);
458  return false;
459  }
460 
462  subaction_idx);
464  copy_qt_qt(r_rotation, controller->grip_pose.orientation_quat);
465  return true;
466 }
467 
469  unsigned int subaction_idx,
470  float r_location[3])
471 {
473  (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) {
474  zero_v3(r_location);
475  return false;
476  }
477 
479  subaction_idx);
481  copy_v3_v3(r_location, controller->aim_pose.position);
482  return true;
483 }
484 
486  unsigned int subaction_idx,
487  float r_rotation[4])
488 {
490  (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) {
491  unit_qt(r_rotation);
492  return false;
493  }
494 
496  subaction_idx);
498  copy_qt_qt(r_rotation, controller->aim_pose.orientation_quat);
499  return true;
500 }
501 
502 bool WM_xr_session_state_nav_location_get(const wmXrData *xr, float r_location[3])
503 {
505  zero_v3(r_location);
506  return false;
507  }
508 
509  copy_v3_v3(r_location, xr->runtime->session_state.nav_pose.position);
510  return true;
511 }
512 
513 void WM_xr_session_state_nav_location_set(wmXrData *xr, const float location[3])
514 {
515  if (WM_xr_session_exists(xr)) {
516  copy_v3_v3(xr->runtime->session_state.nav_pose.position, location);
518  }
519 }
520 
521 bool WM_xr_session_state_nav_rotation_get(const wmXrData *xr, float r_rotation[4])
522 {
524  unit_qt(r_rotation);
525  return false;
526  }
527 
528  copy_qt_qt(r_rotation, xr->runtime->session_state.nav_pose.orientation_quat);
529  return true;
530 }
531 
532 void WM_xr_session_state_nav_rotation_set(wmXrData *xr, const float rotation[4])
533 {
534  if (WM_xr_session_exists(xr)) {
535  BLI_ASSERT_UNIT_QUAT(rotation);
536  copy_qt_qt(xr->runtime->session_state.nav_pose.orientation_quat, rotation);
538  }
539 }
540 
541 bool WM_xr_session_state_nav_scale_get(const wmXrData *xr, float *r_scale)
542 {
544  *r_scale = 1.0f;
545  return false;
546  }
547 
548  *r_scale = xr->runtime->session_state.nav_scale;
549  return true;
550 }
551 
553 {
554  if (WM_xr_session_exists(xr)) {
555  /* Clamp to reasonable values. */
557  xr->runtime->session_state.nav_scale = scale;
559  }
560 }
561 
563 {
564  zero_v3(state->nav_pose.position);
565  unit_qt(state->nav_pose.orientation_quat);
566  state->nav_scale = 1.0f;
567  state->is_navigation_dirty = true;
568 }
569 
570 /* -------------------------------------------------------------------- */
578 {
579  if (!xr->runtime) {
580  return;
581  }
582 
583  GHOST_XrAttachActionSets(xr->runtime->context);
584 }
585 
586 static void wm_xr_session_controller_pose_calc(const GHOST_XrPose *raw_pose,
587  const float view_ofs[3],
588  const float base_mat[4][4],
589  const float nav_mat[4][4],
590  GHOST_XrPose *r_pose,
591  float r_mat[4][4],
592  float r_mat_base[4][4])
593 {
594  float m[4][4];
595  /* Calculate controller matrix in world space. */
596  wm_xr_pose_to_mat(raw_pose, m);
597 
598  /* Apply eye position offset. */
599  sub_v3_v3(m[3], view_ofs);
600 
601  /* Apply base pose and navigation. */
602  mul_m4_m4m4(r_mat_base, base_mat, m);
603  mul_m4_m4m4(r_mat, nav_mat, r_mat_base);
604 
605  /* Save final pose. */
606  mat4_to_loc_quat(r_pose->position, r_pose->orientation_quat, r_mat);
607 }
608 
610  const wmXrAction *grip_action,
611  const wmXrAction *aim_action,
612  GHOST_XrContextHandle xr_context,
614 {
615  BLI_assert(grip_action->count_subaction_paths == aim_action->count_subaction_paths);
616  BLI_assert(grip_action->count_subaction_paths == BLI_listbase_count(&state->controllers));
617 
618  unsigned int subaction_idx = 0;
619  float view_ofs[3], base_mat[4][4], nav_mat[4][4];
620 
621  if ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) {
622  copy_v3_v3(view_ofs, state->prev_local_pose.position);
623  }
624  else {
625  zero_v3(view_ofs);
626  }
627  if ((settings->flag & XR_SESSION_USE_ABSOLUTE_TRACKING) == 0) {
628  add_v3_v3(view_ofs, state->prev_eye_position_ofs);
629  }
630 
631  wm_xr_pose_scale_to_mat(&state->prev_base_pose, state->prev_base_scale, base_mat);
632  wm_xr_pose_scale_to_mat(&state->nav_pose, state->nav_scale, nav_mat);
633 
634  LISTBASE_FOREACH_INDEX (wmXrController *, controller, &state->controllers, subaction_idx) {
635  wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)grip_action->states)[subaction_idx],
636  view_ofs,
637  base_mat,
638  nav_mat,
639  &controller->grip_pose,
640  controller->grip_mat,
641  controller->grip_mat_base);
642  wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)aim_action->states)[subaction_idx],
643  view_ofs,
644  base_mat,
645  nav_mat,
646  &controller->aim_pose,
647  controller->aim_mat,
648  controller->aim_mat_base);
649 
650  if (!controller->model) {
651  /* Notify GHOST to load/continue loading the controller model data. This can be called more
652  * than once since the model may not be available from the runtime yet. The batch itself will
653  * be created in wm_xr_draw_controllers(). */
654  GHOST_XrLoadControllerModel(xr_context, controller->subaction_path);
655  }
656  else {
657  GHOST_XrUpdateControllerModelComponents(xr_context, controller->subaction_path);
658  }
659  }
660 }
661 
663  const char *subaction_path)
664 {
666  &state->controllers, subaction_path, offsetof(wmXrController, subaction_path));
667  return controller ? &controller->aim_pose : NULL;
668 }
669 
670 BLI_INLINE bool test_float_state(const float *state, float threshold, eXrAxisFlag flag)
671 {
672  if ((flag & XR_AXIS0_POS) != 0) {
673  if (*state > threshold) {
674  return true;
675  }
676  }
677  else if ((flag & XR_AXIS0_NEG) != 0) {
678  if (*state < -threshold) {
679  return true;
680  }
681  }
682  else {
683  if (fabsf(*state) > threshold) {
684  return true;
685  }
686  }
687  return false;
688 }
689 
690 BLI_INLINE bool test_vec2f_state(const float state[2], float threshold, eXrAxisFlag flag)
691 {
692  if ((flag & XR_AXIS0_POS) != 0) {
693  if (state[0] < 0.0f) {
694  return false;
695  }
696  }
697  else if ((flag & XR_AXIS0_NEG) != 0) {
698  if (state[0] > 0.0f) {
699  return false;
700  }
701  }
702  if ((flag & XR_AXIS1_POS) != 0) {
703  if (state[1] < 0.0f) {
704  return false;
705  }
706  }
707  else if ((flag & XR_AXIS1_NEG) != 0) {
708  if (state[1] > 0.0f) {
709  return false;
710  }
711  }
712  return (len_v2(state) > threshold);
713 }
714 
715 static bool wm_xr_session_modal_action_test(const ListBase *active_modal_actions,
716  const wmXrAction *action,
717  bool *r_found)
718 {
719  if (r_found) {
720  *r_found = false;
721  }
722 
723  LISTBASE_FOREACH (LinkData *, ld, active_modal_actions) {
724  wmXrAction *active_modal_action = ld->data;
725  if (action == active_modal_action) {
726  if (r_found) {
727  *r_found = true;
728  }
729  return true;
730  }
731  if (action->ot == active_modal_action->ot &&
732  IDP_EqualsProperties(action->op_properties, active_modal_action->op_properties)) {
733  /* Don't allow duplicate modal operators since this can lead to unwanted modal handler
734  * behavior. */
735  return false;
736  }
737  }
738 
739  return true;
740 }
741 
742 static void wm_xr_session_modal_action_test_add(ListBase *active_modal_actions,
743  const wmXrAction *action)
744 {
745  bool found;
746  if (wm_xr_session_modal_action_test(active_modal_actions, action, &found) && !found) {
747  LinkData *ld = MEM_callocN(sizeof(LinkData), __func__);
748  ld->data = (void *)action;
749  BLI_addtail(active_modal_actions, ld);
750  }
751 }
752 
753 static void wm_xr_session_modal_action_remove(ListBase *active_modal_actions,
754  const wmXrAction *action)
755 {
756  LISTBASE_FOREACH (LinkData *, ld, active_modal_actions) {
757  if (action == ld->data) {
758  BLI_freelinkN(active_modal_actions, ld);
759  return;
760  }
761  }
762 }
763 
765  const wmXrAction *action,
766  const char *subaction_path)
767 {
768  LISTBASE_FOREACH (wmXrHapticAction *, ha, active_haptic_actions) {
769  if ((action == ha->action) && (subaction_path == ha->subaction_path)) {
770  return ha;
771  }
772  }
773  return NULL;
774 }
775 
776 static void wm_xr_session_haptic_action_add(ListBase *active_haptic_actions,
777  const wmXrAction *action,
778  const char *subaction_path,
779  int64_t time_now)
780 {
782  active_haptic_actions, action, subaction_path);
783  if (ha) {
784  /* Reset start time since OpenXR restarts haptics if they are already active. */
785  ha->time_start = time_now;
786  }
787  else {
788  ha = MEM_callocN(sizeof(wmXrHapticAction), __func__);
789  ha->action = (wmXrAction *)action;
790  ha->subaction_path = subaction_path;
791  ha->time_start = time_now;
792  BLI_addtail(active_haptic_actions, ha);
793  }
794 }
795 
796 static void wm_xr_session_haptic_action_remove(ListBase *active_haptic_actions,
797  const wmXrAction *action)
798 {
799  LISTBASE_FOREACH (wmXrHapticAction *, ha, active_haptic_actions) {
800  if (action == ha->action) {
801  BLI_freelinkN(active_haptic_actions, ha);
802  return;
803  }
804  }
805 }
806 
807 static void wm_xr_session_haptic_timers_check(ListBase *active_haptic_actions, int64_t time_now)
808 {
809  LISTBASE_FOREACH_MUTABLE (wmXrHapticAction *, ha, active_haptic_actions) {
810  if (time_now - ha->time_start >= ha->action->haptic_duration) {
811  BLI_freelinkN(active_haptic_actions, ha);
812  }
813  }
814 }
815 
817  const char *action_set_name,
818  wmXrAction *action,
819  unsigned int subaction_idx,
820  ListBase *active_modal_actions,
821  ListBase *active_haptic_actions,
822  int64_t time_now,
823  bool modal,
824  bool haptic,
825  short *r_val)
826 {
827  const char *haptic_subaction_path = ((action->haptic_flag & XR_HAPTIC_MATCHUSERPATHS) != 0) ?
828  action->subaction_paths[subaction_idx] :
829  NULL;
830  bool curr = false;
831  bool prev = false;
832 
833  switch (action->type) {
834  case XR_BOOLEAN_INPUT: {
835  const bool *state = &((bool *)action->states)[subaction_idx];
836  bool *state_prev = &((bool *)action->states_prev)[subaction_idx];
837  if (*state) {
838  curr = true;
839  }
840  if (*state_prev) {
841  prev = true;
842  }
843  *state_prev = *state;
844  break;
845  }
846  case XR_FLOAT_INPUT: {
847  const float *state = &((float *)action->states)[subaction_idx];
848  float *state_prev = &((float *)action->states_prev)[subaction_idx];
849  if (test_float_state(
850  state, action->float_thresholds[subaction_idx], action->axis_flags[subaction_idx])) {
851  curr = true;
852  }
853  if (test_float_state(state_prev,
854  action->float_thresholds[subaction_idx],
855  action->axis_flags[subaction_idx])) {
856  prev = true;
857  }
858  *state_prev = *state;
859  break;
860  }
861  case XR_VECTOR2F_INPUT: {
862  const float(*state)[2] = &((float(*)[2])action->states)[subaction_idx];
863  float(*state_prev)[2] = &((float(*)[2])action->states_prev)[subaction_idx];
864  if (test_vec2f_state(*state,
865  action->float_thresholds[subaction_idx],
866  action->axis_flags[subaction_idx])) {
867  curr = true;
868  }
869  if (test_vec2f_state(*state_prev,
870  action->float_thresholds[subaction_idx],
871  action->axis_flags[subaction_idx])) {
872  prev = true;
873  }
874  copy_v2_v2(*state_prev, *state);
875  break;
876  }
877  case XR_POSE_INPUT:
878  case XR_VIBRATION_OUTPUT:
880  break;
881  }
882 
883  if (curr) {
884  if (!prev) {
885  if (modal || (action->op_flag == XR_OP_PRESS)) {
886  *r_val = KM_PRESS;
887  }
888  if (haptic && (action->haptic_flag & (XR_HAPTIC_PRESS | XR_HAPTIC_REPEAT)) != 0) {
889  /* Apply haptics. */
891  action_set_name,
892  action->haptic_name,
893  haptic_subaction_path,
894  &action->haptic_duration,
895  &action->haptic_frequency,
896  &action->haptic_amplitude)) {
898  active_haptic_actions, action, haptic_subaction_path, time_now);
899  }
900  }
901  }
902  else if (modal) {
903  *r_val = KM_PRESS;
904  }
905  if (modal && !action->active_modal_path) {
906  /* Set active modal path. */
907  action->active_modal_path = action->subaction_paths[subaction_idx];
908  /* Add to active modal actions. */
909  wm_xr_session_modal_action_test_add(active_modal_actions, action);
910  }
911  if (haptic && ((action->haptic_flag & XR_HAPTIC_REPEAT) != 0)) {
913  active_haptic_actions, action, haptic_subaction_path)) {
914  /* Apply haptics. */
916  action_set_name,
917  action->haptic_name,
918  haptic_subaction_path,
919  &action->haptic_duration,
920  &action->haptic_frequency,
921  &action->haptic_amplitude)) {
923  active_haptic_actions, action, haptic_subaction_path, time_now);
924  }
925  }
926  }
927  }
928  else if (prev) {
929  if (modal || (action->op_flag == XR_OP_RELEASE)) {
930  *r_val = KM_RELEASE;
931  if (modal && (action->subaction_paths[subaction_idx] == action->active_modal_path)) {
932  /* Unset active modal path. */
933  action->active_modal_path = NULL;
934  /* Remove from active modal actions. */
935  wm_xr_session_modal_action_remove(active_modal_actions, action);
936  }
937  }
938  if (haptic) {
939  if ((action->haptic_flag & XR_HAPTIC_RELEASE) != 0) {
940  /* Apply haptics. */
942  action_set_name,
943  action->haptic_name,
944  haptic_subaction_path,
945  &action->haptic_duration,
946  &action->haptic_frequency,
947  &action->haptic_amplitude)) {
949  active_haptic_actions, action, haptic_subaction_path, time_now);
950  }
951  }
952  else if ((action->haptic_flag & XR_HAPTIC_REPEAT) != 0) {
953  /* Stop any active haptics. */
954  WM_xr_haptic_action_stop(xr, action_set_name, action->haptic_name, haptic_subaction_path);
955  wm_xr_session_haptic_action_remove(active_haptic_actions, action);
956  }
957  }
958  }
959 }
960 
961 static bool wm_xr_session_action_test_bimanual(const wmXrSessionState *session_state,
962  wmXrAction *action,
963  unsigned int subaction_idx,
964  unsigned int *r_subaction_idx_other,
965  const GHOST_XrPose **r_aim_pose_other)
966 {
967  if ((action->action_flag & XR_ACTION_BIMANUAL) == 0) {
968  return false;
969  }
970 
971  bool bimanual = false;
972 
973  *r_subaction_idx_other = (subaction_idx == 0) ?
974  (unsigned int)min_ii(1, action->count_subaction_paths - 1) :
975  0;
976 
977  switch (action->type) {
978  case XR_BOOLEAN_INPUT: {
979  const bool *state = &((bool *)action->states)[*r_subaction_idx_other];
980  if (*state) {
981  bimanual = true;
982  }
983  break;
984  }
985  case XR_FLOAT_INPUT: {
986  const float *state = &((float *)action->states)[*r_subaction_idx_other];
988  action->float_thresholds[*r_subaction_idx_other],
989  action->axis_flags[*r_subaction_idx_other])) {
990  bimanual = true;
991  }
992  break;
993  }
994  case XR_VECTOR2F_INPUT: {
995  const float(*state)[2] = &((float(*)[2])action->states)[*r_subaction_idx_other];
996  if (test_vec2f_state(*state,
997  action->float_thresholds[*r_subaction_idx_other],
998  action->axis_flags[*r_subaction_idx_other])) {
999  bimanual = true;
1000  }
1001  break;
1002  }
1003  case XR_POSE_INPUT:
1004  case XR_VIBRATION_OUTPUT:
1006  break;
1007  }
1008 
1009  if (bimanual) {
1010  *r_aim_pose_other = wm_xr_session_controller_aim_pose_find(
1011  session_state, action->subaction_paths[*r_subaction_idx_other]);
1012  }
1013 
1014  return bimanual;
1015 }
1016 
1017 static wmXrActionData *wm_xr_session_event_create(const char *action_set_name,
1018  const wmXrAction *action,
1019  const GHOST_XrPose *controller_aim_pose,
1020  const GHOST_XrPose *controller_aim_pose_other,
1021  unsigned int subaction_idx,
1022  unsigned int subaction_idx_other,
1023  bool bimanual)
1024 {
1025  wmXrActionData *data = MEM_callocN(sizeof(wmXrActionData), __func__);
1026  strcpy(data->action_set, action_set_name);
1027  strcpy(data->action, action->name);
1028  strcpy(data->user_path, action->subaction_paths[subaction_idx]);
1029  if (bimanual) {
1030  strcpy(data->user_path_other, action->subaction_paths[subaction_idx_other]);
1031  }
1032  data->type = action->type;
1033 
1034  switch (action->type) {
1035  case XR_BOOLEAN_INPUT:
1036  data->state[0] = ((bool *)action->states)[subaction_idx] ? 1.0f : 0.0f;
1037  if (bimanual) {
1038  data->state_other[0] = ((bool *)action->states)[subaction_idx_other] ? 1.0f : 0.0f;
1039  }
1040  break;
1041  case XR_FLOAT_INPUT:
1042  data->state[0] = ((float *)action->states)[subaction_idx];
1043  if (bimanual) {
1044  data->state_other[0] = ((float *)action->states)[subaction_idx_other];
1045  }
1046  data->float_threshold = action->float_thresholds[subaction_idx];
1047  break;
1048  case XR_VECTOR2F_INPUT:
1049  copy_v2_v2(data->state, ((float(*)[2])action->states)[subaction_idx]);
1050  if (bimanual) {
1051  copy_v2_v2(data->state_other, ((float(*)[2])action->states)[subaction_idx_other]);
1052  }
1053  data->float_threshold = action->float_thresholds[subaction_idx];
1054  break;
1055  case XR_POSE_INPUT:
1056  case XR_VIBRATION_OUTPUT:
1058  break;
1059  }
1060 
1061  if (controller_aim_pose) {
1062  copy_v3_v3(data->controller_loc, controller_aim_pose->position);
1063  copy_qt_qt(data->controller_rot, controller_aim_pose->orientation_quat);
1064 
1065  if (bimanual && controller_aim_pose_other) {
1066  copy_v3_v3(data->controller_loc_other, controller_aim_pose_other->position);
1067  copy_qt_qt(data->controller_rot_other, controller_aim_pose_other->orientation_quat);
1068  }
1069  else {
1070  data->controller_rot_other[0] = 1.0f;
1071  }
1072  }
1073  else {
1074  data->controller_rot[0] = 1.0f;
1075  data->controller_rot_other[0] = 1.0f;
1076  }
1077 
1078  data->ot = action->ot;
1079  data->op_properties = action->op_properties;
1080 
1081  data->bimanual = bimanual;
1082 
1083  return data;
1084 }
1085 
1086 /* Dispatch events to window queues. */
1088  GHOST_XrContextHandle xr_context,
1089  wmXrActionSet *action_set,
1090  wmXrSessionState *session_state,
1091  wmWindow *win)
1092 {
1093  const char *action_set_name = action_set->name;
1094 
1095  const unsigned int count = GHOST_XrGetActionCount(xr_context, action_set_name);
1096  if (count < 1) {
1097  return;
1098  }
1099 
1100  const int64_t time_now = (int64_t)(PIL_check_seconds_timer() * 1000);
1101 
1102  ListBase *active_modal_actions = &action_set->active_modal_actions;
1103  ListBase *active_haptic_actions = &action_set->active_haptic_actions;
1104 
1105  wmXrAction **actions = MEM_calloc_arrayN(count, sizeof(*actions), __func__);
1106 
1107  GHOST_XrGetActionCustomdataArray(xr_context, action_set_name, (void **)actions);
1108 
1109  /* Check haptic action timers. */
1110  wm_xr_session_haptic_timers_check(active_haptic_actions, time_now);
1111 
1112  for (unsigned int action_idx = 0; action_idx < count; ++action_idx) {
1113  wmXrAction *action = actions[action_idx];
1114  if (action && action->ot) {
1115  const bool modal = action->ot->modal;
1116  const bool haptic = (GHOST_XrGetActionCustomdata(
1117  xr_context, action_set_name, action->haptic_name) != NULL);
1118 
1119  for (unsigned int subaction_idx = 0; subaction_idx < action->count_subaction_paths;
1120  ++subaction_idx) {
1121  short val = KM_NOTHING;
1122 
1123  /* Interpret action states (update modal/haptic action lists, apply haptics, etc). */
1125  action_set_name,
1126  action,
1127  subaction_idx,
1128  active_modal_actions,
1129  active_haptic_actions,
1130  time_now,
1131  modal,
1132  haptic,
1133  &val);
1134 
1135  const bool is_active_modal_action = wm_xr_session_modal_action_test(
1136  active_modal_actions, action, NULL);
1137  const bool is_active_modal_subaction = (!action->active_modal_path ||
1138  (action->subaction_paths[subaction_idx] ==
1139  action->active_modal_path));
1140 
1141  if ((val != KM_NOTHING) &&
1142  (!modal || (is_active_modal_action && is_active_modal_subaction))) {
1143  const GHOST_XrPose *aim_pose = wm_xr_session_controller_aim_pose_find(
1144  session_state, action->subaction_paths[subaction_idx]);
1145  const GHOST_XrPose *aim_pose_other = NULL;
1146  unsigned int subaction_idx_other = 0;
1147 
1148  /* Test for bimanual interaction. */
1149  const bool bimanual = wm_xr_session_action_test_bimanual(
1150  session_state, action, subaction_idx, &subaction_idx_other, &aim_pose_other);
1151 
1152  wmXrActionData *actiondata = wm_xr_session_event_create(action_set_name,
1153  action,
1154  aim_pose,
1155  aim_pose_other,
1156  subaction_idx,
1157  subaction_idx_other,
1158  bimanual);
1159  wm_event_add_xrevent(win, actiondata, val);
1160  }
1161  }
1162  }
1163  }
1164 
1165  MEM_freeN(actions);
1166 }
1167 
1169 {
1170  wmXrData *xr = &wm->xr;
1171  if (!xr->runtime) {
1172  return;
1173  }
1174 
1175  XrSessionSettings *settings = &xr->session_settings;
1176  GHOST_XrContextHandle xr_context = xr->runtime->context;
1178 
1179  if (state->is_navigation_dirty) {
1180  memcpy(&state->nav_pose_prev, &state->nav_pose, sizeof(state->nav_pose_prev));
1181  state->nav_scale_prev = state->nav_scale;
1182  state->is_navigation_dirty = false;
1183 
1184  /* Update viewer pose with any navigation changes since the last actions sync so that data
1185  * is correct for queries. */
1186  float m[4][4], viewer_mat[4][4];
1187  wm_xr_pose_scale_to_mat(&state->nav_pose, state->nav_scale, m);
1188  mul_m4_m4m4(viewer_mat, m, state->viewer_mat_base);
1189  mat4_to_loc_quat(state->viewer_pose.position, state->viewer_pose.orientation_quat, viewer_mat);
1191  &state->viewer_pose, settings->base_scale * state->nav_scale, state->viewer_viewmat);
1192  }
1193 
1194  /* Set active action set if requested previously. */
1195  if (state->active_action_set_next[0]) {
1196  WM_xr_active_action_set_set(xr, state->active_action_set_next, false);
1197  state->active_action_set_next[0] = '\0';
1198  }
1199  wmXrActionSet *active_action_set = state->active_action_set;
1200 
1201  const bool synced = GHOST_XrSyncActions(xr_context,
1202  active_action_set ? active_action_set->name : NULL);
1203  if (!synced) {
1204  return;
1205  }
1206 
1207  /* Only update controller data and dispatch events for active action set. */
1208  if (active_action_set) {
1210 
1211  if (active_action_set->controller_grip_action && active_action_set->controller_aim_action) {
1213  active_action_set->controller_grip_action,
1214  active_action_set->controller_aim_action,
1215  xr_context,
1216  state);
1217  }
1218 
1219  if (win) {
1220  /* Ensure an XR area exists for events. */
1221  if (!xr->runtime->area) {
1223  }
1224 
1225  /* Set XR area object type flags for operators. */
1226  View3D *v3d = xr->runtime->area->spacedata.first;
1229 
1230  wm_xr_session_events_dispatch(xr, xr_context, active_action_set, state, win);
1231  }
1232  }
1233 }
1234 
1236  const wmXrAction *aim_action,
1237  wmXrData *xr)
1238 {
1239  UNUSED_VARS(aim_action); /* Only used for asserts. */
1240 
1242  ListBase *controllers = &state->controllers;
1243 
1244  BLI_assert(grip_action->count_subaction_paths == aim_action->count_subaction_paths);
1245  const unsigned int count = grip_action->count_subaction_paths;
1246 
1248 
1249  for (unsigned int i = 0; i < count; ++i) {
1250  wmXrController *controller = MEM_callocN(sizeof(*controller), __func__);
1251 
1252  BLI_assert(STREQ(grip_action->subaction_paths[i], aim_action->subaction_paths[i]));
1253  strcpy(controller->subaction_path, grip_action->subaction_paths[i]);
1254 
1255  BLI_addtail(controllers, controller);
1256  }
1257 
1258  /* Activate draw callback. */
1259  if (g_xr_surface) {
1260  wmXrSurfaceData *surface_data = g_xr_surface->customdata;
1261  if (surface_data && !surface_data->controller_draw_handle) {
1262  if (surface_data->controller_art) {
1265  }
1266  }
1267  }
1268 }
1269 
1271 {
1273 
1274  /* Deactivate draw callback. */
1275  if (g_xr_surface) {
1276  wmXrSurfaceData *surface_data = g_xr_surface->customdata;
1277  if (surface_data && surface_data->controller_draw_handle) {
1278  if (surface_data->controller_art) {
1279  ED_region_draw_cb_exit(surface_data->controller_art, surface_data->controller_draw_handle);
1280  }
1281  surface_data->controller_draw_handle = NULL;
1282  }
1283  }
1284 }
1285  /* XR-Session Actions */
1287 
1288 /* -------------------------------------------------------------------- */
1304 {
1306  wmXrDrawData draw_data;
1307 
1308  if (!WM_xr_session_is_ready(&wm->xr)) {
1309  return;
1310  }
1311 
1312  Scene *scene;
1315  /* Might fail when force-redrawing windows with #WM_redraw_windows(), which is done on file
1316  * writing for example. */
1317  // BLI_assert(DEG_is_fully_evaluated(depsgraph));
1318  wm_xr_session_draw_data_populate(&wm->xr, scene, depsgraph, &draw_data);
1319 
1320  GHOST_XrSessionDrawViews(wm->xr.runtime->context, &draw_data);
1321 
1322  /* There's no active frame-buffer if the session was canceled (exception while drawing views). */
1325  }
1326 }
1327 
1329 {
1331 
1332  if (!WM_xr_session_is_ready(&wm->xr)) {
1333  return;
1334  }
1335 
1336  Scene *scene;
1340 }
1341 
1343  const GHOST_XrDrawViewInfo *draw_view)
1344 {
1345  wmXrViewportPair *vp = NULL;
1346  if (draw_view->view_idx >= BLI_listbase_count(&surface_data->viewports)) {
1347  vp = MEM_callocN(sizeof(*vp), __func__);
1348  BLI_addtail(&surface_data->viewports, vp);
1349  }
1350  else {
1351  vp = BLI_findlink(&surface_data->viewports, draw_view->view_idx);
1352  }
1353  BLI_assert(vp);
1354 
1355  GPUOffScreen *offscreen = vp->offscreen;
1356  GPUViewport *viewport = vp->viewport;
1357  const bool size_changed = offscreen && (GPU_offscreen_width(offscreen) != draw_view->width) &&
1358  (GPU_offscreen_height(offscreen) != draw_view->height);
1359  if (offscreen) {
1360  BLI_assert(viewport);
1361 
1362  if (!size_changed) {
1363  return true;
1364  }
1365  GPU_viewport_free(viewport);
1366  GPU_offscreen_free(offscreen);
1367  }
1368 
1369  char err_out[256] = "unknown";
1370  bool failure = false;
1372  GPU_R8; /* Initialize with some unsupported format to check following switch statement. */
1373 
1374  switch (draw_view->swapchain_format) {
1375  case GHOST_kXrSwapchainFormatRGBA8:
1376  format = GPU_RGBA8;
1377  break;
1378  case GHOST_kXrSwapchainFormatRGBA16:
1379  format = GPU_RGBA16;
1380  break;
1381  case GHOST_kXrSwapchainFormatRGBA16F:
1382  format = GPU_RGBA16F;
1383  break;
1384  case GHOST_kXrSwapchainFormatRGB10_A2:
1385  format = GPU_RGB10_A2;
1386  break;
1387  }
1388  BLI_assert(format != GPU_R8);
1389 
1390  offscreen = vp->offscreen = GPU_offscreen_create(
1391  draw_view->width, draw_view->height, true, format, err_out);
1392  if (offscreen) {
1393  viewport = vp->viewport = GPU_viewport_create();
1394  if (!viewport) {
1395  GPU_offscreen_free(offscreen);
1396  offscreen = vp->offscreen = NULL;
1397  failure = true;
1398  }
1399  }
1400  else {
1401  failure = true;
1402  }
1403 
1404  if (failure) {
1405  CLOG_ERROR(&LOG, "Failed to get buffer, %s", err_out);
1406  return false;
1407  }
1408 
1409  return true;
1410 }
1411 
1413 {
1414  wmXrSurfaceData *data = surface->customdata;
1415  ListBase *lb = &data->viewports;
1416  wmXrViewportPair *vp;
1417 
1418  while ((vp = BLI_pophead(lb))) {
1419  if (vp->viewport) {
1421  }
1422  if (vp->offscreen) {
1424  }
1425  BLI_freelinkN(lb, vp);
1426  }
1427 
1428  if (data->controller_art) {
1429  BLI_freelistN(&data->controller_art->drawcalls);
1430  MEM_freeN(data->controller_art);
1431  }
1432 
1433  MEM_freeN(surface->customdata);
1434 
1435  g_xr_surface = NULL;
1436 }
1437 
1439 {
1440  if (g_xr_surface) {
1441  BLI_assert(false);
1442  return g_xr_surface;
1443  }
1444 
1445  wmSurface *surface = MEM_callocN(sizeof(*surface), __func__);
1446  wmXrSurfaceData *data = MEM_callocN(sizeof(*data), "XrSurfaceData");
1447  data->controller_art = MEM_callocN(sizeof(*(data->controller_art)), "XrControllerRegionType");
1448 
1450  surface->do_depsgraph = wm_xr_session_do_depsgraph;
1452  surface->activate = DRW_xr_drawing_begin;
1453  surface->deactivate = DRW_xr_drawing_end;
1454 
1455  surface->ghost_ctx = DRW_xr_opengl_context_get();
1456  surface->gpu_ctx = DRW_xr_gpu_context_get();
1457 
1458  data->controller_art->regionid = RGN_TYPE_XR;
1459  surface->customdata = data;
1460 
1462 
1463  return surface;
1464 }
1465 
1467 {
1469 
1471 
1472  /* Some regions may need to redraw with updated session state after the session is entirely up
1473  * and running. */
1475 
1476  return surface->ghost_ctx;
1477 }
1478 
1480 {
1481  if (g_xr_surface) { /* Might have been freed already */
1483  }
1484 
1486 
1487  /* Some regions may need to redraw with updated session state after the session is entirely
1488  * stopped. */
1490 }
1491 
1493 {
1494  if (g_xr_surface) {
1496  return data->controller_art;
1497  }
1498 
1499  return NULL;
1500 }
1501  /* XR-Session Surface */
typedef float(TangentPoint)[2]
void BKE_callback_exec_null(struct Main *bmain, eCbEvent evt)
Definition: callbacks.c:41
@ BKE_CB_EVT_XR_SESSION_START_PRE
Definition: BKE_callbacks.h:97
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
#define G_MAIN
Definition: BKE_global.h:267
bool IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT
Definition: idprop.c:882
struct Depsgraph * BKE_scene_get_depsgraph(const struct Scene *scene, const struct ViewLayer *view_layer)
void BKE_scene_graph_evaluated_ensure(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.cc:2653
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:221
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
#define M_PI_2
Definition: BLI_math_base.h:23
#define BLI_ASSERT_UNIT_QUAT(q)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4])
Definition: math_matrix.c:2235
void axis_angle_to_quat_single(float q[4], char axis, float angle)
void unit_qt(float q[4])
Definition: math_rotation.c:27
void eul_to_quat(float quat[4], const float eul[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])
Definition: math_rotation.c:46
float fov_to_focallength(float fov, float sensor)
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define UNUSED_VARS(...)
#define UNUSED(x)
#define STREQ(a, b)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
#define DEFAULT_SENSOR_WIDTH
@ RGN_TYPE_XR
@ SPACE_VIEW3D
@ XR_OP_RELEASE
Definition: DNA_xr_types.h:75
@ XR_OP_PRESS
Definition: DNA_xr_types.h:74
eXrAxisFlag
Definition: DNA_xr_types.h:100
@ XR_AXIS0_POS
Definition: DNA_xr_types.h:101
@ XR_AXIS1_NEG
Definition: DNA_xr_types.h:104
@ XR_AXIS1_POS
Definition: DNA_xr_types.h:103
@ XR_AXIS0_NEG
Definition: DNA_xr_types.h:102
@ XR_SESSION_USE_ABSOLUTE_TRACKING
Definition: DNA_xr_types.h:47
@ XR_SESSION_USE_POSITION_TRACKING
Definition: DNA_xr_types.h:46
@ XR_FLOAT_INPUT
Definition: DNA_xr_types.h:66
@ XR_BOOLEAN_INPUT
Definition: DNA_xr_types.h:65
@ XR_VECTOR2F_INPUT
Definition: DNA_xr_types.h:67
@ XR_POSE_INPUT
Definition: DNA_xr_types.h:68
@ XR_VIBRATION_OUTPUT
Definition: DNA_xr_types.h:69
@ XR_BASE_POSE_CUSTOM
Definition: DNA_xr_types.h:53
@ XR_BASE_POSE_OBJECT
Definition: DNA_xr_types.h:52
@ XR_ACTION_BIMANUAL
Definition: DNA_xr_types.h:81
@ XR_HAPTIC_PRESS
Definition: DNA_xr_types.h:91
@ XR_HAPTIC_RELEASE
Definition: DNA_xr_types.h:92
@ XR_HAPTIC_MATCHUSERPATHS
Definition: DNA_xr_types.h:86
@ XR_HAPTIC_REPEAT
Definition: DNA_xr_types.h:93
ScrArea * ED_area_offscreen_create(struct wmWindow *win, eSpace_Type space_type)
Definition: area.c:1995
#define REGION_DRAW_POST_VIEW
Definition: ED_space_api.h:62
void * ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *customdata, int type)
Definition: spacetypes.c:226
bool ED_region_draw_cb_exit(struct ARegionType *art, void *handle)
Definition: spacetypes.c:241
static Controller * controller
GHOST C-API function and type declarations.
void GPU_batch_discard(GPUBatch *)
Definition: gpu_batch.cc:109
void GPU_framebuffer_restore(void)
GPUFrameBuffer * GPU_framebuffer_active_get(void)
eGPUTextureFormat
Definition: GPU_texture.h:83
@ GPU_RGB10_A2
Definition: GPU_texture.h:117
@ GPU_RGBA16
Definition: GPU_texture.h:94
@ GPU_R8
Definition: GPU_texture.h:107
@ GPU_RGBA8
Definition: GPU_texture.h:87
GPUViewport * GPU_viewport_create(void)
Definition: gpu_viewport.c:98
void GPU_viewport_free(GPUViewport *viewport)
Definition: gpu_viewport.c:585
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
Platform independent time functions.
#define C
Definition: RandGen.cpp:25
@ KM_NOTHING
Definition: WM_types.h:266
@ KM_PRESS
Definition: WM_types.h:267
@ KM_RELEASE
Definition: WM_types.h:268
#define NC_WM
Definition: WM_types.h:324
#define ND_XR_DATA_CHANGED
Definition: WM_types.h:366
Scene scene
const Depsgraph * depsgraph
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img GPU_RGBA16F
struct @211::@212 surface
void GPU_offscreen_free(GPUOffScreen *ofs)
GPUOffScreen * GPU_offscreen_create(int width, int height, bool depth, eGPUTextureFormat format, char err_out[256])
int GPU_offscreen_width(const GPUOffScreen *ofs)
int GPU_offscreen_height(const GPUOffScreen *ofs)
int count
ccl_gpu_kernel_postfix ccl_global float int int int int float threshold
const int state
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned c
Definition: RandGen.cpp:83
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
__int64 int64_t
Definition: stdint.h:89
void * data
Definition: DNA_listBase.h:26
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase wm
Definition: BKE_main.h:197
float obmat[4][4]
struct Object * camera
ListBase spacedata
int object_type_exclude_select
int object_type_exclude_viewport
int object_type_exclude_select
Definition: DNA_xr_types.h:42
float base_pose_location[3]
Definition: DNA_xr_types.h:26
Object * base_pose_object
Definition: DNA_xr_types.h:25
int object_type_exclude_viewport
Definition: DNA_xr_types.h:41
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
void * customdata
Definition: wm_surface.h:25
wmXrAction * controller_aim_action
Definition: wm_xr_intern.h:180
wmXrAction * controller_grip_action
Definition: wm_xr_intern.h:179
ListBase active_modal_actions
Definition: wm_xr_intern.h:183
ListBase active_haptic_actions
Definition: wm_xr_intern.h:185
eXrActionType type
Definition: wm_xr_intern.h:137
struct wmOperatorType * ot
Definition: wm_xr_intern.h:153
eXrAxisFlag * axis_flags
Definition: wm_xr_intern.h:147
void * states
Definition: wm_xr_intern.h:141
char * haptic_name
Definition: wm_xr_intern.h:157
unsigned int count_subaction_paths
Definition: wm_xr_intern.h:138
void * states_prev
Definition: wm_xr_intern.h:143
eXrOpFlag op_flag
Definition: wm_xr_intern.h:163
char * name
Definition: wm_xr_intern.h:136
float haptic_frequency
Definition: wm_xr_intern.h:159
int64_t haptic_duration
Definition: wm_xr_intern.h:158
eXrActionFlag action_flag
Definition: wm_xr_intern.h:164
const char * active_modal_path
Definition: wm_xr_intern.h:150
char ** subaction_paths
Definition: wm_xr_intern.h:139
float * float_thresholds
Definition: wm_xr_intern.h:146
float haptic_amplitude
Definition: wm_xr_intern.h:160
eXrHapticFlag haptic_flag
Definition: wm_xr_intern.h:165
IDProperty * op_properties
Definition: wm_xr_intern.h:154
XrSessionSettings session_settings
struct wmXrRuntimeData * runtime
wmXrData * xr_data
Definition: wm_xr_intern.h:103
float base_scale
Definition: wm_xr_intern.h:111
float eye_position_ofs[3]
Definition: wm_xr_intern.h:114
struct Depsgraph * depsgraph
Definition: wm_xr_intern.h:101
GHOST_XrPose base_pose
Definition: wm_xr_intern.h:109
wmXrSurfaceData * surface_data
Definition: wm_xr_intern.h:104
struct Scene * scene
Definition: wm_xr_intern.h:100
const char * subaction_path
Definition: wm_xr_intern.h:171
wmXrAction * action
Definition: wm_xr_intern.h:170
GHOST_XrContextHandle context
Definition: wm_xr_intern.h:65
wmXrSessionExitFn exit_fn
Definition: wm_xr_intern.h:76
wmXrSessionState session_state
Definition: wm_xr_intern.h:75
wmWindow * session_root_win
Definition: wm_xr_intern.h:69
struct ScrArea * area
Definition: wm_xr_intern.h:72
float viewer_viewmat[4][4]
Definition: wm_xr_intern.h:21
GHOST_XrPose nav_pose
Definition: wm_xr_intern.h:45
bool force_reset_to_base_pose
Definition: wm_xr_intern.h:41
bool is_navigation_dirty
Definition: wm_xr_intern.h:51
ListBase controllers
Definition: wm_xr_intern.h:54
GHOST_XrPose viewer_pose
Definition: wm_xr_intern.h:19
struct ARegionType * controller_art
Definition: wm_xr_intern.h:94
ListBase viewports
Definition: wm_xr_intern.h:91
void * controller_draw_handle
Definition: wm_xr_intern.h:96
struct GPUViewport * viewport
Definition: wm_xr_intern.h:86
struct GPUOffScreen * offscreen
Definition: wm_xr_intern.h:85
double PIL_check_seconds_timer(void)
Definition: time.c:64
void WM_main_add_notifier(unsigned int type, void *reference)
void wm_surface_add(wmSurface *surface)
Definition: wm_surface.c:102
void wm_surface_remove(wmSurface *surface)
Definition: wm_surface.c:107
void wm_window_reset_drawable(void)
Definition: wm_window.c:1049
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
Definition: wm_window.c:2217
Scene * WM_window_get_active_scene(const wmWindow *win)
Definition: wm_window.c:2183
void wm_xr_runtime_data_free(wmXrRuntimeData **runtime)
Definition: wm_xr.c:150
void(* wmXrSessionExitFn)(const wmXrData *xr_data)
Definition: wm_xr.h:12
void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name, const char *subaction_path)
Definition: wm_xr_action.c:534
bool WM_xr_haptic_action_apply(wmXrData *xr, const char *action_set_name, const char *action_name, const char *subaction_path, const int64_t *duration, const float *frequency, const float *amplitude)
Definition: wm_xr_action.c:515
bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name, bool delayed)
Definition: wm_xr_action.c:394
void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4])
Definition: wm_xr_draw.c:32
void wm_xr_pose_scale_to_mat(const GHOST_XrPose *pose, float scale, float r_mat[4][4])
Definition: wm_xr_draw.c:38
void wm_xr_draw_controllers(const bContext *UNUSED(C), ARegion *UNUSED(region), void *customdata)
Definition: wm_xr_draw.c:379
void wm_xr_pose_scale_to_imat(const GHOST_XrPose *pose, float scale, float r_imat[4][4])
Definition: wm_xr_draw.c:56
void WM_xr_session_state_nav_scale_set(wmXrData *xr, float scale)
bool WM_xr_session_state_controller_aim_location_get(const wmXrData *xr, unsigned int subaction_idx, float r_location[3])
BLI_INLINE bool test_float_state(const float *state, float threshold, eXrAxisFlag flag)
void wm_xr_session_actions_update(wmWindowManager *wm)
void wm_xr_session_draw_data_update(wmXrSessionState *state, const XrSessionSettings *settings, const GHOST_XrDrawViewInfo *draw_view, wmXrDrawData *draw_data)
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_base[4][4])
static void wm_xr_session_haptic_timers_check(ListBase *active_haptic_actions, int64_t time_now)
wmXrSessionState * WM_xr_session_state_handle_get(const wmXrData *xr)
void WM_xr_session_base_pose_reset(wmXrData *xr)
bool WM_xr_session_state_nav_scale_get(const wmXrData *xr, float *r_scale)
static void wm_xr_session_haptic_action_remove(ListBase *active_haptic_actions, const wmXrAction *action)
static wmSurface * wm_xr_session_surface_create(void)
static void wm_xr_session_exit_cb(void *customdata)
Definition: wm_xr_session.c:90
static wmXrSessionStateEvent wm_xr_session_state_to_event(const wmXrSessionState *state, const XrSessionSettings *settings)
static void wm_xr_session_events_dispatch(wmXrData *xr, GHOST_XrContextHandle xr_context, wmXrActionSet *action_set, wmXrSessionState *session_state, wmWindow *win)
static void wm_xr_session_do_depsgraph(bContext *C)
static void wm_xr_session_base_pose_calc(const Scene *scene, const XrSessionSettings *settings, GHOST_XrPose *r_base_pose, float *r_base_scale)
static bool wm_xr_session_action_test_bimanual(const wmXrSessionState *session_state, wmXrAction *action, unsigned int subaction_idx, unsigned int *r_subaction_idx_other, const GHOST_XrPose **r_aim_pose_other)
static wmXrActionData * wm_xr_session_event_create(const char *action_set_name, const wmXrAction *action, const GHOST_XrPose *controller_aim_pose, const GHOST_XrPose *controller_aim_pose_other, unsigned int subaction_idx, unsigned int subaction_idx_other, bool bimanual)
static void wm_xr_session_modal_action_test_add(ListBase *active_modal_actions, const wmXrAction *action)
bool WM_xr_session_state_controller_grip_rotation_get(const wmXrData *xr, unsigned int subaction_idx, float r_rotation[4])
static wmXrHapticAction * wm_xr_session_haptic_action_find(ListBase *active_haptic_actions, const wmXrAction *action, const char *subaction_path)
void WM_xr_session_state_navigation_reset(wmXrSessionState *state)
BLI_INLINE bool test_vec2f_state(const float state[2], float threshold, eXrAxisFlag flag)
ARegionType * WM_xr_surface_controller_region_type_get(void)
static void wm_xr_session_create_cb(void)
Definition: wm_xr_session.c:51
static void wm_xr_session_action_states_interpret(wmXrData *xr, const char *action_set_name, wmXrAction *action, unsigned int subaction_idx, ListBase *active_modal_actions, ListBase *active_haptic_actions, int64_t time_now, bool modal, bool haptic, short *r_val)
static const GHOST_XrPose * wm_xr_session_controller_aim_pose_find(const wmXrSessionState *state, const char *subaction_path)
static void wm_xr_session_modal_action_remove(ListBase *active_modal_actions, const wmXrAction *action)
wmWindow * wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm, const wmXrRuntimeData *runtime_data)
bool WM_xr_session_state_controller_grip_location_get(const wmXrData *xr, unsigned int subaction_idx, float r_location[3])
static void wm_xr_session_surface_free_data(wmSurface *surface)
static wmSurface * g_xr_surface
Definition: wm_xr_session.c:46
void wm_xr_session_toggle(wmWindowManager *wm, wmWindow *session_root_win, wmXrSessionExitFn session_exit_fn)
void wm_xr_session_controller_data_populate(const wmXrAction *grip_action, const wmXrAction *aim_action, wmXrData *xr)
static void wm_xr_session_surface_draw(bContext *C)
Call Ghost-XR to draw a frame.
static void wm_xr_session_controller_data_update(const XrSessionSettings *settings, const wmXrAction *grip_action, const wmXrAction *aim_action, GHOST_XrContextHandle xr_context, wmXrSessionState *state)
bool WM_xr_session_state_controller_aim_rotation_get(const wmXrData *xr, unsigned int subaction_idx, float r_rotation[4])
void * wm_xr_session_gpu_binding_context_create(void)
void wm_xr_session_state_update(const XrSessionSettings *settings, const wmXrDrawData *draw_data, const GHOST_XrDrawViewInfo *draw_view, wmXrSessionState *state)
static bool wm_xr_session_modal_action_test(const ListBase *active_modal_actions, const wmXrAction *action, bool *r_found)
static void wm_xr_session_controller_data_free(wmXrSessionState *state)
Definition: wm_xr_session.c:72
void wm_xr_session_controller_data_clear(wmXrSessionState *state)
static bool wm_xr_session_draw_data_needs_reset_to_base_pose(const wmXrSessionState *state, const XrSessionSettings *settings)
ScrArea * WM_xr_session_area_get(const wmXrData *xr)
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])
static void wm_xr_session_scene_and_depsgraph_get(const wmWindowManager *wm, Scene **r_scene, Depsgraph **r_depsgraph)
bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr, float r_viewmat[4][4], float *r_focal_len)
static CLG_LogRef LOG
Definition: wm_xr_session.c:47
void wm_xr_session_data_free(wmXrSessionState *state)
Definition: wm_xr_session.c:85
bool wm_xr_session_surface_offscreen_ensure(wmXrSurfaceData *surface_data, const GHOST_XrDrawViewInfo *draw_view)
wmXrSessionStateEvent
@ SESSION_STATE_EVENT_NONE
@ SESSION_STATE_EVENT_POSITION_TRACKING_TOGGLE
@ SESSION_STATE_EVENT_START
@ SESSION_STATE_EVENT_RESET_TO_BASE_POSE
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_actions_init(wmXrData *xr)
static void wm_xr_session_begin_info_create(wmXrData *xr_data, GHOST_XrSessionBeginInfo *r_begin_info)
void WM_xr_session_state_nav_rotation_set(wmXrData *xr, const float rotation[4])
static void wm_xr_session_haptic_action_add(ListBase *active_haptic_actions, const wmXrAction *action, const char *subaction_path, int64_t time_now)
static void wm_xr_session_draw_data_populate(wmXrData *xr_data, Scene *scene, Depsgraph *depsgraph, wmXrDrawData *r_draw_data)
bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_rotation[4])
void wm_xr_session_gpu_binding_context_destroy(GHOST_ContextHandle UNUSED(context))
bool WM_xr_session_state_nav_rotation_get(const wmXrData *xr, float r_rotation[4])