Blender V4.3
wm_xr_operators.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
13#include "BLI_kdopbvh.h"
14#include "BLI_listbase.h"
15#include "BLI_math_matrix.h"
16#include "BLI_math_rotation.h"
17#include "BLI_math_vector.h"
18#include "BLI_time.h"
19
20#include "BKE_context.hh"
21#include "BKE_global.hh"
22#include "BKE_idprop.hh"
23#include "BKE_main.hh"
24#include "BKE_screen.hh"
25
26#include "DEG_depsgraph.hh"
27
28#include "ED_screen.hh"
29#include "ED_space_api.hh"
31#include "ED_view3d.hh"
32
33#include "GHOST_Types.h"
34
35#include "GPU_immediate.hh"
36
37#include "MEM_guardedalloc.h"
38
39#include "RNA_access.hh"
40#include "RNA_define.hh"
41
42#include "WM_api.hh"
43#include "WM_types.hh"
44
45#include "wm_xr_intern.hh"
46
47/* -------------------------------------------------------------------- */
51/* `op->poll`. */
57
58static bool wm_xr_operator_test_event(const wmOperator *op, const wmEvent *event)
59{
60 if (event->type != EVT_XR_ACTION) {
61 return false;
62 }
63
64 BLI_assert(event->custom == EVT_DATA_XR);
65 BLI_assert(event->customdata);
66
67 wmXrActionData *actiondata = static_cast<wmXrActionData *>(event->customdata);
68 return (actiondata->ot == op->type &&
69 IDP_EqualsProperties(actiondata->op_properties, op->properties));
70}
71
74/* -------------------------------------------------------------------- */
80static void wm_xr_session_update_screen(Main *bmain, const wmXrData *xr_data)
81{
82 const bool session_exists = WM_xr_session_exists(xr_data);
83
84 for (bScreen *screen = static_cast<bScreen *>(bmain->screens.first); screen;
85 screen = static_cast<bScreen *>(screen->id.next))
86 {
87 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
88 LISTBASE_FOREACH (SpaceLink *, slink, &area->spacedata) {
89 if (slink->spacetype == SPACE_VIEW3D) {
90 View3D *v3d = (View3D *)slink;
91
92 if (v3d->flag & V3D_XR_SESSION_MIRROR) {
93 ED_view3d_xr_mirror_update(area, v3d, session_exists);
94 }
95
96 if (session_exists) {
97 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
98 const Scene *scene = WM_windows_scene_get_from_screen(wm, screen);
99
100 ED_view3d_xr_shading_update(wm, v3d, scene);
101 }
102 /* Ensure no 3D View is tagged as session root. */
103 else {
104 v3d->runtime.flag &= ~V3D_RUNTIME_XR_SESSION_ROOT;
105 }
106 }
107 }
108 }
109 }
110
112}
113
115{
116 /* Just use G_MAIN here, storing main isn't reliable enough on file read or exit. */
118}
119
121{
122 Main *bmain = CTX_data_main(C);
124 wmWindow *win = CTX_wm_window(C);
125 View3D *v3d = CTX_wm_view3d(C);
126
127 /* Lazily-create XR context - tries to dynamic-link to the runtime,
128 * reading `active_runtime.json`. */
129 if (wm_xr_init(wm) == false) {
130 return OPERATOR_CANCELLED;
131 }
132
135 wm_xr_session_update_screen(bmain, &wm->xr);
136
138
139 return OPERATOR_FINISHED;
140}
141
143{
144 /* Identifiers. */
145 ot->name = "Toggle VR Session";
146 ot->idname = "WM_OT_xr_session_toggle";
147 ot->description =
148 "Open a view for use with virtual reality headsets, or close it if already "
149 "opened";
150
151 /* Callbacks. */
154
155 /* XXX INTERNAL just to hide it from the search menu by default, an Add-on will expose it in the
156 * UI instead. Not meant as a permanent solution. */
158}
159
162/* -------------------------------------------------------------------- */
172
174{
175 BLI_assert(op->customdata == nullptr);
176
177 op->customdata = MEM_callocN(sizeof(XrGrabData), __func__);
178}
179
181{
183}
184
185static void wm_xr_grab_update(wmOperator *op, const wmXrActionData *actiondata)
186{
187 XrGrabData *data = static_cast<XrGrabData *>(op->customdata);
188
189 quat_to_mat4(data->mat_prev, actiondata->controller_rot);
190 copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
191
192 if (actiondata->bimanual) {
193 quat_to_mat4(data->mat_other_prev, actiondata->controller_rot_other);
194 copy_v3_v3(data->mat_other_prev[3], actiondata->controller_loc_other);
195 data->bimanual_prev = true;
196 }
197 else {
198 data->bimanual_prev = false;
199 }
200}
201
202static void orient_mat_z_normalized(float R[4][4], const float z_axis[3])
203{
204 const float scale = len_v3(R[0]);
205 float x_axis[3], y_axis[3];
206
207 cross_v3_v3v3(y_axis, z_axis, R[0]);
208 normalize_v3(y_axis);
209 mul_v3_v3fl(R[1], y_axis, scale);
210
211 cross_v3_v3v3(x_axis, R[1], z_axis);
212 normalize_v3(x_axis);
213 mul_v3_v3fl(R[0], x_axis, scale);
214
215 mul_v3_v3fl(R[2], z_axis, scale);
216}
217
218static void wm_xr_navlocks_apply(const float nav_mat[4][4],
219 const float nav_inv[4][4],
220 bool loc_lock,
221 bool locz_lock,
222 bool rotz_lock,
223 float r_prev[4][4],
224 float r_curr[4][4])
225{
226 /* Locked in base pose coordinates. */
227 float prev_base[4][4], curr_base[4][4];
228
229 mul_m4_m4m4(prev_base, nav_inv, r_prev);
230 mul_m4_m4m4(curr_base, nav_inv, r_curr);
231
232 if (rotz_lock) {
233 const float z_axis[3] = {0.0f, 0.0f, 1.0f};
234 orient_mat_z_normalized(prev_base, z_axis);
235 orient_mat_z_normalized(curr_base, z_axis);
236 }
237
238 if (loc_lock) {
239 copy_v3_v3(curr_base[3], prev_base[3]);
240 }
241 else if (locz_lock) {
242 curr_base[3][2] = prev_base[3][2];
243 }
244
245 mul_m4_m4m4(r_prev, nav_mat, prev_base);
246 mul_m4_m4m4(r_curr, nav_mat, curr_base);
247}
248
258static void wm_xr_grab_compute(const wmXrActionData *actiondata,
259 const XrGrabData *data,
260 const float nav_mat[4][4],
261 const float nav_inv[4][4],
262 bool reverse,
263 float r_delta[4][4])
264{
265 const bool nav_lock = (nav_mat && nav_inv);
266 float prev[4][4], curr[4][4];
267
268 if (!data->rot_lock) {
269 copy_m4_m4(prev, data->mat_prev);
270 zero_v3(prev[3]);
271 quat_to_mat4(curr, actiondata->controller_rot);
272 }
273 else {
274 unit_m4(prev);
275 unit_m4(curr);
276 }
277
278 if (!data->loc_lock || nav_lock) {
279 copy_v3_v3(prev[3], data->mat_prev[3]);
280 copy_v3_v3(curr[3], actiondata->controller_loc);
281 }
282
283 if (nav_lock) {
285 nav_mat, nav_inv, data->loc_lock, data->locz_lock, data->rotz_lock, prev, curr);
286 }
287
288 if (reverse) {
289 invert_m4(curr);
290 mul_m4_m4m4(r_delta, prev, curr);
291 }
292 else {
293 invert_m4(prev);
294 mul_m4_m4m4(r_delta, curr, prev);
295 }
296}
297
310static void wm_xr_grab_compute_bimanual(const wmXrActionData *actiondata,
311 const XrGrabData *data,
312 const float nav_mat[4][4],
313 const float nav_inv[4][4],
314 bool reverse,
315 float r_delta[4][4])
316{
317 const bool nav_lock = (nav_mat && nav_inv);
318 float prev[4][4], curr[4][4];
319 unit_m4(prev);
320 unit_m4(curr);
321
322 if (!data->rot_lock) {
323 /* Rotation. */
324 float x_axis_prev[3], x_axis_curr[3], y_axis_prev[3], y_axis_curr[3], z_axis_prev[3],
325 z_axis_curr[3];
326 float m0[3][3], m1[3][3];
327 quat_to_mat3(m0, actiondata->controller_rot);
328 quat_to_mat3(m1, actiondata->controller_rot_other);
329
330 /* X-axis is the base line between the two controllers. */
331 sub_v3_v3v3(x_axis_prev, data->mat_prev[3], data->mat_other_prev[3]);
332 sub_v3_v3v3(x_axis_curr, actiondata->controller_loc, actiondata->controller_loc_other);
333 /* Y-axis is the average of the controllers' y-axes. */
334 add_v3_v3v3(y_axis_prev, data->mat_prev[1], data->mat_other_prev[1]);
335 mul_v3_fl(y_axis_prev, 0.5f);
336 add_v3_v3v3(y_axis_curr, m0[1], m1[1]);
337 mul_v3_fl(y_axis_curr, 0.5f);
338 /* Z-axis is the cross product of the two. */
339 cross_v3_v3v3(z_axis_prev, x_axis_prev, y_axis_prev);
340 cross_v3_v3v3(z_axis_curr, x_axis_curr, y_axis_curr);
341 /* Fix the y-axis to be orthogonal. */
342 cross_v3_v3v3(y_axis_prev, z_axis_prev, x_axis_prev);
343 cross_v3_v3v3(y_axis_curr, z_axis_curr, x_axis_curr);
344 /* Normalize. */
345 normalize_v3_v3(prev[0], x_axis_prev);
346 normalize_v3_v3(prev[1], y_axis_prev);
347 normalize_v3_v3(prev[2], z_axis_prev);
348 normalize_v3_v3(curr[0], x_axis_curr);
349 normalize_v3_v3(curr[1], y_axis_curr);
350 normalize_v3_v3(curr[2], z_axis_curr);
351 }
352
353 if (!data->loc_lock || nav_lock) {
354 /* Translation: translation of the averaged controller locations. */
355 add_v3_v3v3(prev[3], data->mat_prev[3], data->mat_other_prev[3]);
356 mul_v3_fl(prev[3], 0.5f);
357 add_v3_v3v3(curr[3], actiondata->controller_loc, actiondata->controller_loc_other);
358 mul_v3_fl(curr[3], 0.5f);
359 }
360
361 if (!data->scale_lock) {
362 /* Scaling: distance between controllers. */
363 float scale, v[3];
364
365 sub_v3_v3v3(v, data->mat_prev[3], data->mat_other_prev[3]);
366 scale = len_v3(v);
367 mul_v3_fl(prev[0], scale);
368 mul_v3_fl(prev[1], scale);
369 mul_v3_fl(prev[2], scale);
370
371 sub_v3_v3v3(v, actiondata->controller_loc, actiondata->controller_loc_other);
372 scale = len_v3(v);
373 mul_v3_fl(curr[0], scale);
374 mul_v3_fl(curr[1], scale);
375 mul_v3_fl(curr[2], scale);
376 }
377
378 if (nav_lock) {
380 nav_mat, nav_inv, data->loc_lock, data->locz_lock, data->rotz_lock, prev, curr);
381 }
382
383 if (reverse) {
384 invert_m4(curr);
385 mul_m4_m4m4(r_delta, prev, curr);
386 }
387 else {
388 invert_m4(prev);
389 mul_m4_m4m4(r_delta, curr, prev);
390 }
391}
392
395/* -------------------------------------------------------------------- */
402{
403 if (!wm_xr_operator_test_event(op, event)) {
405 }
406
407 const wmXrActionData *actiondata = static_cast<const wmXrActionData *>(event->customdata);
408
409 wm_xr_grab_init(op);
410 wm_xr_grab_update(op, actiondata);
411
413
415}
416
417static int wm_xr_navigation_grab_exec(bContext * /*C*/, wmOperator * /*op*/)
418{
419 return OPERATOR_CANCELLED;
420}
421
422static bool wm_xr_navigation_grab_can_do_bimanual(const wmXrActionData *actiondata,
423 const XrGrabData *data)
424{
425 /* Returns true if: 1) Bimanual interaction is currently occurring (i.e. inputs on both
426 * controllers are pressed) and 2) bimanual interaction occurred on the last update. This second
427 * part is needed to avoid "jumpy" navigation changes when transitioning from one-handed to
428 * two-handed interaction (see #wm_xr_grab_compute/compute_bimanual() for how navigation deltas
429 * are calculated). */
430 return (actiondata->bimanual && data->bimanual_prev);
431}
432
433static bool wm_xr_navigation_grab_is_bimanual_ending(const wmXrActionData *actiondata,
434 const XrGrabData *data)
435{
436 return (!actiondata->bimanual && data->bimanual_prev);
437}
438
439static bool wm_xr_navigation_grab_is_locked(const XrGrabData *data, const bool bimanual)
440{
441 if (bimanual) {
442 return data->loc_lock && data->rot_lock && data->scale_lock;
443 }
444 /* Ignore scale lock, as one-handed interaction cannot change navigation scale. */
445 return data->loc_lock && data->rot_lock;
446}
447
449 const wmXrActionData *actiondata,
450 const XrGrabData *data,
451 bool bimanual)
452{
453 GHOST_XrPose nav_pose;
454 float nav_scale;
455 float nav_mat[4][4], nav_inv[4][4], delta[4][4], out[4][4];
456
457 const bool need_navinv = (data->loc_lock || data->locz_lock || data->rotz_lock);
458
459 WM_xr_session_state_nav_location_get(xr, nav_pose.position);
460 WM_xr_session_state_nav_rotation_get(xr, nav_pose.orientation_quat);
461 WM_xr_session_state_nav_scale_get(xr, &nav_scale);
462
463 wm_xr_pose_scale_to_mat(&nav_pose, nav_scale, nav_mat);
464 if (need_navinv) {
465 wm_xr_pose_scale_to_imat(&nav_pose, nav_scale, nav_inv);
466 }
467
468 if (bimanual) {
470 data,
471 need_navinv ? nav_mat : nullptr,
472 need_navinv ? nav_inv : nullptr,
473 true,
474 delta);
475 }
476 else {
477 wm_xr_grab_compute(actiondata,
478 data,
479 need_navinv ? nav_mat : nullptr,
480 need_navinv ? nav_inv : nullptr,
481 true,
482 delta);
483 }
484
485 mul_m4_m4m4(out, delta, nav_mat);
486
487 /* Limit scale to reasonable values. */
488 nav_scale = len_v3(out[0]);
489
490 if (!(nav_scale < xr->session_settings.clip_start || nav_scale > xr->session_settings.clip_end))
491 {
493 if (!data->rot_lock) {
494 mat4_to_quat(nav_pose.orientation_quat, out);
495 normalize_qt(nav_pose.orientation_quat);
496 WM_xr_session_state_nav_rotation_set(xr, nav_pose.orientation_quat);
497 }
498 if (!data->scale_lock && bimanual) {
500 }
501 }
502}
503
504static void wm_xr_navigation_grab_bimanual_state_update(const wmXrActionData *actiondata,
505 XrGrabData *data)
506{
507 if (actiondata->bimanual) {
508 if (!data->bimanual_prev) {
509 quat_to_mat4(data->mat_prev, actiondata->controller_rot);
510 copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
511 quat_to_mat4(data->mat_other_prev, actiondata->controller_rot_other);
512 copy_v3_v3(data->mat_other_prev[3], actiondata->controller_loc_other);
513 }
514 data->bimanual_prev = true;
515 }
516 else {
517 if (data->bimanual_prev) {
518 quat_to_mat4(data->mat_prev, actiondata->controller_rot);
519 copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
520 }
521 data->bimanual_prev = false;
522 }
523}
524
526{
527 if (!wm_xr_operator_test_event(op, event)) {
529 }
530
531 const wmXrActionData *actiondata = static_cast<const wmXrActionData *>(event->customdata);
532 XrGrabData *data = static_cast<XrGrabData *>(op->customdata);
534 wmXrData *xr = &wm->xr;
535
536 const bool do_bimanual = wm_xr_navigation_grab_can_do_bimanual(actiondata, data);
537
538 data->loc_lock = RNA_boolean_get(op->ptr, "lock_location");
539 data->locz_lock = RNA_boolean_get(op->ptr, "lock_location_z");
540 data->rot_lock = RNA_boolean_get(op->ptr, "lock_rotation");
541 data->rotz_lock = RNA_boolean_get(op->ptr, "lock_rotation_z");
542 data->scale_lock = RNA_boolean_get(op->ptr, "lock_scale");
543
544 /* Check if navigation is locked. */
545 if (!wm_xr_navigation_grab_is_locked(data, do_bimanual)) {
546 /* Prevent unwanted snapping (i.e. "jumpy" navigation changes when transitioning from
547 * two-handed to one-handed interaction) at the end of a bimanual interaction. */
548 if (!wm_xr_navigation_grab_is_bimanual_ending(actiondata, data)) {
549 wm_xr_navigation_grab_apply(xr, actiondata, data, do_bimanual);
550 }
551 }
552
554
555 /* NOTE: #KM_PRESS and #KM_RELEASE are the only two values supported by XR events during event
556 * dispatching (see #wm_xr_session_action_states_interpret()). For modal XR operators, modal
557 * handling starts when an input is "pressed" (action state exceeds the action threshold) and
558 * ends when the input is "released" (state falls below the threshold). */
559 switch (event->val) {
560 case KM_PRESS:
562 case KM_RELEASE:
564 return OPERATOR_FINISHED;
565 default:
568 return OPERATOR_CANCELLED;
569 }
570}
571
573{
574 /* Identifiers. */
575 ot->name = "XR Navigation Grab";
576 ot->idname = "WM_OT_xr_navigation_grab";
577 ot->description = "Navigate the VR scene by grabbing with controllers";
578
579 /* Callbacks. */
584
585 /* Properties. */
587 ot->srna, "lock_location", false, "Lock Location", "Prevent changes to viewer location");
589 ot->srna, "lock_location_z", false, "Lock Elevation", "Prevent changes to viewer elevation");
591 ot->srna, "lock_rotation", false, "Lock Rotation", "Prevent changes to viewer rotation");
593 "lock_rotation_z",
594 false,
595 "Lock Up Orientation",
596 "Prevent changes to viewer up orientation");
597 RNA_def_boolean(ot->srna, "lock_scale", false, "Lock Scale", "Prevent changes to viewer scale");
598}
599
602/* -------------------------------------------------------------------- */
606static const float g_xr_default_raycast_axis[3] = {0.0f, 0.0f, -1.0f};
607static const float g_xr_default_raycast_color[4] = {0.35f, 0.35f, 1.0f, 1.0f};
608
611 float origin[3];
612 float direction[3];
613 float end[3];
614 float color[4];
616};
617
618static void wm_xr_raycast_draw(const bContext * /*C*/, ARegion * /*region*/, void *customdata)
619{
620 const XrRaycastData *data = static_cast<const XrRaycastData *>(customdata);
621
624
625 if (data->from_viewer) {
627 immUniformColor4fv(data->color);
628
630 GPU_point_size(7.0f);
631
633 immVertex3fv(pos, data->end);
634 immEnd();
635 }
636 else {
639
640 float viewport[4];
641 GPU_viewport_size_get_f(viewport);
642 immUniform2fv("viewportSize", &viewport[2]);
643
644 immUniform1f("lineWidth", 3.0f * U.pixelsize);
645
647
650 immVertex3fv(pos, data->origin);
651 immAttr4fv(col, data->color);
652 immVertex3fv(pos, data->end);
653 immEnd();
654 }
655
657}
658
660{
661 BLI_assert(op->customdata == nullptr);
662
663 op->customdata = MEM_callocN(sizeof(XrRaycastData), __func__);
664
666 if (!st) {
667 return;
668 }
669
671 if (!art) {
672 return;
673 }
674
675 XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
678}
679
681{
682 if (!op->customdata) {
683 return;
684 }
685
687 if (st) {
689 if (art) {
690 XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
691 ED_region_draw_cb_exit(art, data->draw_handle);
692 }
693 }
694
696}
697
699 const wmXrData *xr,
700 const wmXrActionData *actiondata)
701{
702 XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
703 float ray_length, axis[3];
704
705 data->from_viewer = RNA_boolean_get(op->ptr, "from_viewer");
706 RNA_float_get_array(op->ptr, "axis", axis);
707 RNA_float_get_array(op->ptr, "color", data->color);
708
709 if (data->from_viewer) {
710 float viewer_rot[4];
713 mul_qt_v3(viewer_rot, axis);
714 ray_length = (xr->session_settings.clip_start + xr->session_settings.clip_end) / 2.0f;
715 }
716 else {
717 copy_v3_v3(data->origin, actiondata->controller_loc);
718 mul_qt_v3(actiondata->controller_rot, axis);
719 ray_length = xr->session_settings.clip_end;
720 }
721
722 copy_v3_v3(data->direction, axis);
723 madd_v3_v3v3fl(data->end, data->origin, data->direction, ray_length);
724}
725
726static void wm_xr_raycast(Scene *scene,
727 Depsgraph *depsgraph,
728 const float origin[3],
729 const float direction[3],
730 float *ray_dist,
731 bool selectable_only,
732 float r_location[3],
733 float r_normal[3],
734 int *r_index,
735 const Object **r_ob,
736 float r_obmat[4][4])
737{
738 /* Uses same raycast method as Scene.ray_cast(). */
740
742 params.snap_target_select = (selectable_only ? SCE_SNAP_TARGET_ONLY_SELECTABLE :
745 depsgraph,
746 nullptr,
747 &params,
748 origin,
749 direction,
750 ray_dist,
751 r_location,
752 r_normal,
753 r_index,
754 r_ob,
755 r_obmat);
756
758}
759
762/* -------------------------------------------------------------------- */
769#define XR_DEFAULT_FLY_SPEED_MOVE 0.054f
770#define XR_DEFAULT_FLY_SPEED_TURN 0.03f
771
787
788struct XrFlyData {
789 float viewer_rot[4];
790 double time_prev;
791};
792
793static void wm_xr_fly_init(wmOperator *op, const wmXrData *xr)
794{
795 BLI_assert(op->customdata == nullptr);
796
797 XrFlyData *data = static_cast<XrFlyData *>(
798 op->customdata = MEM_callocN(sizeof(XrFlyData), __func__));
799
801 data->time_prev = BLI_time_now_seconds();
802}
803
805{
807}
808
810 float speed,
811 const float ref_quat[4],
812 const float nav_mat[4][4],
813 bool locz_lock,
814 float r_delta[4][4])
815{
816 float ref_axes[3][3];
817 quat_to_mat3(ref_axes, ref_quat);
818
819 unit_m4(r_delta);
820
821 switch (mode) {
822 /* Navigation space reference. */
823 case XR_FLY_FORWARD:
824 madd_v3_v3fl(r_delta[3], ref_axes[1], speed);
825 return;
826 case XR_FLY_BACK:
827 madd_v3_v3fl(r_delta[3], ref_axes[1], -speed);
828 return;
829 case XR_FLY_LEFT:
830 madd_v3_v3fl(r_delta[3], ref_axes[0], -speed);
831 return;
832 case XR_FLY_RIGHT:
833 madd_v3_v3fl(r_delta[3], ref_axes[0], speed);
834 return;
835 case XR_FLY_UP:
836 case XR_FLY_DOWN:
837 if (!locz_lock) {
838 madd_v3_v3fl(r_delta[3], ref_axes[2], (mode == XR_FLY_UP) ? speed : -speed);
839 }
840 return;
841 /* Viewer/controller space reference. */
844 negate_v3_v3(r_delta[3], ref_axes[2]);
845 break;
847 copy_v3_v3(r_delta[3], ref_axes[2]);
848 break;
850 negate_v3_v3(r_delta[3], ref_axes[0]);
851 break;
853 copy_v3_v3(r_delta[3], ref_axes[0]);
854 break;
855 /* Unused. */
856 case XR_FLY_TURNLEFT:
857 case XR_FLY_TURNRIGHT:
859 return;
860 }
861
862 if (locz_lock) {
863 /* Lock elevation in navigation space. */
864 float z_axis[3], projected[3];
865
866 normalize_v3_v3(z_axis, nav_mat[2]);
867 project_v3_v3v3_normalized(projected, r_delta[3], z_axis);
868 sub_v3_v3(r_delta[3], projected);
869
870 normalize_v3(r_delta[3]);
871 }
872
873 mul_v3_fl(r_delta[3], speed);
874}
875
877 float speed,
878 const float viewer_mat[4][4],
879 const float nav_mat[4][4],
880 const float nav_inv[4][4],
881 float r_delta[4][4])
882{
884
885 float z_axis[3], m[3][3], prev[4][4], curr[4][4];
886
887 /* Turn around Z-axis in navigation space. */
888 normalize_v3_v3(z_axis, nav_mat[2]);
889 axis_angle_normalized_to_mat3(m, z_axis, (mode == XR_FLY_TURNLEFT) ? speed : -speed);
890 copy_m4_m3(r_delta, m);
891
892 copy_m4_m4(prev, viewer_mat);
893 mul_m4_m4m4(curr, r_delta, viewer_mat);
894
895 /* Lock location in base pose space. */
896 wm_xr_navlocks_apply(nav_mat, nav_inv, true, false, false, prev, curr);
897
898 invert_m4(prev);
899 mul_m4_m4m4(r_delta, curr, prev);
900}
901
903 const float nav_rotation[4],
904 float r_rotation[4])
905{
906 /* Apply nav rotation to base pose Z-rotation. */
907 float base_eul[3], base_quatz[4];
908 quat_to_eul(base_eul, xr->runtime->session_state.prev_base_pose.orientation_quat);
909 axis_angle_to_quat_single(base_quatz, 'Z', base_eul[2]);
910 mul_qt_qtqt(r_rotation, nav_rotation, base_quatz);
911}
912
914{
915 if (!wm_xr_operator_test_event(op, event)) {
917 }
918
920
921 wm_xr_fly_init(op, &wm->xr);
922
924
926}
927
928static int wm_xr_navigation_fly_exec(bContext * /*C*/, wmOperator * /*op*/)
929{
930 return OPERATOR_CANCELLED;
931}
932
933static int wm_xr_navigation_fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
934{
935 if (!wm_xr_operator_test_event(op, event)) {
937 }
938
939 if (event->val == KM_RELEASE) {
941 return OPERATOR_FINISHED;
942 }
943
944 const wmXrActionData *actiondata = static_cast<const wmXrActionData *>(event->customdata);
945 XrFlyData *data = static_cast<XrFlyData *>(op->customdata);
947 wmXrData *xr = &wm->xr;
948 eXrFlyMode mode;
949 bool turn, locz_lock, dir_lock, speed_frame_based;
950 bool speed_interp_cubic = false;
951 float speed, speed_max, speed_p0[2], speed_p1[2];
952 GHOST_XrPose nav_pose;
953 float nav_mat[4][4], delta[4][4], out[4][4];
954
955 const double time_now = BLI_time_now_seconds();
956
957 mode = (eXrFlyMode)RNA_enum_get(op->ptr, "mode");
959
960 locz_lock = RNA_boolean_get(op->ptr, "lock_location_z");
961 dir_lock = RNA_boolean_get(op->ptr, "lock_direction");
962 speed_frame_based = RNA_boolean_get(op->ptr, "speed_frame_based");
963 speed = RNA_float_get(op->ptr, "speed_min");
964 speed_max = RNA_float_get(op->ptr, "speed_max");
965
966 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "speed_interpolation0");
967 if (prop && RNA_property_is_set(op->ptr, prop)) {
968 RNA_property_float_get_array(op->ptr, prop, speed_p0);
969 speed_interp_cubic = true;
970 }
971 else {
972 speed_p0[0] = speed_p0[1] = 0.0f;
973 }
974
975 prop = RNA_struct_find_property(op->ptr, "speed_interpolation1");
976 if (prop && RNA_property_is_set(op->ptr, prop)) {
977 RNA_property_float_get_array(op->ptr, prop, speed_p1);
978 speed_interp_cubic = true;
979 }
980 else {
981 speed_p1[0] = speed_p1[1] = 1.0f;
982 }
983
984 /* Ensure valid interpolation. */
985 if (speed_max < speed) {
986 speed_max = speed;
987 }
988
989 /* Interpolate between min/max speeds based on button state. */
990 switch (actiondata->type) {
991 case XR_BOOLEAN_INPUT:
992 speed = speed_max;
993 break;
994 case XR_FLOAT_INPUT:
995 case XR_VECTOR2F_INPUT: {
996 float state = (actiondata->type == XR_FLOAT_INPUT) ? fabsf(actiondata->state[0]) :
997 len_v2(actiondata->state);
998 float speed_t = (actiondata->float_threshold < 1.0f) ?
999 (state - actiondata->float_threshold) /
1000 (1.0f - actiondata->float_threshold) :
1001 1.0f;
1002 if (speed_interp_cubic) {
1003 float start[2], end[2], p[2];
1004
1005 start[0] = 0.0f;
1006 start[1] = speed;
1007 speed_p0[1] = speed + speed_p0[1] * (speed_max - speed);
1008 speed_p1[1] = speed + speed_p1[1] * (speed_max - speed);
1009 end[0] = 1.0f;
1010 end[1] = speed_max;
1011
1012 interp_v2_v2v2v2v2_cubic(p, start, speed_p0, speed_p1, end, speed_t);
1013 speed = p[1];
1014 }
1015 else {
1016 speed += speed_t * (speed_max - speed);
1017 }
1018 break;
1019 }
1020 case XR_POSE_INPUT:
1023 break;
1024 }
1025
1026 if (!speed_frame_based) {
1027 /* Adjust speed based on last update time. */
1028 speed *= time_now - data->time_prev;
1029 }
1030 data->time_prev = time_now;
1031
1032 WM_xr_session_state_nav_location_get(xr, nav_pose.position);
1033 WM_xr_session_state_nav_rotation_get(xr, nav_pose.orientation_quat);
1034 wm_xr_pose_to_mat(&nav_pose, nav_mat);
1035
1036 if (turn) {
1037 if (dir_lock) {
1038 unit_m4(delta);
1039 }
1040 else {
1041 GHOST_XrPose viewer_pose;
1042 float viewer_mat[4][4], nav_inv[4][4];
1043
1044 WM_xr_session_state_viewer_pose_location_get(xr, viewer_pose.position);
1045 WM_xr_session_state_viewer_pose_rotation_get(xr, viewer_pose.orientation_quat);
1046 wm_xr_pose_to_mat(&viewer_pose, viewer_mat);
1047 wm_xr_pose_to_imat(&nav_pose, nav_inv);
1048
1049 wm_xr_fly_compute_turn(mode, speed, viewer_mat, nav_mat, nav_inv, delta);
1050 }
1051 }
1052 else {
1053 float nav_scale, ref_quat[4];
1054
1055 /* Adjust speed for base and navigation scale. */
1056 WM_xr_session_state_nav_scale_get(xr, &nav_scale);
1057 speed *= xr->session_settings.base_scale * nav_scale;
1058
1059 switch (mode) {
1060 /* Move relative to navigation space. */
1061 case XR_FLY_FORWARD:
1062 case XR_FLY_BACK:
1063 case XR_FLY_LEFT:
1064 case XR_FLY_RIGHT:
1065 case XR_FLY_UP:
1066 case XR_FLY_DOWN:
1067 wm_xr_basenav_rotation_calc(xr, nav_pose.orientation_quat, ref_quat);
1068 break;
1069 /* Move relative to viewer. */
1071 case XR_FLY_VIEWER_BACK:
1072 case XR_FLY_VIEWER_LEFT:
1074 if (dir_lock) {
1075 copy_qt_qt(ref_quat, data->viewer_rot);
1076 }
1077 else {
1079 }
1080 break;
1081 /* Move relative to controller. */
1083 copy_qt_qt(ref_quat, actiondata->controller_rot);
1084 break;
1085 /* Unused. */
1086 case XR_FLY_TURNLEFT:
1087 case XR_FLY_TURNRIGHT:
1089 break;
1090 }
1091
1092 wm_xr_fly_compute_move(mode, speed, ref_quat, nav_mat, locz_lock, delta);
1093 }
1094
1095 mul_m4_m4m4(out, delta, nav_mat);
1096
1098 if (turn) {
1099 mat4_to_quat(nav_pose.orientation_quat, out);
1100 WM_xr_session_state_nav_rotation_set(xr, nav_pose.orientation_quat);
1101 }
1102
1103 if (event->val == KM_PRESS) {
1105 }
1106
1107 /* XR events currently only support press and release. */
1109 wm_xr_fly_uninit(op);
1110 return OPERATOR_CANCELLED;
1111}
1112
1114{
1115 /* Identifiers. */
1116 ot->name = "XR Navigation Fly";
1117 ot->idname = "WM_OT_xr_navigation_fly";
1118 ot->description = "Move/turn relative to the VR viewer or controller";
1119
1120 /* Callbacks. */
1125
1126 /* Properties. */
1127 static const EnumPropertyItem fly_modes[] = {
1128 {XR_FLY_FORWARD, "FORWARD", 0, "Forward", "Move along navigation forward axis"},
1129 {XR_FLY_BACK, "BACK", 0, "Back", "Move along navigation back axis"},
1130 {XR_FLY_LEFT, "LEFT", 0, "Left", "Move along navigation left axis"},
1131 {XR_FLY_RIGHT, "RIGHT", 0, "Right", "Move along navigation right axis"},
1132 {XR_FLY_UP, "UP", 0, "Up", "Move along navigation up axis"},
1133 {XR_FLY_DOWN, "DOWN", 0, "Down", "Move along navigation down axis"},
1135 "TURNLEFT",
1136 0,
1137 "Turn Left",
1138 "Turn counter-clockwise around navigation up axis"},
1139 {XR_FLY_TURNRIGHT, "TURNRIGHT", 0, "Turn Right", "Turn clockwise around navigation up axis"},
1141 "VIEWER_FORWARD",
1142 0,
1143 "Viewer Forward",
1144 "Move along viewer's forward axis"},
1145 {XR_FLY_VIEWER_BACK, "VIEWER_BACK", 0, "Viewer Back", "Move along viewer's back axis"},
1146 {XR_FLY_VIEWER_LEFT, "VIEWER_LEFT", 0, "Viewer Left", "Move along viewer's left axis"},
1147 {XR_FLY_VIEWER_RIGHT, "VIEWER_RIGHT", 0, "Viewer Right", "Move along viewer's right axis"},
1149 "CONTROLLER_FORWARD",
1150 0,
1151 "Controller Forward",
1152 "Move along controller's forward axis"},
1153 {0, nullptr, 0, nullptr, nullptr},
1154 };
1155
1156 static const float default_speed_p0[2] = {0.0f, 0.0f};
1157 static const float default_speed_p1[2] = {1.0f, 1.0f};
1158
1159 RNA_def_enum(ot->srna, "mode", fly_modes, XR_FLY_VIEWER_FORWARD, "Mode", "Fly mode");
1161 ot->srna, "lock_location_z", false, "Lock Elevation", "Prevent changes to viewer elevation");
1163 "lock_direction",
1164 false,
1165 "Lock Direction",
1166 "Limit movement to viewer's initial direction");
1168 "speed_frame_based",
1169 true,
1170 "Frame Based Speed",
1171 "Apply fixed movement deltas every update");
1173 "speed_min",
1175 0.0f,
1176 1000.0f,
1177 "Minimum Speed",
1178 "Minimum move (turn) speed in meters (radians) per second or frame",
1179 0.0f,
1180 1000.0f);
1182 "speed_max",
1184 0.0f,
1185 1000.0f,
1186 "Maximum Speed",
1187 "Maximum move (turn) speed in meters (radians) per second or frame",
1188 0.0f,
1189 1000.0f);
1191 "speed_interpolation0",
1192 2,
1193 default_speed_p0,
1194 0.0f,
1195 1.0f,
1196 "Speed Interpolation 0",
1197 "First cubic spline control point between min/max speeds",
1198 0.0f,
1199 1.0f);
1201 "speed_interpolation1",
1202 2,
1203 default_speed_p1,
1204 0.0f,
1205 1.0f,
1206 "Speed Interpolation 1",
1207 "Second cubic spline control point between min/max speeds",
1208 0.0f,
1209 1.0f);
1210}
1211
1214/* -------------------------------------------------------------------- */
1221 wmXrData *xr,
1222 const float origin[3],
1223 const float direction[3],
1224 float *ray_dist,
1225 bool selectable_only,
1226 const bool teleport_axes[3],
1227 float teleport_t,
1228 float teleport_ofs)
1229{
1230 Scene *scene = CTX_data_scene(C);
1232 float location[3];
1233 float normal[3];
1234 int index;
1235 const Object *ob = nullptr;
1236 float obmat[4][4];
1237
1238 wm_xr_raycast(scene,
1239 depsgraph,
1240 origin,
1241 direction,
1242 ray_dist,
1243 selectable_only,
1244 location,
1245 normal,
1246 &index,
1247 &ob,
1248 obmat);
1249
1250 /* Teleport. */
1251 if (ob) {
1252 float nav_location[3], nav_rotation[4], viewer_location[3];
1253 float nav_axes[3][3], projected[3], v0[3], v1[3];
1254 float out[3] = {0.0f, 0.0f, 0.0f};
1255
1256 WM_xr_session_state_nav_location_get(xr, nav_location);
1257 WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
1259
1260 wm_xr_basenav_rotation_calc(xr, nav_rotation, nav_rotation);
1261 quat_to_mat3(nav_axes, nav_rotation);
1262
1263 /* Project locations onto navigation axes. */
1264 for (int a = 0; a < 3; ++a) {
1265 project_v3_v3v3_normalized(projected, nav_location, nav_axes[a]);
1266 if (teleport_axes[a]) {
1267 /* Interpolate between projected locations. */
1268 project_v3_v3v3_normalized(v0, location, nav_axes[a]);
1269 project_v3_v3v3_normalized(v1, viewer_location, nav_axes[a]);
1270 sub_v3_v3(v0, v1);
1271 madd_v3_v3fl(projected, v0, teleport_t);
1272 /* Subtract offset. */
1273 project_v3_v3v3_normalized(v0, normal, nav_axes[a]);
1274 madd_v3_v3fl(projected, v0, teleport_ofs);
1275 }
1276 /* Add to final location. */
1277 add_v3_v3(out, projected);
1278 }
1279
1281 }
1282}
1283
1285{
1286 if (!wm_xr_operator_test_event(op, event)) {
1287 return OPERATOR_PASS_THROUGH;
1288 }
1289
1291
1292 int retval = op->type->modal(C, op, event);
1293
1294 if ((retval & OPERATOR_RUNNING_MODAL) != 0) {
1296 }
1297
1298 return retval;
1299}
1300
1302{
1303 return OPERATOR_CANCELLED;
1304}
1305
1307{
1308 if (!wm_xr_operator_test_event(op, event)) {
1309 return OPERATOR_PASS_THROUGH;
1310 }
1311
1312 const wmXrActionData *actiondata = static_cast<const wmXrActionData *>(event->customdata);
1314 wmXrData *xr = &wm->xr;
1315
1316 wm_xr_raycast_update(op, xr, actiondata);
1317
1318 switch (event->val) {
1319 case KM_PRESS:
1321 case KM_RELEASE: {
1322 XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
1323 bool selectable_only, teleport_axes[3];
1324 float teleport_t, teleport_ofs, ray_dist;
1325
1326 RNA_boolean_get_array(op->ptr, "teleport_axes", teleport_axes);
1327 teleport_t = RNA_float_get(op->ptr, "interpolation");
1328 teleport_ofs = RNA_float_get(op->ptr, "offset");
1329 selectable_only = RNA_boolean_get(op->ptr, "selectable_only");
1330 ray_dist = RNA_float_get(op->ptr, "distance");
1331
1333 xr,
1334 data->origin,
1335 data->direction,
1336 &ray_dist,
1337 selectable_only,
1338 teleport_axes,
1339 teleport_t,
1340 teleport_ofs);
1341
1343
1344 return OPERATOR_FINISHED;
1345 }
1346 default:
1347 /* XR events currently only support press and release. */
1350 return OPERATOR_CANCELLED;
1351 }
1352}
1353
1355{
1356 /* Identifiers. */
1357 ot->name = "XR Navigation Teleport";
1358 ot->idname = "WM_OT_xr_navigation_teleport";
1359 ot->description = "Set VR viewer location to controller raycast hit location";
1360
1361 /* Callbacks. */
1366
1367 /* Properties. */
1368 static const bool default_teleport_axes[3] = {true, true, true};
1369
1371 "teleport_axes",
1372 3,
1373 default_teleport_axes,
1374 "Teleport Axes",
1375 "Enabled teleport axes in navigation space");
1377 "interpolation",
1378 1.0f,
1379 0.0f,
1380 1.0f,
1381 "Interpolation",
1382 "Interpolation factor between viewer and hit locations",
1383 0.0f,
1384 1.0f);
1386 "offset",
1387 0.0f,
1388 0.0f,
1389 FLT_MAX,
1390 "Offset",
1391 "Offset along hit normal to subtract from final location",
1392 0.0f,
1393 FLT_MAX);
1395 "selectable_only",
1396 true,
1397 "Selectable Only",
1398 "Only allow selectable objects to influence raycast result");
1400 "distance",
1402 0.0,
1404 "",
1405 "Maximum raycast distance",
1406 0.0,
1409 ot->srna, "from_viewer", false, "From Viewer", "Use viewer pose as raycast origin");
1411 "axis",
1412 3,
1414 -1.0f,
1415 1.0f,
1416 "Axis",
1417 "Raycast axis in controller/viewer space",
1418 -1.0f,
1419 1.0f);
1421 "color",
1422 4,
1424 0.0f,
1425 1.0f,
1426 "Color",
1427 "Raycast color",
1428 0.0f,
1429 1.0f);
1430}
1431
1434/* -------------------------------------------------------------------- */
1441{
1443 wmXrData *xr = &wm->xr;
1444 bool reset_loc, reset_rot, reset_scale;
1445
1446 reset_loc = RNA_boolean_get(op->ptr, "location");
1447 reset_rot = RNA_boolean_get(op->ptr, "rotation");
1448 reset_scale = RNA_boolean_get(op->ptr, "scale");
1449
1450 if (reset_loc) {
1451 float loc[3];
1452 if (!reset_scale) {
1453 float nav_rotation[4], nav_scale;
1454
1455 WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
1456 WM_xr_session_state_nav_scale_get(xr, &nav_scale);
1457
1458 /* Adjust location based on scale. */
1459 mul_v3_v3fl(loc, xr->runtime->session_state.prev_base_pose.position, nav_scale);
1460 sub_v3_v3(loc, xr->runtime->session_state.prev_base_pose.position);
1461 mul_qt_v3(nav_rotation, loc);
1462 negate_v3(loc);
1463 }
1464 else {
1465 zero_v3(loc);
1466 }
1468 }
1469
1470 if (reset_rot) {
1471 float rot[4];
1472 unit_qt(rot);
1474 }
1475
1476 if (reset_scale) {
1477 if (!reset_loc) {
1478 float nav_location[3], nav_rotation[4], nav_scale;
1479 float nav_axes[3][3], v[3];
1480
1481 WM_xr_session_state_nav_location_get(xr, nav_location);
1482 WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
1483 WM_xr_session_state_nav_scale_get(xr, &nav_scale);
1484
1485 /* Offset any location changes when changing scale. */
1486 mul_v3_v3fl(v, xr->runtime->session_state.prev_base_pose.position, nav_scale);
1488 mul_qt_v3(nav_rotation, v);
1489 add_v3_v3(nav_location, v);
1490
1491 /* Reset elevation to base pose value. */
1492 quat_to_mat3(nav_axes, nav_rotation);
1493 project_v3_v3v3_normalized(v, nav_location, nav_axes[2]);
1494 sub_v3_v3(nav_location, v);
1495
1496 WM_xr_session_state_nav_location_set(xr, nav_location);
1497 }
1499 }
1500
1501 return OPERATOR_FINISHED;
1502}
1503
1505{
1506 /* Identifiers. */
1507 ot->name = "XR Navigation Reset";
1508 ot->idname = "WM_OT_xr_navigation_reset";
1509 ot->description = "Reset VR navigation deltas relative to session base pose";
1510
1511 /* Callbacks. */
1514
1515 /* Properties. */
1516 RNA_def_boolean(ot->srna, "location", true, "Location", "Reset location deltas");
1517 RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "Reset rotation deltas");
1518 RNA_def_boolean(ot->srna, "scale", true, "Scale", "Reset scale deltas");
1519}
1520
1523/* -------------------------------------------------------------------- */
1535
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
#define G_MAIN
bool IDP_EqualsProperties(const IDProperty *prop1, const IDProperty *prop2) ATTR_WARN_UNUSED_RESULT
Definition idprop.cc:984
SpaceType * BKE_spacetype_from_id(int spaceid)
Definition screen.cc:243
ARegionType * BKE_regiontype_from_id(const SpaceType *st, int regionid)
Definition screen.cc:253
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BVH_RAYCAST_DIST_MAX
Definition BLI_kdopbvh.h:92
#define LISTBASE_FOREACH(type, var, list)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void unit_m4(float m[4][4])
Definition rct.c:1127
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4(float mat[4][4])
void quat_to_mat3(float m[3][3], const float q[4])
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
void axis_angle_to_quat_single(float q[4], char axis, float angle)
float normalize_qt(float q[4])
void quat_to_mat4(float m[4][4], const float q[4])
void mul_qt_v3(const float q[4], float r[3])
void unit_qt(float q[4])
void quat_to_eul(float eul[3], const float quat[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
void mat4_to_quat(float q[4], const float mat[4][4])
void copy_qt_qt(float q[4], const float a[4])
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3(float r[3], const float a[3])
void interp_v2_v2v2v2v2_cubic(float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2], float u)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
void project_v3_v3v3_normalized(float out[3], const float p[3], const float v_proj[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
#define ELEM(...)
@ SCE_SNAP_TARGET_ONLY_SELECTABLE
@ SCE_SNAP_TARGET_ALL
@ RGN_TYPE_XR
@ SPACE_VIEW3D
@ V3D_RUNTIME_XR_SESSION_ROOT
@ V3D_XR_SESSION_MIRROR
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ XR_FLOAT_INPUT
@ XR_BOOLEAN_INPUT
@ XR_VECTOR2F_INPUT
@ XR_POSE_INPUT
@ XR_VIBRATION_OUTPUT
bool ED_operator_view3d_active(bContext *C)
void * ED_region_draw_cb_activate(ARegionType *art, void(*draw)(const bContext *, ARegion *, void *), void *customdata, int type)
#define REGION_DRAW_POST_VIEW
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx, Depsgraph *depsgraph, const View3D *v3d, const 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, const Object **r_ob, float r_obmat[4][4])
SnapObjectContext * ED_transform_snap_object_context_create(Scene *scene, int flag)
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
void immEnd()
void immUniform2fv(const char *name, const float data[2])
void immUnbindProgram()
void immAttr4fv(uint attr_id, const float data[4])
void immAttrSkip(uint attr_id)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat()
void immUniformColor4fv(const float rgba[4])
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_3D_POLYLINE_FLAT_COLOR
void GPU_point_size(float size)
Definition gpu_state.cc:167
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:111
@ GPU_DEPTH_NONE
Definition GPU_state.hh:108
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:262
@ 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)
@ OPTYPE_INTERNAL
Definition WM_types.hh:182
#define NC_WM
Definition WM_types.hh:341
@ KM_PRESS
Definition WM_types.hh:284
@ KM_RELEASE
Definition WM_types.hh:285
#define ND_XR_DATA_CHANGED
Definition WM_types.hh:385
ATTR_WARN_UNUSED_RESULT const BMVert * v
unsigned int U
Definition btGjkEpa3.h:78
const Depsgraph * depsgraph
#define fabsf(x)
#define rot(x, k)
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
static ulong state[N]
#define R
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
void RNA_boolean_get_array(PointerRNA *ptr, const char *name, bool *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const bool *default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
#define FLT_MAX
Definition stdcycles.h:14
void * first
ListBase wm
Definition BKE_main.hh:239
ListBase screens
Definition BKE_main.hh:225
View3D_Runtime runtime
float viewer_rot[4]
float mat_other_prev[4][4]
float mat_prev[4][4]
short custom
Definition WM_types.hh:758
short val
Definition WM_types.hh:724
short type
Definition WM_types.hh:722
void * customdata
Definition WM_types.hh:772
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
StructRNA * srna
Definition WM_types.hh:1080
IDProperty * properties
struct wmOperatorType * type
struct PointerRNA * ptr
XrSessionSettings session_settings
struct wmXrRuntimeData * runtime
wmXrSessionState session_state
GHOST_XrPose prev_base_pose
void WM_main_add_notifier(uint type, void *reference)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ EVT_DATA_XR
@ EVT_XR_ACTION
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
Scene * WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen *screen)
bool wm_xr_init(wmWindowManager *wm)
Definition wm_xr.cc:58
void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4])
Definition wm_xr_draw.cc:33
void wm_xr_pose_scale_to_mat(const GHOST_XrPose *pose, float scale, float r_mat[4][4])
Definition wm_xr_draw.cc:39
void wm_xr_pose_scale_to_imat(const GHOST_XrPose *pose, float scale, float r_imat[4][4])
Definition wm_xr_draw.cc:57
void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4])
Definition wm_xr_draw.cc:49
static void orient_mat_z_normalized(float R[4][4], const float z_axis[3])
static void wm_xr_grab_init(wmOperator *op)
static void wm_xr_navigation_teleport(bContext *C, wmXrData *xr, const float origin[3], const float direction[3], float *ray_dist, bool selectable_only, const bool teleport_axes[3], float teleport_t, float teleport_ofs)
static void wm_xr_fly_init(wmOperator *op, const wmXrData *xr)
static void wm_xr_navigation_grab_bimanual_state_update(const wmXrActionData *actiondata, XrGrabData *data)
static void wm_xr_basenav_rotation_calc(const wmXrData *xr, const float nav_rotation[4], float r_rotation[4])
static 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 int wm_xr_navigation_teleport_exec(bContext *, wmOperator *)
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 void wm_xr_grab_compute_bimanual(const wmXrActionData *actiondata, const XrGrabData *data, const float nav_mat[4][4], const float nav_inv[4][4], bool reverse, float r_delta[4][4])
static void wm_xr_fly_uninit(wmOperator *op)
static bool wm_xr_operator_sessionactive(bContext *C)
#define XR_DEFAULT_FLY_SPEED_MOVE
static void wm_xr_raycast_uninit(wmOperator *op)
static int wm_xr_navigation_grab_exec(bContext *, wmOperator *)
static int wm_xr_navigation_fly_exec(bContext *, wmOperator *)
void wm_xr_operatortypes_register()
static void wm_xr_raycast_update(wmOperator *op, const wmXrData *xr, const wmXrActionData *actiondata)
static bool wm_xr_navigation_grab_is_locked(const XrGrabData *data, const bool bimanual)
static void wm_xr_session_update_screen_on_exit_cb(const wmXrData *xr_data)
static 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)
static void wm_xr_grab_update(wmOperator *op, const wmXrActionData *actiondata)
static void wm_xr_raycast(Scene *scene, Depsgraph *depsgraph, const float origin[3], const float direction[3], float *ray_dist, bool selectable_only, float r_location[3], float r_normal[3], int *r_index, const Object **r_ob, float r_obmat[4][4])
static const float g_xr_default_raycast_color[4]
static int wm_xr_navigation_grab_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int wm_xr_session_toggle_exec(bContext *C, wmOperator *)
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)
@ 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_raycast_draw(const bContext *, ARegion *, void *customdata)
static void wm_xr_grab_compute(const wmXrActionData *actiondata, const XrGrabData *data, const float nav_mat[4][4], const float nav_inv[4][4], bool reverse, float r_delta[4][4])
static void wm_xr_fly_compute_move(eXrFlyMode mode, float speed, const float ref_quat[4], const float nav_mat[4][4], bool locz_lock, float r_delta[4][4])
static void WM_OT_xr_session_toggle(wmOperatorType *ot)
static 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])