Blender  V3.3
wm_xr_operators.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
11 #include "BLI_kdopbvh.h"
12 #include "BLI_listbase.h"
13 #include "BLI_math.h"
14 
15 #include "BKE_context.h"
16 #include "BKE_global.h"
17 #include "BKE_idprop.h"
18 #include "BKE_main.h"
19 #include "BKE_screen.h"
20 
21 #include "DEG_depsgraph.h"
22 
23 #include "ED_screen.h"
24 #include "ED_space_api.h"
26 #include "ED_view3d.h"
27 
28 #include "GHOST_Types.h"
29 
30 #include "GPU_immediate.h"
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "PIL_time.h"
35 
36 #include "RNA_access.h"
37 #include "RNA_define.h"
38 
39 #include "WM_api.h"
40 #include "WM_types.h"
41 
42 #include "wm_xr_intern.h"
43 
44 /* -------------------------------------------------------------------- */
48 /* op->poll */
50 {
52  return WM_xr_session_is_ready(&wm->xr);
53 }
54 
55 static bool wm_xr_operator_test_event(const wmOperator *op, const wmEvent *event)
56 {
57  if (event->type != EVT_XR_ACTION) {
58  return false;
59  }
60 
61  BLI_assert(event->custom == EVT_DATA_XR);
62  BLI_assert(event->customdata);
63 
64  wmXrActionData *actiondata = event->customdata;
65  return (actiondata->ot == op->type &&
66  IDP_EqualsProperties(actiondata->op_properties, op->properties));
67 }
68 
71 /* -------------------------------------------------------------------- */
77 static void wm_xr_session_update_screen(Main *bmain, const wmXrData *xr_data)
78 {
79  const bool session_exists = WM_xr_session_exists(xr_data);
80 
81  for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
82  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
83  LISTBASE_FOREACH (SpaceLink *, slink, &area->spacedata) {
84  if (slink->spacetype == SPACE_VIEW3D) {
85  View3D *v3d = (View3D *)slink;
86 
87  if (v3d->flag & V3D_XR_SESSION_MIRROR) {
88  ED_view3d_xr_mirror_update(area, v3d, session_exists);
89  }
90 
91  if (session_exists) {
92  wmWindowManager *wm = bmain->wm.first;
93  const Scene *scene = WM_windows_scene_get_from_screen(wm, screen);
94 
95  ED_view3d_xr_shading_update(wm, v3d, scene);
96  }
97  /* Ensure no 3D View is tagged as session root. */
98  else {
100  }
101  }
102  }
103  }
104  }
105 
107 }
108 
110 {
111  /* Just use G_MAIN here, storing main isn't reliable enough on file read or exit. */
113 }
114 
116 {
117  Main *bmain = CTX_data_main(C);
119  wmWindow *win = CTX_wm_window(C);
120  View3D *v3d = CTX_wm_view3d(C);
121 
122  /* Lazily-create XR context - tries to dynamic-link to the runtime,
123  * reading `active_runtime.json`. */
124  if (wm_xr_init(wm) == false) {
125  return OPERATOR_CANCELLED;
126  }
127 
130  wm_xr_session_update_screen(bmain, &wm->xr);
131 
133 
134  return OPERATOR_FINISHED;
135 }
136 
138 {
139  /* identifiers */
140  ot->name = "Toggle VR Session";
141  ot->idname = "WM_OT_xr_session_toggle";
142  ot->description =
143  "Open a view for use with virtual reality headsets, or close it if already "
144  "opened";
145 
146  /* callbacks */
149 
150  /* XXX INTERNAL just to hide it from the search menu by default, an Add-on will expose it in the
151  * UI instead. Not meant as a permanent solution. */
153 }
154 
157 /* -------------------------------------------------------------------- */
161 typedef struct XrGrabData {
162  float mat_prev[4][4];
163  float mat_other_prev[4][4];
167 
168 static void wm_xr_grab_init(wmOperator *op)
169 {
170  BLI_assert(op->customdata == NULL);
171 
172  op->customdata = MEM_callocN(sizeof(XrGrabData), __func__);
173 }
174 
176 {
178 }
179 
180 static void wm_xr_grab_update(wmOperator *op, const wmXrActionData *actiondata)
181 {
182  XrGrabData *data = op->customdata;
183 
184  quat_to_mat4(data->mat_prev, actiondata->controller_rot);
185  copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
186 
187  if (actiondata->bimanual) {
188  quat_to_mat4(data->mat_other_prev, actiondata->controller_rot_other);
189  copy_v3_v3(data->mat_other_prev[3], actiondata->controller_loc_other);
190  data->bimanual_prev = true;
191  }
192  else {
193  data->bimanual_prev = false;
194  }
195 }
196 
197 static void orient_mat_z_normalized(float R[4][4], const float z_axis[3])
198 {
199  const float scale = len_v3(R[0]);
200  float x_axis[3], y_axis[3];
201 
202  cross_v3_v3v3(y_axis, z_axis, R[0]);
203  normalize_v3(y_axis);
204  mul_v3_v3fl(R[1], y_axis, scale);
205 
206  cross_v3_v3v3(x_axis, R[1], z_axis);
207  normalize_v3(x_axis);
208  mul_v3_v3fl(R[0], x_axis, scale);
209 
210  mul_v3_v3fl(R[2], z_axis, scale);
211 }
212 
213 static void wm_xr_navlocks_apply(const float nav_mat[4][4],
214  const float nav_inv[4][4],
215  bool loc_lock,
216  bool locz_lock,
217  bool rotz_lock,
218  float r_prev[4][4],
219  float r_curr[4][4])
220 {
221  /* Locked in base pose coordinates. */
222  float prev_base[4][4], curr_base[4][4];
223 
224  mul_m4_m4m4(prev_base, nav_inv, r_prev);
225  mul_m4_m4m4(curr_base, nav_inv, r_curr);
226 
227  if (rotz_lock) {
228  const float z_axis[3] = {0.0f, 0.0f, 1.0f};
229  orient_mat_z_normalized(prev_base, z_axis);
230  orient_mat_z_normalized(curr_base, z_axis);
231  }
232 
233  if (loc_lock) {
234  copy_v3_v3(curr_base[3], prev_base[3]);
235  }
236  else if (locz_lock) {
237  curr_base[3][2] = prev_base[3][2];
238  }
239 
240  mul_m4_m4m4(r_prev, nav_mat, prev_base);
241  mul_m4_m4m4(r_curr, nav_mat, curr_base);
242 }
243 
253 static void wm_xr_grab_compute(const wmXrActionData *actiondata,
254  const XrGrabData *data,
255  const float nav_mat[4][4],
256  const float nav_inv[4][4],
257  bool reverse,
258  float r_delta[4][4])
259 {
260  const bool nav_lock = (nav_mat && nav_inv);
261  float prev[4][4], curr[4][4];
262 
263  if (!data->rot_lock) {
264  copy_m4_m4(prev, data->mat_prev);
265  zero_v3(prev[3]);
266  quat_to_mat4(curr, actiondata->controller_rot);
267  }
268  else {
269  unit_m4(prev);
270  unit_m4(curr);
271  }
272 
273  if (!data->loc_lock || nav_lock) {
274  copy_v3_v3(prev[3], data->mat_prev[3]);
275  copy_v3_v3(curr[3], actiondata->controller_loc);
276  }
277 
278  if (nav_lock) {
280  nav_mat, nav_inv, data->loc_lock, data->locz_lock, data->rotz_lock, prev, curr);
281  }
282 
283  if (reverse) {
284  invert_m4(curr);
285  mul_m4_m4m4(r_delta, prev, curr);
286  }
287  else {
288  invert_m4(prev);
289  mul_m4_m4m4(r_delta, curr, prev);
290  }
291 }
292 
305 static void wm_xr_grab_compute_bimanual(const wmXrActionData *actiondata,
306  const XrGrabData *data,
307  const float nav_mat[4][4],
308  const float nav_inv[4][4],
309  bool reverse,
310  float r_delta[4][4])
311 {
312  const bool nav_lock = (nav_mat && nav_inv);
313  float prev[4][4], curr[4][4];
314  unit_m4(prev);
315  unit_m4(curr);
316 
317  if (!data->rot_lock) {
318  /* Rotation. */
319  float x_axis_prev[3], x_axis_curr[3], y_axis_prev[3], y_axis_curr[3], z_axis_prev[3],
320  z_axis_curr[3];
321  float m0[3][3], m1[3][3];
322  quat_to_mat3(m0, actiondata->controller_rot);
323  quat_to_mat3(m1, actiondata->controller_rot_other);
324 
325  /* x-axis is the base line between the two controllers. */
326  sub_v3_v3v3(x_axis_prev, data->mat_prev[3], data->mat_other_prev[3]);
327  sub_v3_v3v3(x_axis_curr, actiondata->controller_loc, actiondata->controller_loc_other);
328  /* y-axis is the average of the controllers' y-axes. */
329  add_v3_v3v3(y_axis_prev, data->mat_prev[1], data->mat_other_prev[1]);
330  mul_v3_fl(y_axis_prev, 0.5f);
331  add_v3_v3v3(y_axis_curr, m0[1], m1[1]);
332  mul_v3_fl(y_axis_curr, 0.5f);
333  /* z-axis is the cross product of the two. */
334  cross_v3_v3v3(z_axis_prev, x_axis_prev, y_axis_prev);
335  cross_v3_v3v3(z_axis_curr, x_axis_curr, y_axis_curr);
336  /* Fix the y-axis to be orthogonal. */
337  cross_v3_v3v3(y_axis_prev, z_axis_prev, x_axis_prev);
338  cross_v3_v3v3(y_axis_curr, z_axis_curr, x_axis_curr);
339  /* Normalize. */
340  normalize_v3_v3(prev[0], x_axis_prev);
341  normalize_v3_v3(prev[1], y_axis_prev);
342  normalize_v3_v3(prev[2], z_axis_prev);
343  normalize_v3_v3(curr[0], x_axis_curr);
344  normalize_v3_v3(curr[1], y_axis_curr);
345  normalize_v3_v3(curr[2], z_axis_curr);
346  }
347 
348  if (!data->loc_lock || nav_lock) {
349  /* Translation: translation of the averaged controller locations. */
350  add_v3_v3v3(prev[3], data->mat_prev[3], data->mat_other_prev[3]);
351  mul_v3_fl(prev[3], 0.5f);
352  add_v3_v3v3(curr[3], actiondata->controller_loc, actiondata->controller_loc_other);
353  mul_v3_fl(curr[3], 0.5f);
354  }
355 
356  if (!data->scale_lock) {
357  /* Scaling: distance between controllers. */
358  float scale, v[3];
359 
360  sub_v3_v3v3(v, data->mat_prev[3], data->mat_other_prev[3]);
361  scale = len_v3(v);
362  mul_v3_fl(prev[0], scale);
363  mul_v3_fl(prev[1], scale);
364  mul_v3_fl(prev[2], scale);
365 
366  sub_v3_v3v3(v, actiondata->controller_loc, actiondata->controller_loc_other);
367  scale = len_v3(v);
368  mul_v3_fl(curr[0], scale);
369  mul_v3_fl(curr[1], scale);
370  mul_v3_fl(curr[2], scale);
371  }
372 
373  if (nav_lock) {
375  nav_mat, nav_inv, data->loc_lock, data->locz_lock, data->rotz_lock, prev, curr);
376  }
377 
378  if (reverse) {
379  invert_m4(curr);
380  mul_m4_m4m4(r_delta, prev, curr);
381  }
382  else {
383  invert_m4(prev);
384  mul_m4_m4m4(r_delta, curr, prev);
385  }
386 }
387 
390 /* -------------------------------------------------------------------- */
397 {
398  if (!wm_xr_operator_test_event(op, event)) {
399  return OPERATOR_PASS_THROUGH;
400  }
401 
402  const wmXrActionData *actiondata = event->customdata;
403 
404  wm_xr_grab_init(op);
405  wm_xr_grab_update(op, actiondata);
406 
408 
409  return OPERATOR_RUNNING_MODAL;
410 }
411 
413 {
414  return OPERATOR_CANCELLED;
415 }
416 
417 static bool wm_xr_navigation_grab_can_do_bimanual(const wmXrActionData *actiondata,
418  const XrGrabData *data)
419 {
420  /* Returns true if: 1) Bimanual interaction is currently occurring (i.e. inputs on both
421  * controllers are pressed) and 2) bimanual interaction occurred on the last update. This second
422  * part is needed to avoid "jumpy" navigation changes when transitioning from one-handed to
423  * two-handed interaction (see #wm_xr_grab_compute/compute_bimanual() for how navigation deltas
424  * are calculated). */
425  return (actiondata->bimanual && data->bimanual_prev);
426 }
427 
428 static bool wm_xr_navigation_grab_is_bimanual_ending(const wmXrActionData *actiondata,
429  const XrGrabData *data)
430 {
431  return (!actiondata->bimanual && data->bimanual_prev);
432 }
433 
434 static bool wm_xr_navigation_grab_is_locked(const XrGrabData *data, const bool bimanual)
435 {
436  if (bimanual) {
437  return data->loc_lock && data->rot_lock && data->scale_lock;
438  }
439  /* Ignore scale lock, as one-handed interaction cannot change navigation scale. */
440  return data->loc_lock && data->rot_lock;
441 }
442 
444  const wmXrActionData *actiondata,
445  const XrGrabData *data,
446  bool bimanual)
447 {
448  GHOST_XrPose nav_pose;
449  float nav_scale;
450  float nav_mat[4][4], nav_inv[4][4], delta[4][4], out[4][4];
451 
452  const bool need_navinv = (data->loc_lock || data->locz_lock || data->rotz_lock);
453 
454  WM_xr_session_state_nav_location_get(xr, nav_pose.position);
455  WM_xr_session_state_nav_rotation_get(xr, nav_pose.orientation_quat);
456  WM_xr_session_state_nav_scale_get(xr, &nav_scale);
457 
458  wm_xr_pose_scale_to_mat(&nav_pose, nav_scale, nav_mat);
459  if (need_navinv) {
460  wm_xr_pose_scale_to_imat(&nav_pose, nav_scale, nav_inv);
461  }
462 
463  if (bimanual) {
465  actiondata, data, need_navinv ? nav_mat : NULL, need_navinv ? nav_inv : NULL, true, delta);
466  }
467  else {
469  actiondata, data, need_navinv ? nav_mat : NULL, need_navinv ? nav_inv : NULL, true, delta);
470  }
471 
472  mul_m4_m4m4(out, delta, nav_mat);
473 
474  /* Limit scale to reasonable values. */
475  nav_scale = len_v3(out[0]);
476 
477  if (!(nav_scale < xr->session_settings.clip_start ||
478  nav_scale > xr->session_settings.clip_end)) {
480  if (!data->rot_lock) {
481  mat4_to_quat(nav_pose.orientation_quat, out);
482  normalize_qt(nav_pose.orientation_quat);
483  WM_xr_session_state_nav_rotation_set(xr, nav_pose.orientation_quat);
484  }
485  if (!data->scale_lock && bimanual) {
486  WM_xr_session_state_nav_scale_set(xr, nav_scale);
487  }
488  }
489 }
490 
491 static void wm_xr_navigation_grab_bimanual_state_update(const wmXrActionData *actiondata,
492  XrGrabData *data)
493 {
494  if (actiondata->bimanual) {
495  if (!data->bimanual_prev) {
496  quat_to_mat4(data->mat_prev, actiondata->controller_rot);
497  copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
498  quat_to_mat4(data->mat_other_prev, actiondata->controller_rot_other);
499  copy_v3_v3(data->mat_other_prev[3], actiondata->controller_loc_other);
500  }
501  data->bimanual_prev = true;
502  }
503  else {
504  if (data->bimanual_prev) {
505  quat_to_mat4(data->mat_prev, actiondata->controller_rot);
506  copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
507  }
508  data->bimanual_prev = false;
509  }
510 }
511 
512 static int wm_xr_navigation_grab_modal(bContext *C, wmOperator *op, const wmEvent *event)
513 {
514  if (!wm_xr_operator_test_event(op, event)) {
515  return OPERATOR_PASS_THROUGH;
516  }
517 
518  const wmXrActionData *actiondata = event->customdata;
519  XrGrabData *data = op->customdata;
521  wmXrData *xr = &wm->xr;
522 
523  const bool do_bimanual = wm_xr_navigation_grab_can_do_bimanual(actiondata, data);
524 
525  data->loc_lock = RNA_boolean_get(op->ptr, "lock_location");
526  data->locz_lock = RNA_boolean_get(op->ptr, "lock_location_z");
527  data->rot_lock = RNA_boolean_get(op->ptr, "lock_rotation");
528  data->rotz_lock = RNA_boolean_get(op->ptr, "lock_rotation_z");
529  data->scale_lock = RNA_boolean_get(op->ptr, "lock_scale");
530 
531  /* Check if navigation is locked. */
532  if (!wm_xr_navigation_grab_is_locked(data, do_bimanual)) {
533  /* Prevent unwanted snapping (i.e. "jumpy" navigation changes when transitioning from
534  * two-handed to one-handed interaction) at the end of a bimanual interaction. */
536  wm_xr_navigation_grab_apply(xr, actiondata, data, do_bimanual);
537  }
538  }
539 
541 
542  /* NOTE: #KM_PRESS and #KM_RELEASE are the only two values supported by XR events during event
543  * dispatching (see #wm_xr_session_action_states_interpret()). For modal XR operators, modal
544  * handling starts when an input is "pressed" (action state exceeds the action threshold) and
545  * ends when the input is "released" (state falls below the threshold). */
546  switch (event->val) {
547  case KM_PRESS:
548  return OPERATOR_RUNNING_MODAL;
549  case KM_RELEASE:
550  wm_xr_grab_uninit(op);
551  return OPERATOR_FINISHED;
552  default:
554  wm_xr_grab_uninit(op);
555  return OPERATOR_CANCELLED;
556  }
557 }
558 
560 {
561  /* identifiers */
562  ot->name = "XR Navigation Grab";
563  ot->idname = "WM_OT_xr_navigation_grab";
564  ot->description = "Navigate the VR scene by grabbing with controllers";
565 
566  /* callbacks */
571 
572  /* properties */
574  ot->srna, "lock_location", false, "Lock Location", "Prevent changes to viewer location");
576  ot->srna, "lock_location_z", false, "Lock Elevation", "Prevent changes to viewer elevation");
578  ot->srna, "lock_rotation", false, "Lock Rotation", "Prevent changes to viewer rotation");
580  "lock_rotation_z",
581  false,
582  "Lock Up Orientation",
583  "Prevent changes to viewer up orientation");
584  RNA_def_boolean(ot->srna, "lock_scale", false, "Lock Scale", "Prevent changes to viewer scale");
585 }
586 
589 /* -------------------------------------------------------------------- */
593 static const float g_xr_default_raycast_axis[3] = {0.0f, 0.0f, -1.0f};
594 static const float g_xr_default_raycast_color[4] = {0.35f, 0.35f, 1.0f, 1.0f};
595 
596 typedef struct XrRaycastData {
598  float origin[3];
599  float direction[3];
600  float end[3];
601  float color[4];
602  void *draw_handle;
604 
605 static void wm_xr_raycast_draw(const bContext *UNUSED(C),
606  ARegion *UNUSED(region),
607  void *customdata)
608 {
609  const XrRaycastData *data = customdata;
610 
613 
614  if (data->from_viewer) {
616  immUniformColor4fv(data->color);
617 
619  GPU_point_size(7.0f);
620 
622  immVertex3fv(pos, data->end);
623  immEnd();
624  }
625  else {
628 
629  float viewport[4];
630  GPU_viewport_size_get_f(viewport);
631  immUniform2fv("viewportSize", &viewport[2]);
632 
633  immUniform1f("lineWidth", 3.0f * U.pixelsize);
634 
636 
638  immAttrSkip(col);
639  immVertex3fv(pos, data->origin);
640  immAttr4fv(col, data->color);
641  immVertex3fv(pos, data->end);
642  immEnd();
643  }
644 
646 }
647 
649 {
650  BLI_assert(op->customdata == NULL);
651 
652  op->customdata = MEM_callocN(sizeof(XrRaycastData), __func__);
653 
655  if (!st) {
656  return;
657  }
658 
660  if (!art) {
661  return;
662  }
663 
665  data->draw_handle = ED_region_draw_cb_activate(
667 }
668 
670 {
671  if (!op->customdata) {
672  return;
673  }
674 
676  if (st) {
678  if (art) {
680  ED_region_draw_cb_exit(art, data->draw_handle);
681  }
682  }
683 
684  MEM_freeN(op->customdata);
685 }
686 
688  const wmXrData *xr,
689  const wmXrActionData *actiondata)
690 {
692  float ray_length, axis[3];
693 
694  data->from_viewer = RNA_boolean_get(op->ptr, "from_viewer");
695  RNA_float_get_array(op->ptr, "axis", axis);
696  RNA_float_get_array(op->ptr, "color", data->color);
697 
698  if (data->from_viewer) {
699  float viewer_rot[4];
702  mul_qt_v3(viewer_rot, axis);
703  ray_length = (xr->session_settings.clip_start + xr->session_settings.clip_end) / 2.0f;
704  }
705  else {
706  copy_v3_v3(data->origin, actiondata->controller_loc);
707  mul_qt_v3(actiondata->controller_rot, axis);
708  ray_length = xr->session_settings.clip_end;
709  }
710 
711  copy_v3_v3(data->direction, axis);
712  madd_v3_v3v3fl(data->end, data->origin, data->direction, ray_length);
713 }
714 
715 static void wm_xr_raycast(Scene *scene,
717  const float origin[3],
718  const float direction[3],
719  float *ray_dist,
720  bool selectable_only,
721  float r_location[3],
722  float r_normal[3],
723  int *r_index,
724  Object **r_ob,
725  float r_obmat[4][4])
726 {
727  /* Uses same raycast method as Scene.ray_cast(). */
729 
731  sctx,
732  depsgraph,
733  NULL,
734  &(const struct SnapObjectParams){.snap_target_select = (selectable_only ?
737  origin,
738  direction,
739  ray_dist,
740  r_location,
741  r_normal,
742  r_index,
743  r_ob,
744  r_obmat);
745 
747 }
748 
751 /* -------------------------------------------------------------------- */
758 #define XR_DEFAULT_FLY_SPEED_MOVE 0.054f
759 #define XR_DEFAULT_FLY_SPEED_TURN 0.03f
760 
761 typedef enum eXrFlyMode {
776 
777 typedef struct XrFlyData {
778  float viewer_rot[4];
779  double time_prev;
781 
782 static void wm_xr_fly_init(wmOperator *op, const wmXrData *xr)
783 {
784  BLI_assert(op->customdata == NULL);
785 
786  XrFlyData *data = op->customdata = MEM_callocN(sizeof(XrFlyData), __func__);
787 
789  data->time_prev = PIL_check_seconds_timer();
790 }
791 
792 static void wm_xr_fly_uninit(wmOperator *op)
793 {
795 }
796 
798  float speed,
799  const float ref_quat[4],
800  const float nav_mat[4][4],
801  bool locz_lock,
802  float r_delta[4][4])
803 {
804  float ref_axes[3][3];
805  quat_to_mat3(ref_axes, ref_quat);
806 
807  unit_m4(r_delta);
808 
809  switch (mode) {
810  /* Navigation space reference. */
811  case XR_FLY_FORWARD:
812  madd_v3_v3fl(r_delta[3], ref_axes[1], speed);
813  return;
814  case XR_FLY_BACK:
815  madd_v3_v3fl(r_delta[3], ref_axes[1], -speed);
816  return;
817  case XR_FLY_LEFT:
818  madd_v3_v3fl(r_delta[3], ref_axes[0], -speed);
819  return;
820  case XR_FLY_RIGHT:
821  madd_v3_v3fl(r_delta[3], ref_axes[0], speed);
822  return;
823  case XR_FLY_UP:
824  case XR_FLY_DOWN:
825  if (!locz_lock) {
826  madd_v3_v3fl(r_delta[3], ref_axes[2], (mode == XR_FLY_UP) ? speed : -speed);
827  }
828  return;
829  /* Viewer/controller space reference. */
832  negate_v3_v3(r_delta[3], ref_axes[2]);
833  break;
834  case XR_FLY_VIEWER_BACK:
835  copy_v3_v3(r_delta[3], ref_axes[2]);
836  break;
837  case XR_FLY_VIEWER_LEFT:
838  negate_v3_v3(r_delta[3], ref_axes[0]);
839  break;
840  case XR_FLY_VIEWER_RIGHT:
841  copy_v3_v3(r_delta[3], ref_axes[0]);
842  break;
843  /* Unused. */
844  case XR_FLY_TURNLEFT:
845  case XR_FLY_TURNRIGHT:
847  return;
848  }
849 
850  if (locz_lock) {
851  /* Lock elevation in navigation space. */
852  float z_axis[3], projected[3];
853 
854  normalize_v3_v3(z_axis, nav_mat[2]);
855  project_v3_v3v3_normalized(projected, r_delta[3], z_axis);
856  sub_v3_v3(r_delta[3], projected);
857 
858  normalize_v3(r_delta[3]);
859  }
860 
861  mul_v3_fl(r_delta[3], speed);
862 }
863 
865  float speed,
866  const float viewer_mat[4][4],
867  const float nav_mat[4][4],
868  const float nav_inv[4][4],
869  float r_delta[4][4])
870 {
872 
873  float z_axis[3], m[3][3], prev[4][4], curr[4][4];
874 
875  /* Turn around Z-axis in navigation space. */
876  normalize_v3_v3(z_axis, nav_mat[2]);
877  axis_angle_normalized_to_mat3(m, z_axis, (mode == XR_FLY_TURNLEFT) ? speed : -speed);
878  copy_m4_m3(r_delta, m);
879 
880  copy_m4_m4(prev, viewer_mat);
881  mul_m4_m4m4(curr, r_delta, viewer_mat);
882 
883  /* Lock location in base pose space. */
884  wm_xr_navlocks_apply(nav_mat, nav_inv, true, false, false, prev, curr);
885 
886  invert_m4(prev);
887  mul_m4_m4m4(r_delta, curr, prev);
888 }
889 
890 static void wm_xr_basenav_rotation_calc(const wmXrData *xr,
891  const float nav_rotation[4],
892  float r_rotation[4])
893 {
894  /* Apply nav rotation to base pose Z-rotation. */
895  float base_eul[3], base_quatz[4];
896  quat_to_eul(base_eul, xr->runtime->session_state.prev_base_pose.orientation_quat);
897  axis_angle_to_quat_single(base_quatz, 'Z', base_eul[2]);
898  mul_qt_qtqt(r_rotation, nav_rotation, base_quatz);
899 }
900 
901 static int wm_xr_navigation_fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
902 {
903  if (!wm_xr_operator_test_event(op, event)) {
904  return OPERATOR_PASS_THROUGH;
905  }
906 
908 
909  wm_xr_fly_init(op, &wm->xr);
910 
912 
913  return OPERATOR_RUNNING_MODAL;
914 }
915 
917 {
918  return OPERATOR_CANCELLED;
919 }
920 
921 static int wm_xr_navigation_fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
922 {
923  if (!wm_xr_operator_test_event(op, event)) {
924  return OPERATOR_PASS_THROUGH;
925  }
926 
927  if (event->val == KM_RELEASE) {
928  wm_xr_fly_uninit(op);
929  return OPERATOR_FINISHED;
930  }
931 
932  const wmXrActionData *actiondata = event->customdata;
933  XrFlyData *data = op->customdata;
935  wmXrData *xr = &wm->xr;
936  eXrFlyMode mode;
937  bool turn, locz_lock, dir_lock, speed_frame_based;
938  bool speed_interp_cubic = false;
939  float speed, speed_max, speed_p0[2], speed_p1[2];
940  GHOST_XrPose nav_pose;
941  float nav_mat[4][4], delta[4][4], out[4][4];
942 
943  const double time_now = PIL_check_seconds_timer();
944 
945  mode = (eXrFlyMode)RNA_enum_get(op->ptr, "mode");
946  turn = (ELEM(mode, XR_FLY_TURNLEFT, XR_FLY_TURNRIGHT));
947 
948  locz_lock = RNA_boolean_get(op->ptr, "lock_location_z");
949  dir_lock = RNA_boolean_get(op->ptr, "lock_direction");
950  speed_frame_based = RNA_boolean_get(op->ptr, "speed_frame_based");
951  speed = RNA_float_get(op->ptr, "speed_min");
952  speed_max = RNA_float_get(op->ptr, "speed_max");
953 
954  PropertyRNA *prop = RNA_struct_find_property(op->ptr, "speed_interpolation0");
955  if (prop && RNA_property_is_set(op->ptr, prop)) {
956  RNA_property_float_get_array(op->ptr, prop, speed_p0);
957  speed_interp_cubic = true;
958  }
959  else {
960  speed_p0[0] = speed_p0[1] = 0.0f;
961  }
962 
963  prop = RNA_struct_find_property(op->ptr, "speed_interpolation1");
964  if (prop && RNA_property_is_set(op->ptr, prop)) {
965  RNA_property_float_get_array(op->ptr, prop, speed_p1);
966  speed_interp_cubic = true;
967  }
968  else {
969  speed_p1[0] = speed_p1[1] = 1.0f;
970  }
971 
972  /* Ensure valid interpolation. */
973  if (speed_max < speed) {
974  speed_max = speed;
975  }
976 
977  /* Interpolate between min/max speeds based on button state. */
978  switch (actiondata->type) {
979  case XR_BOOLEAN_INPUT:
980  speed = speed_max;
981  break;
982  case XR_FLOAT_INPUT:
983  case XR_VECTOR2F_INPUT: {
984  float state = (actiondata->type == XR_FLOAT_INPUT) ? fabsf(actiondata->state[0]) :
985  len_v2(actiondata->state);
986  float speed_t = (actiondata->float_threshold < 1.0f) ?
987  (state - actiondata->float_threshold) /
988  (1.0f - actiondata->float_threshold) :
989  1.0f;
990  if (speed_interp_cubic) {
991  float start[2], end[2], p[2];
992 
993  start[0] = 0.0f;
994  start[1] = speed;
995  speed_p0[1] = speed + speed_p0[1] * (speed_max - speed);
996  speed_p1[1] = speed + speed_p1[1] * (speed_max - speed);
997  end[0] = 1.0f;
998  end[1] = speed_max;
999 
1000  interp_v2_v2v2v2v2_cubic(p, start, speed_p0, speed_p1, end, speed_t);
1001  speed = p[1];
1002  }
1003  else {
1004  speed += speed_t * (speed_max - speed);
1005  }
1006  break;
1007  }
1008  case XR_POSE_INPUT:
1009  case XR_VIBRATION_OUTPUT:
1011  break;
1012  }
1013 
1014  if (!speed_frame_based) {
1015  /* Adjust speed based on last update time. */
1016  speed *= time_now - data->time_prev;
1017  }
1018  data->time_prev = time_now;
1019 
1020  WM_xr_session_state_nav_location_get(xr, nav_pose.position);
1021  WM_xr_session_state_nav_rotation_get(xr, nav_pose.orientation_quat);
1022  wm_xr_pose_to_mat(&nav_pose, nav_mat);
1023 
1024  if (turn) {
1025  if (dir_lock) {
1026  unit_m4(delta);
1027  }
1028  else {
1029  GHOST_XrPose viewer_pose;
1030  float viewer_mat[4][4], nav_inv[4][4];
1031 
1032  WM_xr_session_state_viewer_pose_location_get(xr, viewer_pose.position);
1033  WM_xr_session_state_viewer_pose_rotation_get(xr, viewer_pose.orientation_quat);
1034  wm_xr_pose_to_mat(&viewer_pose, viewer_mat);
1035  wm_xr_pose_to_imat(&nav_pose, nav_inv);
1036 
1037  wm_xr_fly_compute_turn(mode, speed, viewer_mat, nav_mat, nav_inv, delta);
1038  }
1039  }
1040  else {
1041  float nav_scale, ref_quat[4];
1042 
1043  /* Adjust speed for base and navigation scale. */
1044  WM_xr_session_state_nav_scale_get(xr, &nav_scale);
1045  speed *= xr->session_settings.base_scale * nav_scale;
1046 
1047  switch (mode) {
1048  /* Move relative to navigation space. */
1049  case XR_FLY_FORWARD:
1050  case XR_FLY_BACK:
1051  case XR_FLY_LEFT:
1052  case XR_FLY_RIGHT:
1053  case XR_FLY_UP:
1054  case XR_FLY_DOWN:
1055  wm_xr_basenav_rotation_calc(xr, nav_pose.orientation_quat, ref_quat);
1056  break;
1057  /* Move relative to viewer. */
1058  case XR_FLY_VIEWER_FORWARD:
1059  case XR_FLY_VIEWER_BACK:
1060  case XR_FLY_VIEWER_LEFT:
1061  case XR_FLY_VIEWER_RIGHT:
1062  if (dir_lock) {
1063  copy_qt_qt(ref_quat, data->viewer_rot);
1064  }
1065  else {
1067  }
1068  break;
1069  /* Move relative to controller. */
1071  copy_qt_qt(ref_quat, actiondata->controller_rot);
1072  break;
1073  /* Unused. */
1074  case XR_FLY_TURNLEFT:
1075  case XR_FLY_TURNRIGHT:
1077  break;
1078  }
1079 
1080  wm_xr_fly_compute_move(mode, speed, ref_quat, nav_mat, locz_lock, delta);
1081  }
1082 
1083  mul_m4_m4m4(out, delta, nav_mat);
1084 
1086  if (turn) {
1087  mat4_to_quat(nav_pose.orientation_quat, out);
1088  WM_xr_session_state_nav_rotation_set(xr, nav_pose.orientation_quat);
1089  }
1090 
1091  if (event->val == KM_PRESS) {
1092  return OPERATOR_RUNNING_MODAL;
1093  }
1094 
1095  /* XR events currently only support press and release. */
1097  wm_xr_fly_uninit(op);
1098  return OPERATOR_CANCELLED;
1099 }
1100 
1102 {
1103  /* identifiers */
1104  ot->name = "XR Navigation Fly";
1105  ot->idname = "WM_OT_xr_navigation_fly";
1106  ot->description = "Move/turn relative to the VR viewer or controller";
1107 
1108  /* callbacks */
1113 
1114  /* properties */
1115  static const EnumPropertyItem fly_modes[] = {
1116  {XR_FLY_FORWARD, "FORWARD", 0, "Forward", "Move along navigation forward axis"},
1117  {XR_FLY_BACK, "BACK", 0, "Back", "Move along navigation back axis"},
1118  {XR_FLY_LEFT, "LEFT", 0, "Left", "Move along navigation left axis"},
1119  {XR_FLY_RIGHT, "RIGHT", 0, "Right", "Move along navigation right axis"},
1120  {XR_FLY_UP, "UP", 0, "Up", "Move along navigation up axis"},
1121  {XR_FLY_DOWN, "DOWN", 0, "Down", "Move along navigation down axis"},
1122  {XR_FLY_TURNLEFT,
1123  "TURNLEFT",
1124  0,
1125  "Turn Left",
1126  "Turn counter-clockwise around navigation up axis"},
1127  {XR_FLY_TURNRIGHT, "TURNRIGHT", 0, "Turn Right", "Turn clockwise around navigation up axis"},
1129  "VIEWER_FORWARD",
1130  0,
1131  "Viewer Forward",
1132  "Move along viewer's forward axis"},
1133  {XR_FLY_VIEWER_BACK, "VIEWER_BACK", 0, "Viewer Back", "Move along viewer's back axis"},
1134  {XR_FLY_VIEWER_LEFT, "VIEWER_LEFT", 0, "Viewer Left", "Move along viewer's left axis"},
1135  {XR_FLY_VIEWER_RIGHT, "VIEWER_RIGHT", 0, "Viewer Right", "Move along viewer's right axis"},
1137  "CONTROLLER_FORWARD",
1138  0,
1139  "Controller Forward",
1140  "Move along controller's forward axis"},
1141  {0, NULL, 0, NULL, NULL},
1142  };
1143 
1144  static const float default_speed_p0[2] = {0.0f, 0.0f};
1145  static const float default_speed_p1[2] = {1.0f, 1.0f};
1146 
1147  RNA_def_enum(ot->srna, "mode", fly_modes, XR_FLY_VIEWER_FORWARD, "Mode", "Fly mode");
1149  ot->srna, "lock_location_z", false, "Lock Elevation", "Prevent changes to viewer elevation");
1151  "lock_direction",
1152  false,
1153  "Lock Direction",
1154  "Limit movement to viewer's initial direction");
1156  "speed_frame_based",
1157  true,
1158  "Frame Based Speed",
1159  "Apply fixed movement deltas every update");
1161  "speed_min",
1163  0.0f,
1164  1000.0f,
1165  "Minimum Speed",
1166  "Minimum move (turn) speed in meters (radians) per second or frame",
1167  0.0f,
1168  1000.0f);
1170  "speed_max",
1172  0.0f,
1173  1000.0f,
1174  "Maximum Speed",
1175  "Maximum move (turn) speed in meters (radians) per second or frame",
1176  0.0f,
1177  1000.0f);
1179  "speed_interpolation0",
1180  2,
1181  default_speed_p0,
1182  0.0f,
1183  1.0f,
1184  "Speed Interpolation 0",
1185  "First cubic spline control point between min/max speeds",
1186  0.0f,
1187  1.0f);
1189  "speed_interpolation1",
1190  2,
1191  default_speed_p1,
1192  0.0f,
1193  1.0f,
1194  "Speed Interpolation 1",
1195  "Second cubic spline control point between min/max speeds",
1196  0.0f,
1197  1.0f);
1198 }
1199 
1202 /* -------------------------------------------------------------------- */
1209  wmXrData *xr,
1210  const float origin[3],
1211  const float direction[3],
1212  float *ray_dist,
1213  bool selectable_only,
1214  const bool teleport_axes[3],
1215  float teleport_t,
1216  float teleport_ofs)
1217 {
1220  float location[3];
1221  float normal[3];
1222  int index;
1223  Object *ob = NULL;
1224  float obmat[4][4];
1225 
1227  depsgraph,
1228  origin,
1229  direction,
1230  ray_dist,
1231  selectable_only,
1232  location,
1233  normal,
1234  &index,
1235  &ob,
1236  obmat);
1237 
1238  /* Teleport. */
1239  if (ob) {
1240  float nav_location[3], nav_rotation[4], viewer_location[3];
1241  float nav_axes[3][3], projected[3], v0[3], v1[3];
1242  float out[3] = {0.0f, 0.0f, 0.0f};
1243 
1244  WM_xr_session_state_nav_location_get(xr, nav_location);
1245  WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
1246  WM_xr_session_state_viewer_pose_location_get(xr, viewer_location);
1247 
1248  wm_xr_basenav_rotation_calc(xr, nav_rotation, nav_rotation);
1249  quat_to_mat3(nav_axes, nav_rotation);
1250 
1251  /* Project locations onto navigation axes. */
1252  for (int a = 0; a < 3; ++a) {
1253  project_v3_v3v3_normalized(projected, nav_location, nav_axes[a]);
1254  if (teleport_axes[a]) {
1255  /* Interpolate between projected locations. */
1256  project_v3_v3v3_normalized(v0, location, nav_axes[a]);
1257  project_v3_v3v3_normalized(v1, viewer_location, nav_axes[a]);
1258  sub_v3_v3(v0, v1);
1259  madd_v3_v3fl(projected, v0, teleport_t);
1260  /* Subtract offset. */
1261  project_v3_v3v3_normalized(v0, normal, nav_axes[a]);
1262  madd_v3_v3fl(projected, v0, teleport_ofs);
1263  }
1264  /* Add to final location. */
1265  add_v3_v3(out, projected);
1266  }
1267 
1269  }
1270 }
1271 
1273 {
1274  if (!wm_xr_operator_test_event(op, event)) {
1275  return OPERATOR_PASS_THROUGH;
1276  }
1277 
1278  wm_xr_raycast_init(op);
1279 
1280  int retval = op->type->modal(C, op, event);
1281 
1282  if ((retval & OPERATOR_RUNNING_MODAL) != 0) {
1284  }
1285 
1286  return retval;
1287 }
1288 
1290 {
1291  return OPERATOR_CANCELLED;
1292 }
1293 
1295 {
1296  if (!wm_xr_operator_test_event(op, event)) {
1297  return OPERATOR_PASS_THROUGH;
1298  }
1299 
1300  const wmXrActionData *actiondata = event->customdata;
1302  wmXrData *xr = &wm->xr;
1303 
1304  wm_xr_raycast_update(op, xr, actiondata);
1305 
1306  switch (event->val) {
1307  case KM_PRESS:
1308  return OPERATOR_RUNNING_MODAL;
1309  case KM_RELEASE: {
1310  XrRaycastData *data = op->customdata;
1311  bool selectable_only, teleport_axes[3];
1312  float teleport_t, teleport_ofs, ray_dist;
1313 
1314  RNA_boolean_get_array(op->ptr, "teleport_axes", teleport_axes);
1315  teleport_t = RNA_float_get(op->ptr, "interpolation");
1316  teleport_ofs = RNA_float_get(op->ptr, "offset");
1317  selectable_only = RNA_boolean_get(op->ptr, "selectable_only");
1318  ray_dist = RNA_float_get(op->ptr, "distance");
1319 
1321  xr,
1322  data->origin,
1323  data->direction,
1324  &ray_dist,
1325  selectable_only,
1326  teleport_axes,
1327  teleport_t,
1328  teleport_ofs);
1329 
1331 
1332  return OPERATOR_FINISHED;
1333  }
1334  default:
1335  /* XR events currently only support press and release. */
1338  return OPERATOR_CANCELLED;
1339  }
1340 }
1341 
1343 {
1344  /* identifiers */
1345  ot->name = "XR Navigation Teleport";
1346  ot->idname = "WM_OT_xr_navigation_teleport";
1347  ot->description = "Set VR viewer location to controller raycast hit location";
1348 
1349  /* callbacks */
1354 
1355  /* properties */
1356  static bool default_teleport_axes[3] = {true, true, true};
1357 
1359  "teleport_axes",
1360  3,
1361  default_teleport_axes,
1362  "Teleport Axes",
1363  "Enabled teleport axes in navigation space");
1365  "interpolation",
1366  1.0f,
1367  0.0f,
1368  1.0f,
1369  "Interpolation",
1370  "Interpolation factor between viewer and hit locations",
1371  0.0f,
1372  1.0f);
1374  "offset",
1375  0.0f,
1376  0.0f,
1377  FLT_MAX,
1378  "Offset",
1379  "Offset along hit normal to subtract from final location",
1380  0.0f,
1381  FLT_MAX);
1383  "selectable_only",
1384  true,
1385  "Selectable Only",
1386  "Only allow selectable objects to influence raycast result");
1388  "distance",
1390  0.0,
1392  "",
1393  "Maximum raycast distance",
1394  0.0,
1397  ot->srna, "from_viewer", false, "From Viewer", "Use viewer pose as raycast origin");
1399  "axis",
1400  3,
1402  -1.0f,
1403  1.0f,
1404  "Axis",
1405  "Raycast axis in controller/viewer space",
1406  -1.0f,
1407  1.0f);
1409  "color",
1410  4,
1412  0.0f,
1413  1.0f,
1414  "Color",
1415  "Raycast color",
1416  0.0f,
1417  1.0f);
1418 }
1419 
1422 /* -------------------------------------------------------------------- */
1429 {
1431  wmXrData *xr = &wm->xr;
1432  bool reset_loc, reset_rot, reset_scale;
1433 
1434  reset_loc = RNA_boolean_get(op->ptr, "location");
1435  reset_rot = RNA_boolean_get(op->ptr, "rotation");
1436  reset_scale = RNA_boolean_get(op->ptr, "scale");
1437 
1438  if (reset_loc) {
1439  float loc[3];
1440  if (!reset_scale) {
1441  float nav_rotation[4], nav_scale;
1442 
1443  WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
1444  WM_xr_session_state_nav_scale_get(xr, &nav_scale);
1445 
1446  /* Adjust location based on scale. */
1447  mul_v3_v3fl(loc, xr->runtime->session_state.prev_base_pose.position, nav_scale);
1448  sub_v3_v3(loc, xr->runtime->session_state.prev_base_pose.position);
1449  mul_qt_v3(nav_rotation, loc);
1450  negate_v3(loc);
1451  }
1452  else {
1453  zero_v3(loc);
1454  }
1456  }
1457 
1458  if (reset_rot) {
1459  float rot[4];
1460  unit_qt(rot);
1462  }
1463 
1464  if (reset_scale) {
1465  if (!reset_loc) {
1466  float nav_location[3], nav_rotation[4], nav_scale;
1467  float nav_axes[3][3], v[3];
1468 
1469  WM_xr_session_state_nav_location_get(xr, nav_location);
1470  WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
1471  WM_xr_session_state_nav_scale_get(xr, &nav_scale);
1472 
1473  /* Offset any location changes when changing scale. */
1474  mul_v3_v3fl(v, xr->runtime->session_state.prev_base_pose.position, nav_scale);
1476  mul_qt_v3(nav_rotation, v);
1477  add_v3_v3(nav_location, v);
1478 
1479  /* Reset elevation to base pose value. */
1480  quat_to_mat3(nav_axes, nav_rotation);
1481  project_v3_v3v3_normalized(v, nav_location, nav_axes[2]);
1482  sub_v3_v3(nav_location, v);
1483 
1484  WM_xr_session_state_nav_location_set(xr, nav_location);
1485  }
1487  }
1488 
1489  return OPERATOR_FINISHED;
1490 }
1491 
1493 {
1494  /* identifiers */
1495  ot->name = "XR Navigation Reset";
1496  ot->idname = "WM_OT_xr_navigation_reset";
1497  ot->description = "Reset VR navigation deltas relative to session base pose";
1498 
1499  /* callbacks */
1502 
1503  /* properties */
1504  RNA_def_boolean(ot->srna, "location", true, "Location", "Reset location deltas");
1505  RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "Reset rotation deltas");
1506  RNA_def_boolean(ot->srna, "scale", true, "Scale", "Reset scale deltas");
1507 }
1508 
1511 /* -------------------------------------------------------------------- */
1516 {
1522 }
1523 
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
#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 SpaceType * BKE_spacetype_from_id(int spaceid)
Definition: screen.c:353
struct ARegionType * BKE_regiontype_from_id(const struct SpaceType *st, int regionid)
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BVH_RAYCAST_DIST_MAX
Definition: BLI_kdopbvh.h:89
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1206
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
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 mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:59
void unit_qt(float q[4])
Definition: math_rotation.c:27
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
void mat4_to_quat(float q[4], const float mat[4][4])
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
void quat_to_mat3(float mat[3][3], const float q[4])
void quat_to_mat4(float mat[4][4], const float q[4])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
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)
Definition: math_vector.c:139
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])
Definition: math_vector.c:630
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 float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
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 len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ SCE_SNAP_TARGET_ONLY_SELECTABLE
@ SCE_SNAP_TARGET_ALL
@ RGN_TYPE_XR
@ SPACE_VIEW3D
@ V3D_RUNTIME_XR_SESSION_ROOT
#define V3D_XR_SESSION_MIRROR
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ 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
bool ED_operator_view3d_active(struct bContext *C)
Definition: screen_ops.c:225
#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
SnapObjectContext * ED_transform_snap_object_context_create(struct Scene *scene, int flag)
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
bool ED_transform_snap_object_project_ray_ex(struct SnapObjectContext *sctx, struct Depsgraph *depsgraph, const View3D *v3d, const struct SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float *ray_depth, float r_loc[3], float r_no[3], int *r_index, struct Object **r_ob, float r_obmat[4][4])
void immUniform2fv(const char *name, const float data[2])
void immAttr4fv(uint attr_id, const float data[4])
void immAttrSkip(uint attr_id)
void immUnbindProgram(void)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniform1f(const char *name, float x)
void immUniformColor4fv(const float rgba[4])
GPUVertFormat * immVertexFormat(void)
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:19
@ GPU_SHADER_3D_UNIFORM_COLOR
Definition: GPU_shader.h:230
@ GPU_SHADER_3D_POLYLINE_FLAT_COLOR
Definition: GPU_shader.h:262
void GPU_point_size(float size)
Definition: gpu_state.cc:164
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:86
@ GPU_DEPTH_NONE
Definition: GPU_state.h:83
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:65
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:259
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Platform independent time functions.
#define C
Definition: RandGen.cpp:25
@ KM_PRESS
Definition: WM_types.h:267
@ KM_RELEASE
Definition: WM_types.h:268
@ OPTYPE_INTERNAL
Definition: WM_types.h:168
#define NC_WM
Definition: WM_types.h:324
#define ND_XR_DATA_CHANGED
Definition: WM_types.h:366
ATTR_WARN_UNUSED_RESULT const BMVert * v
unsigned int U
Definition: btGjkEpa3.h:78
Scene scene
const Depsgraph * depsgraph
#define rot(x, k)
uint pos
uint col
IconTextureDrawCall normal
const int state
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define R
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
static const pxr::TfToken st("st", pxr::TfToken::Immortal)
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:2879
void RNA_boolean_get_array(PointerRNA *ptr, const char *name, bool *values)
Definition: rna_access.c:4886
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
Definition: rna_access.c:4980
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3836
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
PropertyRNA * RNA_def_float_vector(StructOrFunctionRNA *cont_, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3862
PropertyRNA * RNA_def_boolean_vector(StructOrFunctionRNA *cont_, const char *identifier, int len, bool *default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3575
PropertyRNA * RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3922
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase wm
Definition: BKE_main.h:197
ListBase screens
Definition: BKE_main.h:183
View3D_Runtime runtime
float viewer_rot[4]
double time_prev
float mat_other_prev[4][4]
float mat_prev[4][4]
float direction[3]
short custom
Definition: WM_types.h:712
short val
Definition: WM_types.h:680
short type
Definition: WM_types.h:678
void * customdata
Definition: WM_types.h:715
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
IDProperty * properties
struct wmOperatorType * type
struct PointerRNA * ptr
XrSessionSettings session_settings
struct wmXrRuntimeData * runtime
wmXrSessionState session_state
Definition: wm_xr_intern.h:75
GHOST_XrPose prev_base_pose
Definition: wm_xr_intern.h:33
double PIL_check_seconds_timer(void)
Definition: time.c:64
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ EVT_XR_ACTION
@ EVT_DATA_XR
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
Scene * WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen *screen)
Definition: wm_window.c:2151
bool wm_xr_init(wmWindowManager *wm)
Definition: wm_xr.c:55
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_pose_scale_to_imat(const GHOST_XrPose *pose, float scale, float r_imat[4][4])
Definition: wm_xr_draw.c:56
void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4])
Definition: wm_xr_draw.c:48
static void orient_mat_z_normalized(float R[4][4], const float z_axis[3])
static void wm_xr_grab_init(wmOperator *op)
void wm_xr_operatortypes_register(void)
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 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, Object **r_ob, float r_obmat[4][4])
static int wm_xr_navigation_teleport_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
static int wm_xr_navigation_grab_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int wm_xr_navigation_fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void wm_xr_raycast_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *customdata)
struct XrGrabData XrGrabData
static void wm_xr_grab_uninit(wmOperator *op)
static void WM_OT_xr_navigation_fly(wmOperatorType *ot)
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 int wm_xr_navigation_reset_exec(bContext *C, wmOperator *op)
static int wm_xr_navigation_fly_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
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 int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
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 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 int wm_xr_navigation_grab_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
static int wm_xr_navigation_teleport_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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)
struct XrFlyData XrFlyData
static void wm_xr_grab_update(wmOperator *op, const wmXrActionData *actiondata)
struct XrRaycastData XrRaycastData
static const float g_xr_default_raycast_color[4]
static int wm_xr_navigation_grab_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void WM_OT_xr_navigation_reset(wmOperatorType *ot)
static const float g_xr_default_raycast_axis[3]
static void WM_OT_xr_navigation_grab(wmOperatorType *ot)
eXrFlyMode
@ XR_FLY_VIEWER_FORWARD
@ XR_FLY_FORWARD
@ XR_FLY_RIGHT
@ XR_FLY_TURNLEFT
@ XR_FLY_CONTROLLER_FORWARD
@ XR_FLY_VIEWER_BACK
@ XR_FLY_VIEWER_RIGHT
@ XR_FLY_BACK
@ XR_FLY_DOWN
@ XR_FLY_UP
@ XR_FLY_TURNRIGHT
@ XR_FLY_LEFT
@ XR_FLY_VIEWER_LEFT
static void wm_xr_raycast_init(wmOperator *op)
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 int wm_xr_navigation_teleport_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int wm_xr_navigation_fly_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])