Blender V4.5
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
12
13#include "BLI_kdopbvh.hh"
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 "BLT_translation.hh"
21
22#include "BKE_context.hh"
23#include "BKE_global.hh"
24#include "BKE_idprop.hh"
25#include "BKE_main.hh"
26#include "BKE_screen.hh"
27
28#include "DEG_depsgraph.hh"
29
30#include "ED_screen.hh"
31#include "ED_space_api.hh"
33#include "ED_view3d.hh"
34
35#include "GHOST_Types.h"
36
37#include "GPU_immediate.hh"
38#include "GPU_state.hh"
39
40#include "MEM_guardedalloc.h"
41
42#include "RNA_access.hh"
43#include "RNA_define.hh"
44
45#include "WM_api.hh"
46#include "WM_types.hh"
47
48#include "wm_xr_intern.hh"
49
50/* -------------------------------------------------------------------- */
53
54/* `op->poll`. */
60
61static bool wm_xr_operator_test_event(const wmOperator *op, const wmEvent *event)
62{
63 if (event->type != EVT_XR_ACTION) {
64 return false;
65 }
66
67 BLI_assert(event->custom == EVT_DATA_XR);
68 BLI_assert(event->customdata);
69
70 wmXrActionData *actiondata = static_cast<wmXrActionData *>(event->customdata);
71 return (actiondata->ot == op->type &&
72 IDP_EqualsProperties(actiondata->op_properties, op->properties));
73}
74
76
77/* -------------------------------------------------------------------- */
82
83static void wm_xr_session_update_screen(Main *bmain, const wmXrData *xr_data)
84{
85 const bool session_exists = WM_xr_session_exists(xr_data);
86
87 for (bScreen *screen = static_cast<bScreen *>(bmain->screens.first); screen;
88 screen = static_cast<bScreen *>(screen->id.next))
89 {
90 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
91 LISTBASE_FOREACH (SpaceLink *, slink, &area->spacedata) {
92 if (slink->spacetype == SPACE_VIEW3D) {
93 View3D *v3d = (View3D *)slink;
94
95 if (v3d->flag & V3D_XR_SESSION_MIRROR) {
96 ED_view3d_xr_mirror_update(area, v3d, session_exists);
97 }
98
99 if (session_exists) {
100 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
101 const Scene *scene = WM_windows_scene_get_from_screen(wm, screen);
102
103 ED_view3d_xr_shading_update(wm, v3d, scene);
104 }
105 /* Ensure no 3D View is tagged as session root. */
106 else {
108 }
109 }
110 }
111 }
112 }
113
115}
116
118{
119 /* Just use G_MAIN here, storing main isn't reliable enough on file read or exit. */
121}
122
124{
125 Main *bmain = CTX_data_main(C);
127 wmWindow *win = CTX_wm_window(C);
128 View3D *v3d = CTX_wm_view3d(C);
129
130 /* Lazily-create XR context - tries to dynamic-link to the runtime,
131 * reading `active_runtime.json`. */
132 if (wm_xr_init(wm) == false) {
133 return OPERATOR_CANCELLED;
134 }
135
138 wm_xr_session_update_screen(bmain, &wm->xr);
139
141
142 return OPERATOR_FINISHED;
143}
144
146{
147 /* Identifiers. */
148 ot->name = "Toggle VR Session";
149 ot->idname = "WM_OT_xr_session_toggle";
150 ot->description =
151 "Open a view for use with virtual reality headsets, or close it if already "
152 "opened";
153
154 /* Callbacks. */
157
158 /* XXX INTERNAL just to hide it from the search menu by default, an Add-on will expose it in the
159 * UI instead. Not meant as a permanent solution. */
160 ot->flag = OPTYPE_INTERNAL;
161}
162
164
165/* -------------------------------------------------------------------- */
168
175
177{
178 BLI_assert(op->customdata == nullptr);
179
180 op->customdata = MEM_callocN<XrGrabData>(__func__);
181}
182
184{
185 XrGrabData *data = static_cast<XrGrabData *>(op->customdata);
187 op->customdata = nullptr;
188}
189
190static void wm_xr_grab_update(wmOperator *op, const wmXrActionData *actiondata)
191{
192 XrGrabData *data = static_cast<XrGrabData *>(op->customdata);
193
194 quat_to_mat4(data->mat_prev, actiondata->controller_rot);
195 copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
196
197 if (actiondata->bimanual) {
198 quat_to_mat4(data->mat_other_prev, actiondata->controller_rot_other);
199 copy_v3_v3(data->mat_other_prev[3], actiondata->controller_loc_other);
200 data->bimanual_prev = true;
201 }
202 else {
203 data->bimanual_prev = false;
204 }
205}
206
207static void orient_mat_z_normalized(float R[4][4], const float z_axis[3])
208{
209 const float scale = len_v3(R[0]);
210 float x_axis[3], y_axis[3];
211
212 cross_v3_v3v3(y_axis, z_axis, R[0]);
213 normalize_v3(y_axis);
214 mul_v3_v3fl(R[1], y_axis, scale);
215
216 cross_v3_v3v3(x_axis, R[1], z_axis);
217 normalize_v3(x_axis);
218 mul_v3_v3fl(R[0], x_axis, scale);
219
220 mul_v3_v3fl(R[2], z_axis, scale);
221}
222
223static void wm_xr_navlocks_apply(const float nav_mat[4][4],
224 const float nav_inv[4][4],
225 bool loc_lock,
226 bool locz_lock,
227 bool rotz_lock,
228 float r_prev[4][4],
229 float r_curr[4][4])
230{
231 /* Locked in base pose coordinates. */
232 float prev_base[4][4], curr_base[4][4];
233
234 mul_m4_m4m4(prev_base, nav_inv, r_prev);
235 mul_m4_m4m4(curr_base, nav_inv, r_curr);
236
237 if (rotz_lock) {
238 const float z_axis[3] = {0.0f, 0.0f, 1.0f};
239 orient_mat_z_normalized(prev_base, z_axis);
240 orient_mat_z_normalized(curr_base, z_axis);
241 }
242
243 if (loc_lock) {
244 copy_v3_v3(curr_base[3], prev_base[3]);
245 }
246 else if (locz_lock) {
247 curr_base[3][2] = prev_base[3][2];
248 }
249
250 mul_m4_m4m4(r_prev, nav_mat, prev_base);
251 mul_m4_m4m4(r_curr, nav_mat, curr_base);
252}
253
263static void wm_xr_grab_compute(const wmXrActionData *actiondata,
264 const XrGrabData *data,
265 const float nav_mat[4][4],
266 const float nav_inv[4][4],
267 bool reverse,
268 float r_delta[4][4])
269{
270 const bool nav_lock = (nav_mat && nav_inv);
271 float prev[4][4], curr[4][4];
272
273 if (!data->rot_lock) {
274 copy_m4_m4(prev, data->mat_prev);
275 zero_v3(prev[3]);
276 quat_to_mat4(curr, actiondata->controller_rot);
277 }
278 else {
279 unit_m4(prev);
280 unit_m4(curr);
281 }
282
283 if (!data->loc_lock || nav_lock) {
284 copy_v3_v3(prev[3], data->mat_prev[3]);
285 copy_v3_v3(curr[3], actiondata->controller_loc);
286 }
287
288 if (nav_lock) {
290 nav_mat, nav_inv, data->loc_lock, data->locz_lock, data->rotz_lock, prev, curr);
291 }
292
293 if (reverse) {
294 invert_m4(curr);
295 mul_m4_m4m4(r_delta, prev, curr);
296 }
297 else {
298 invert_m4(prev);
299 mul_m4_m4m4(r_delta, curr, prev);
300 }
301}
302
315static void wm_xr_grab_compute_bimanual(const wmXrActionData *actiondata,
316 const XrGrabData *data,
317 const float nav_mat[4][4],
318 const float nav_inv[4][4],
319 bool reverse,
320 float r_delta[4][4])
321{
322 const bool nav_lock = (nav_mat && nav_inv);
323 float prev[4][4], curr[4][4];
324 unit_m4(prev);
325 unit_m4(curr);
326
327 if (!data->rot_lock) {
328 /* Rotation. */
329 float x_axis_prev[3], x_axis_curr[3], y_axis_prev[3], y_axis_curr[3], z_axis_prev[3],
330 z_axis_curr[3];
331 float m0[3][3], m1[3][3];
332 quat_to_mat3(m0, actiondata->controller_rot);
333 quat_to_mat3(m1, actiondata->controller_rot_other);
334
335 /* X-axis is the base line between the two controllers. */
336 sub_v3_v3v3(x_axis_prev, data->mat_prev[3], data->mat_other_prev[3]);
337 sub_v3_v3v3(x_axis_curr, actiondata->controller_loc, actiondata->controller_loc_other);
338 /* Y-axis is the average of the controllers' y-axes. */
339 add_v3_v3v3(y_axis_prev, data->mat_prev[1], data->mat_other_prev[1]);
340 mul_v3_fl(y_axis_prev, 0.5f);
341 add_v3_v3v3(y_axis_curr, m0[1], m1[1]);
342 mul_v3_fl(y_axis_curr, 0.5f);
343 /* Z-axis is the cross product of the two. */
344 cross_v3_v3v3(z_axis_prev, x_axis_prev, y_axis_prev);
345 cross_v3_v3v3(z_axis_curr, x_axis_curr, y_axis_curr);
346 /* Fix the y-axis to be orthogonal. */
347 cross_v3_v3v3(y_axis_prev, z_axis_prev, x_axis_prev);
348 cross_v3_v3v3(y_axis_curr, z_axis_curr, x_axis_curr);
349 /* Normalize. */
350 normalize_v3_v3(prev[0], x_axis_prev);
351 normalize_v3_v3(prev[1], y_axis_prev);
352 normalize_v3_v3(prev[2], z_axis_prev);
353 normalize_v3_v3(curr[0], x_axis_curr);
354 normalize_v3_v3(curr[1], y_axis_curr);
355 normalize_v3_v3(curr[2], z_axis_curr);
356 }
357
358 if (!data->loc_lock || nav_lock) {
359 /* Translation: translation of the averaged controller locations. */
360 add_v3_v3v3(prev[3], data->mat_prev[3], data->mat_other_prev[3]);
361 mul_v3_fl(prev[3], 0.5f);
362 add_v3_v3v3(curr[3], actiondata->controller_loc, actiondata->controller_loc_other);
363 mul_v3_fl(curr[3], 0.5f);
364 }
365
366 if (!data->scale_lock) {
367 /* Scaling: distance between controllers. */
368 float scale, v[3];
369
370 sub_v3_v3v3(v, data->mat_prev[3], data->mat_other_prev[3]);
371 scale = len_v3(v);
372 mul_v3_fl(prev[0], scale);
373 mul_v3_fl(prev[1], scale);
374 mul_v3_fl(prev[2], scale);
375
376 sub_v3_v3v3(v, actiondata->controller_loc, actiondata->controller_loc_other);
377 scale = len_v3(v);
378 mul_v3_fl(curr[0], scale);
379 mul_v3_fl(curr[1], scale);
380 mul_v3_fl(curr[2], scale);
381 }
382
383 if (nav_lock) {
385 nav_mat, nav_inv, data->loc_lock, data->locz_lock, data->rotz_lock, prev, curr);
386 }
387
388 if (reverse) {
389 invert_m4(curr);
390 mul_m4_m4m4(r_delta, prev, curr);
391 }
392 else {
393 invert_m4(prev);
394 mul_m4_m4m4(r_delta, curr, prev);
395 }
396}
397
399
400/* -------------------------------------------------------------------- */
405
407 wmOperator *op,
408 const wmEvent *event)
409{
410 if (!wm_xr_operator_test_event(op, event)) {
412 }
413
414 const wmXrActionData *actiondata = static_cast<const wmXrActionData *>(event->customdata);
415
416 wm_xr_grab_init(op);
417 wm_xr_grab_update(op, actiondata);
418
420
422}
423
428
429static bool wm_xr_navigation_grab_can_do_bimanual(const wmXrActionData *actiondata,
430 const XrGrabData *data)
431{
432 /* Returns true if: 1) Bimanual interaction is currently occurring (i.e. inputs on both
433 * controllers are pressed) and 2) bimanual interaction occurred on the last update. This second
434 * part is needed to avoid "jumpy" navigation changes when transitioning from one-handed to
435 * two-handed interaction (see #wm_xr_grab_compute/compute_bimanual() for how navigation deltas
436 * are calculated). */
437 return (actiondata->bimanual && data->bimanual_prev);
438}
439
440static bool wm_xr_navigation_grab_is_bimanual_ending(const wmXrActionData *actiondata,
441 const XrGrabData *data)
442{
443 return (!actiondata->bimanual && data->bimanual_prev);
444}
445
446static bool wm_xr_navigation_grab_is_locked(const XrGrabData *data, const bool bimanual)
447{
448 if (bimanual) {
449 return data->loc_lock && data->rot_lock && data->scale_lock;
450 }
451 /* Ignore scale lock, as one-handed interaction cannot change navigation scale. */
452 return data->loc_lock && data->rot_lock;
453}
454
456 const wmXrActionData *actiondata,
457 const XrGrabData *data,
458 bool bimanual)
459{
460 GHOST_XrPose nav_pose;
461 float nav_scale;
462 float nav_mat[4][4], nav_inv[4][4], delta[4][4], out[4][4];
463
464 const bool need_navinv = (data->loc_lock || data->locz_lock || data->rotz_lock);
465
466 WM_xr_session_state_nav_location_get(xr, nav_pose.position);
467 WM_xr_session_state_nav_rotation_get(xr, nav_pose.orientation_quat);
468 WM_xr_session_state_nav_scale_get(xr, &nav_scale);
469
470 wm_xr_pose_scale_to_mat(&nav_pose, nav_scale, nav_mat);
471 if (need_navinv) {
472 wm_xr_pose_scale_to_imat(&nav_pose, nav_scale, nav_inv);
473 }
474
475 if (bimanual) {
477 data,
478 need_navinv ? nav_mat : nullptr,
479 need_navinv ? nav_inv : nullptr,
480 true,
481 delta);
482 }
483 else {
484 wm_xr_grab_compute(actiondata,
485 data,
486 need_navinv ? nav_mat : nullptr,
487 need_navinv ? nav_inv : nullptr,
488 true,
489 delta);
490 }
491
492 mul_m4_m4m4(out, delta, nav_mat);
493
494 /* Limit scale to reasonable values. */
495 nav_scale = len_v3(out[0]);
496
497 if (!(nav_scale < xr->session_settings.clip_start || nav_scale > xr->session_settings.clip_end))
498 {
500 if (!data->rot_lock) {
501 mat4_to_quat(nav_pose.orientation_quat, out);
502 normalize_qt(nav_pose.orientation_quat);
503 WM_xr_session_state_nav_rotation_set(xr, nav_pose.orientation_quat);
504 }
505 if (!data->scale_lock && bimanual) {
507 }
508 }
509}
510
511static void wm_xr_navigation_grab_bimanual_state_update(const wmXrActionData *actiondata,
513{
514 if (actiondata->bimanual) {
515 if (!data->bimanual_prev) {
516 quat_to_mat4(data->mat_prev, actiondata->controller_rot);
517 copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
518 quat_to_mat4(data->mat_other_prev, actiondata->controller_rot_other);
519 copy_v3_v3(data->mat_other_prev[3], actiondata->controller_loc_other);
520 }
521 data->bimanual_prev = true;
522 }
523 else {
524 if (data->bimanual_prev) {
525 quat_to_mat4(data->mat_prev, actiondata->controller_rot);
526 copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
527 }
528 data->bimanual_prev = false;
529 }
530}
531
533 wmOperator *op,
534 const wmEvent *event)
535{
536 if (!wm_xr_operator_test_event(op, event)) {
538 }
539
540 const wmXrActionData *actiondata = static_cast<const wmXrActionData *>(event->customdata);
541 XrGrabData *data = static_cast<XrGrabData *>(op->customdata);
543 wmXrData *xr = &wm->xr;
544
545 const bool do_bimanual = wm_xr_navigation_grab_can_do_bimanual(actiondata, data);
546
547 data->loc_lock = RNA_boolean_get(op->ptr, "lock_location");
548 data->locz_lock = RNA_boolean_get(op->ptr, "lock_location_z");
549 data->rot_lock = RNA_boolean_get(op->ptr, "lock_rotation");
550 data->rotz_lock = RNA_boolean_get(op->ptr, "lock_rotation_z");
551 data->scale_lock = RNA_boolean_get(op->ptr, "lock_scale");
552
553 /* Check if navigation is locked. */
554 if (!wm_xr_navigation_grab_is_locked(data, do_bimanual)) {
555 /* Prevent unwanted snapping (i.e. "jumpy" navigation changes when transitioning from
556 * two-handed to one-handed interaction) at the end of a bimanual interaction. */
558 wm_xr_navigation_grab_apply(xr, actiondata, data, do_bimanual);
559 }
560 }
561
563
564 /* NOTE: #KM_PRESS and #KM_RELEASE are the only two values supported by XR events during event
565 * dispatching (see #wm_xr_session_action_states_interpret()). For modal XR operators, modal
566 * handling starts when an input is "pressed" (action state exceeds the action threshold) and
567 * ends when the input is "released" (state falls below the threshold). */
568 switch (event->val) {
569 case KM_PRESS:
571 case KM_RELEASE:
573 return OPERATOR_FINISHED;
574 default:
577 return OPERATOR_CANCELLED;
578 }
579}
580
582{
583 /* Identifiers. */
584 ot->name = "XR Navigation Grab";
585 ot->idname = "WM_OT_xr_navigation_grab";
586 ot->description = "Navigate the VR scene by grabbing with controllers";
587
588 /* Callbacks. */
593
594 /* Properties. */
596 ot->srna, "lock_location", false, "Lock Location", "Prevent changes to viewer location");
598 ot->srna, "lock_location_z", false, "Lock Elevation", "Prevent changes to viewer elevation");
600 ot->srna, "lock_rotation", false, "Lock Rotation", "Prevent changes to viewer rotation");
601 RNA_def_boolean(ot->srna,
602 "lock_rotation_z",
603 false,
604 "Lock Up Orientation",
605 "Prevent changes to viewer up orientation");
606 RNA_def_boolean(ot->srna, "lock_scale", false, "Lock Scale", "Prevent changes to viewer scale");
607}
608
610
611/* -------------------------------------------------------------------- */
614
615static const float g_xr_default_raycast_axis[3] = {0.0f, 0.0f, -1.0f};
616static const float g_xr_default_raycast_color[4] = {0.35f, 0.35f, 1.0f, 1.0f};
617
620 float origin[3];
621 float direction[3];
622 float end[3];
623 float color[4];
625};
626
627static void wm_xr_raycast_draw(const bContext * /*C*/, ARegion * /*region*/, void *customdata)
628{
629 const XrRaycastData *data = static_cast<const XrRaycastData *>(customdata);
630
633
634 if (data->from_viewer) {
636 immUniformColor4fv(data->color);
637
639 GPU_point_size(7.0f);
640
642 immVertex3fv(pos, data->end);
643 immEnd();
644 }
645 else {
648
649 float viewport[4];
650 GPU_viewport_size_get_f(viewport);
651 immUniform2fv("viewportSize", &viewport[2]);
652
653 immUniform1f("lineWidth", 3.0f * U.pixelsize);
654
656
659 immVertex3fv(pos, data->origin);
660 immAttr4fv(col, data->color);
661 immVertex3fv(pos, data->end);
662 immEnd();
663 }
664
666}
667
669{
670 BLI_assert(op->customdata == nullptr);
671
673
675 if (!st) {
676 return;
677 }
678
680 if (!art) {
681 return;
682 }
683
684 XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
685 data->draw_handle = ED_region_draw_cb_activate(
687}
688
690{
691 if (!op->customdata) {
692 return;
693 }
694
695 XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
696
698 if (st) {
700 if (art) {
701 ED_region_draw_cb_exit(art, data->draw_handle);
702 }
703 }
704
706 op->customdata = nullptr;
707}
708
710 const wmXrData *xr,
711 const wmXrActionData *actiondata)
712{
713 XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
714 float ray_length, axis[3];
715
716 data->from_viewer = RNA_boolean_get(op->ptr, "from_viewer");
717 RNA_float_get_array(op->ptr, "axis", axis);
718 RNA_float_get_array(op->ptr, "color", data->color);
719
720 if (data->from_viewer) {
721 float viewer_rot[4];
724 mul_qt_v3(viewer_rot, axis);
725 ray_length = (xr->session_settings.clip_start + xr->session_settings.clip_end) / 2.0f;
726 }
727 else {
728 copy_v3_v3(data->origin, actiondata->controller_loc);
729 mul_qt_v3(actiondata->controller_rot, axis);
730 ray_length = xr->session_settings.clip_end;
731 }
732
733 copy_v3_v3(data->direction, axis);
734 madd_v3_v3v3fl(data->end, data->origin, data->direction, ray_length);
735}
736
737static void wm_xr_raycast(Scene *scene,
738 Depsgraph *depsgraph,
739 const float origin[3],
740 const float direction[3],
741 float *ray_dist,
742 bool selectable_only,
743 float r_location[3],
744 float r_normal[3],
745 int *r_index,
746 const Object **r_ob,
747 float r_obmat[4][4])
748{
749 /* Uses same raycast method as Scene.ray_cast(). */
752
754 params.snap_target_select = (selectable_only ? SCE_SNAP_TARGET_ONLY_SELECTABLE :
757 depsgraph,
758 nullptr,
759 &params,
760 origin,
761 direction,
762 ray_dist,
763 r_location,
764 r_normal,
765 r_index,
766 r_ob,
767 r_obmat);
768
770}
771
773
774/* -------------------------------------------------------------------- */
780
781#define XR_DEFAULT_FLY_SPEED_MOVE 0.054f
782
798
799struct XrFlyData {
800 float viewer_rot[4];
801 double time_prev;
802};
803
804static void wm_xr_fly_init(wmOperator *op, const wmXrData *xr)
805{
806 BLI_assert(op->customdata == nullptr);
807
809 op->customdata = data;
810
812 data->time_prev = BLI_time_now_seconds();
813}
814
816{
817 XrFlyData *data = static_cast<XrFlyData *>(op->customdata);
819 op->customdata = nullptr;
820}
821
823 float speed,
824 const float ref_quat[4],
825 const float nav_mat[4][4],
826 bool locz_lock,
827 float r_delta[4][4])
828{
829 float ref_axes[3][3];
830 quat_to_mat3(ref_axes, ref_quat);
831
832 unit_m4(r_delta);
833
834 switch (mode) {
835 /* Navigation space reference. */
836 case XR_FLY_FORWARD:
837 madd_v3_v3fl(r_delta[3], ref_axes[1], speed);
838 return;
839 case XR_FLY_BACK:
840 madd_v3_v3fl(r_delta[3], ref_axes[1], -speed);
841 return;
842 case XR_FLY_LEFT:
843 madd_v3_v3fl(r_delta[3], ref_axes[0], -speed);
844 return;
845 case XR_FLY_RIGHT:
846 madd_v3_v3fl(r_delta[3], ref_axes[0], speed);
847 return;
848 case XR_FLY_UP:
849 case XR_FLY_DOWN:
850 if (!locz_lock) {
851 madd_v3_v3fl(r_delta[3], ref_axes[2], (mode == XR_FLY_UP) ? speed : -speed);
852 }
853 return;
854 /* Viewer/controller space reference. */
857 negate_v3_v3(r_delta[3], ref_axes[2]);
858 break;
860 copy_v3_v3(r_delta[3], ref_axes[2]);
861 break;
863 negate_v3_v3(r_delta[3], ref_axes[0]);
864 break;
866 copy_v3_v3(r_delta[3], ref_axes[0]);
867 break;
868 /* Unused. */
869 case XR_FLY_TURNLEFT:
870 case XR_FLY_TURNRIGHT:
872 return;
873 }
874
875 if (locz_lock) {
876 /* Lock elevation in navigation space. */
877 float z_axis[3], projected[3];
878
879 normalize_v3_v3(z_axis, nav_mat[2]);
880 project_v3_v3v3_normalized(projected, r_delta[3], z_axis);
881 sub_v3_v3(r_delta[3], projected);
882
883 normalize_v3(r_delta[3]);
884 }
885
886 mul_v3_fl(r_delta[3], speed);
887}
888
890 float speed,
891 const float viewer_mat[4][4],
892 const float nav_mat[4][4],
893 const float nav_inv[4][4],
894 float r_delta[4][4])
895{
897
898 float z_axis[3], m[3][3], prev[4][4], curr[4][4];
899
900 /* Turn around Z-axis in navigation space. */
901 normalize_v3_v3(z_axis, nav_mat[2]);
902 axis_angle_normalized_to_mat3(m, z_axis, (mode == XR_FLY_TURNLEFT) ? speed : -speed);
903 copy_m4_m3(r_delta, m);
904
905 copy_m4_m4(prev, viewer_mat);
906 mul_m4_m4m4(curr, r_delta, viewer_mat);
907
908 /* Lock location in base pose space. */
909 wm_xr_navlocks_apply(nav_mat, nav_inv, true, false, false, prev, curr);
910
911 invert_m4(prev);
912 mul_m4_m4m4(r_delta, curr, prev);
913}
914
916 const float nav_rotation[4],
917 float r_rotation[4])
918{
919 /* Apply nav rotation to base pose Z-rotation. */
920 float base_eul[3], base_quatz[4];
921 quat_to_eul(base_eul, xr->runtime->session_state.prev_base_pose.orientation_quat);
922 axis_angle_to_quat_single(base_quatz, 'Z', base_eul[2]);
923 mul_qt_qtqt(r_rotation, nav_rotation, base_quatz);
924}
925
927 wmOperator *op,
928 const wmEvent *event)
929{
930 if (!wm_xr_operator_test_event(op, event)) {
932 }
933
935
936 wm_xr_fly_init(op, &wm->xr);
937
939
941}
942
947
949 wmOperator *op,
950 const wmEvent *event)
951{
952 if (!wm_xr_operator_test_event(op, event)) {
954 }
955
956 if (event->val == KM_RELEASE) {
958 return OPERATOR_FINISHED;
959 }
960
961 const wmXrActionData *actiondata = static_cast<const wmXrActionData *>(event->customdata);
962 XrFlyData *data = static_cast<XrFlyData *>(op->customdata);
964 wmXrData *xr = &wm->xr;
965 eXrFlyMode mode;
966 bool turn, locz_lock, dir_lock, speed_frame_based;
967 bool speed_interp_cubic = false;
968 float speed, speed_max, speed_p0[2], speed_p1[2];
969 GHOST_XrPose nav_pose;
970 float nav_mat[4][4], delta[4][4], out[4][4];
971
972 const double time_now = BLI_time_now_seconds();
973
974 mode = (eXrFlyMode)RNA_enum_get(op->ptr, "mode");
976
977 locz_lock = RNA_boolean_get(op->ptr, "lock_location_z");
978 dir_lock = RNA_boolean_get(op->ptr, "lock_direction");
979 speed_frame_based = RNA_boolean_get(op->ptr, "speed_frame_based");
980 speed = RNA_float_get(op->ptr, "speed_min");
981 speed_max = RNA_float_get(op->ptr, "speed_max");
982
983 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "speed_interpolation0");
984 if (prop && RNA_property_is_set(op->ptr, prop)) {
985 RNA_property_float_get_array(op->ptr, prop, speed_p0);
986 speed_interp_cubic = true;
987 }
988 else {
989 speed_p0[0] = speed_p0[1] = 0.0f;
990 }
991
992 prop = RNA_struct_find_property(op->ptr, "speed_interpolation1");
993 if (prop && RNA_property_is_set(op->ptr, prop)) {
994 RNA_property_float_get_array(op->ptr, prop, speed_p1);
995 speed_interp_cubic = true;
996 }
997 else {
998 speed_p1[0] = speed_p1[1] = 1.0f;
999 }
1000
1001 /* Ensure valid interpolation. */
1002 if (speed_max < speed) {
1003 speed_max = speed;
1004 }
1005
1006 /* Interpolate between min/max speeds based on button state. */
1007 switch (actiondata->type) {
1008 case XR_BOOLEAN_INPUT:
1009 speed = speed_max;
1010 break;
1011 case XR_FLOAT_INPUT:
1012 case XR_VECTOR2F_INPUT: {
1013 float state = (actiondata->type == XR_FLOAT_INPUT) ? fabsf(actiondata->state[0]) :
1014 len_v2(actiondata->state);
1015 float speed_t = (actiondata->float_threshold < 1.0f) ?
1016 (state - actiondata->float_threshold) /
1017 (1.0f - actiondata->float_threshold) :
1018 1.0f;
1019 if (speed_interp_cubic) {
1020 float start[2], end[2], p[2];
1021
1022 start[0] = 0.0f;
1023 start[1] = speed;
1024 speed_p0[1] = speed + speed_p0[1] * (speed_max - speed);
1025 speed_p1[1] = speed + speed_p1[1] * (speed_max - speed);
1026 end[0] = 1.0f;
1027 end[1] = speed_max;
1028
1029 interp_v2_v2v2v2v2_cubic(p, start, speed_p0, speed_p1, end, speed_t);
1030 speed = p[1];
1031 }
1032 else {
1033 speed += speed_t * (speed_max - speed);
1034 }
1035 break;
1036 }
1037 case XR_POSE_INPUT:
1040 break;
1041 }
1042
1043 if (!speed_frame_based) {
1044 /* Adjust speed based on last update time. */
1045 speed *= time_now - data->time_prev;
1046 }
1047 data->time_prev = time_now;
1048
1049 WM_xr_session_state_nav_location_get(xr, nav_pose.position);
1050 WM_xr_session_state_nav_rotation_get(xr, nav_pose.orientation_quat);
1051 wm_xr_pose_to_mat(&nav_pose, nav_mat);
1052
1053 if (turn) {
1054 if (dir_lock) {
1055 unit_m4(delta);
1056 }
1057 else {
1058 GHOST_XrPose viewer_pose;
1059 float viewer_mat[4][4], nav_inv[4][4];
1060
1061 WM_xr_session_state_viewer_pose_location_get(xr, viewer_pose.position);
1062 WM_xr_session_state_viewer_pose_rotation_get(xr, viewer_pose.orientation_quat);
1063 wm_xr_pose_to_mat(&viewer_pose, viewer_mat);
1064 wm_xr_pose_to_imat(&nav_pose, nav_inv);
1065
1066 wm_xr_fly_compute_turn(mode, speed, viewer_mat, nav_mat, nav_inv, delta);
1067 }
1068 }
1069 else {
1070 float nav_scale, ref_quat[4];
1071
1072 /* Adjust speed for base and navigation scale. */
1073 WM_xr_session_state_nav_scale_get(xr, &nav_scale);
1074 speed *= xr->session_settings.base_scale * nav_scale;
1075
1076 switch (mode) {
1077 /* Move relative to navigation space. */
1078 case XR_FLY_FORWARD:
1079 case XR_FLY_BACK:
1080 case XR_FLY_LEFT:
1081 case XR_FLY_RIGHT:
1082 case XR_FLY_UP:
1083 case XR_FLY_DOWN:
1084 wm_xr_basenav_rotation_calc(xr, nav_pose.orientation_quat, ref_quat);
1085 break;
1086 /* Move relative to viewer. */
1088 case XR_FLY_VIEWER_BACK:
1089 case XR_FLY_VIEWER_LEFT:
1091 if (dir_lock) {
1092 copy_qt_qt(ref_quat, data->viewer_rot);
1093 }
1094 else {
1096 }
1097 break;
1098 /* Move relative to controller. */
1100 copy_qt_qt(ref_quat, actiondata->controller_rot);
1101 break;
1102 /* Unused. */
1103 case XR_FLY_TURNLEFT:
1104 case XR_FLY_TURNRIGHT:
1106 break;
1107 }
1108
1109 wm_xr_fly_compute_move(mode, speed, ref_quat, nav_mat, locz_lock, delta);
1110 }
1111
1112 mul_m4_m4m4(out, delta, nav_mat);
1113
1115 if (turn) {
1116 mat4_to_quat(nav_pose.orientation_quat, out);
1117 WM_xr_session_state_nav_rotation_set(xr, nav_pose.orientation_quat);
1118 }
1119
1120 if (event->val == KM_PRESS) {
1122 }
1123
1124 /* XR events currently only support press and release. */
1126 wm_xr_fly_uninit(op);
1127 return OPERATOR_CANCELLED;
1128}
1129
1131{
1132 PropertyRNA *prop;
1133
1134 /* Identifiers. */
1135 ot->name = "XR Navigation Fly";
1136 ot->idname = "WM_OT_xr_navigation_fly";
1137 ot->description = "Move/turn relative to the VR viewer or controller";
1138
1139 /* Callbacks. */
1144
1145 /* Properties. */
1146 static const EnumPropertyItem fly_modes[] = {
1147 {XR_FLY_FORWARD, "FORWARD", 0, "Forward", "Move along navigation forward axis"},
1148 {XR_FLY_BACK, "BACK", 0, "Back", "Move along navigation back axis"},
1149 {XR_FLY_LEFT, "LEFT", 0, "Left", "Move along navigation left axis"},
1150 {XR_FLY_RIGHT, "RIGHT", 0, "Right", "Move along navigation right axis"},
1151 {XR_FLY_UP, "UP", 0, "Up", "Move along navigation up axis"},
1152 {XR_FLY_DOWN, "DOWN", 0, "Down", "Move along navigation down axis"},
1154 "TURNLEFT",
1155 0,
1156 "Turn Left",
1157 "Turn counter-clockwise around navigation up axis"},
1158 {XR_FLY_TURNRIGHT, "TURNRIGHT", 0, "Turn Right", "Turn clockwise around navigation up axis"},
1160 "VIEWER_FORWARD",
1161 0,
1162 "Viewer Forward",
1163 "Move along viewer's forward axis"},
1164 {XR_FLY_VIEWER_BACK, "VIEWER_BACK", 0, "Viewer Back", "Move along viewer's back axis"},
1165 {XR_FLY_VIEWER_LEFT, "VIEWER_LEFT", 0, "Viewer Left", "Move along viewer's left axis"},
1166 {XR_FLY_VIEWER_RIGHT, "VIEWER_RIGHT", 0, "Viewer Right", "Move along viewer's right axis"},
1168 "CONTROLLER_FORWARD",
1169 0,
1170 "Controller Forward",
1171 "Move along controller's forward axis"},
1172 {0, nullptr, 0, nullptr, nullptr},
1173 };
1174
1175 static const float default_speed_p0[2] = {0.0f, 0.0f};
1176 static const float default_speed_p1[2] = {1.0f, 1.0f};
1177
1178 prop = RNA_def_enum(ot->srna, "mode", fly_modes, XR_FLY_VIEWER_FORWARD, "Mode", "Fly mode");
1180
1182 ot->srna, "lock_location_z", false, "Lock Elevation", "Prevent changes to viewer elevation");
1183 RNA_def_boolean(ot->srna,
1184 "lock_direction",
1185 false,
1186 "Lock Direction",
1187 "Limit movement to viewer's initial direction");
1188 RNA_def_boolean(ot->srna,
1189 "speed_frame_based",
1190 true,
1191 "Frame Based Speed",
1192 "Apply fixed movement deltas every update");
1193 RNA_def_float(ot->srna,
1194 "speed_min",
1196 0.0f,
1197 1000.0f,
1198 "Minimum Speed",
1199 "Minimum move (turn) speed in meters (radians) per second or frame",
1200 0.0f,
1201 1000.0f);
1202 RNA_def_float(ot->srna,
1203 "speed_max",
1205 0.0f,
1206 1000.0f,
1207 "Maximum Speed",
1208 "Maximum move (turn) speed in meters (radians) per second or frame",
1209 0.0f,
1210 1000.0f);
1212 "speed_interpolation0",
1213 2,
1214 default_speed_p0,
1215 0.0f,
1216 1.0f,
1217 "Speed Interpolation 0",
1218 "First cubic spline control point between min/max speeds",
1219 0.0f,
1220 1.0f);
1222 "speed_interpolation1",
1223 2,
1224 default_speed_p1,
1225 0.0f,
1226 1.0f,
1227 "Speed Interpolation 1",
1228 "Second cubic spline control point between min/max speeds",
1229 0.0f,
1230 1.0f);
1231}
1232
1234
1235/* -------------------------------------------------------------------- */
1240
1242 wmXrData *xr,
1243 const float origin[3],
1244 const float direction[3],
1245 float *ray_dist,
1246 bool selectable_only,
1247 const bool teleport_axes[3],
1248 float teleport_t,
1249 float teleport_ofs)
1250{
1251 Scene *scene = CTX_data_scene(C);
1253 float location[3];
1254 float normal[3];
1255 int index;
1256 const Object *ob = nullptr;
1257 float obmat[4][4];
1258
1259 wm_xr_raycast(scene,
1260 depsgraph,
1261 origin,
1262 direction,
1263 ray_dist,
1264 selectable_only,
1265 location,
1266 normal,
1267 &index,
1268 &ob,
1269 obmat);
1270
1271 /* Teleport. */
1272 if (ob) {
1273 float nav_location[3], nav_rotation[4], viewer_location[3];
1274 float nav_axes[3][3], projected[3], v0[3], v1[3];
1275 float out[3] = {0.0f, 0.0f, 0.0f};
1276
1277 WM_xr_session_state_nav_location_get(xr, nav_location);
1278 WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
1280
1281 wm_xr_basenav_rotation_calc(xr, nav_rotation, nav_rotation);
1282 quat_to_mat3(nav_axes, nav_rotation);
1283
1284 /* Project locations onto navigation axes. */
1285 for (int a = 0; a < 3; ++a) {
1286 project_v3_v3v3_normalized(projected, nav_location, nav_axes[a]);
1287 if (teleport_axes[a]) {
1288 /* Interpolate between projected locations. */
1289 project_v3_v3v3_normalized(v0, location, nav_axes[a]);
1290 project_v3_v3v3_normalized(v1, viewer_location, nav_axes[a]);
1291 sub_v3_v3(v0, v1);
1292 madd_v3_v3fl(projected, v0, teleport_t);
1293 /* Subtract offset. */
1294 project_v3_v3v3_normalized(v0, normal, nav_axes[a]);
1295 madd_v3_v3fl(projected, v0, teleport_ofs);
1296 }
1297 /* Add to final location. */
1298 add_v3_v3(out, projected);
1299 }
1300
1302 }
1303}
1304
1306 wmOperator *op,
1307 const wmEvent *event)
1308{
1309 if (!wm_xr_operator_test_event(op, event)) {
1310 return OPERATOR_PASS_THROUGH;
1311 }
1312
1314
1315 const wmOperatorStatus retval = op->type->modal(C, op, event);
1316 OPERATOR_RETVAL_CHECK(retval);
1317
1318 if (retval & OPERATOR_RUNNING_MODAL) {
1320 }
1321
1322 return retval;
1323}
1324
1329
1331 wmOperator *op,
1332 const wmEvent *event)
1333{
1334 if (!wm_xr_operator_test_event(op, event)) {
1335 return OPERATOR_PASS_THROUGH;
1336 }
1337
1338 const wmXrActionData *actiondata = static_cast<const wmXrActionData *>(event->customdata);
1340 wmXrData *xr = &wm->xr;
1341
1342 wm_xr_raycast_update(op, xr, actiondata);
1343
1344 switch (event->val) {
1345 case KM_PRESS:
1347 case KM_RELEASE: {
1348 XrRaycastData *data = static_cast<XrRaycastData *>(op->customdata);
1349 bool selectable_only, teleport_axes[3];
1350 float teleport_t, teleport_ofs, ray_dist;
1351
1352 RNA_boolean_get_array(op->ptr, "teleport_axes", teleport_axes);
1353 teleport_t = RNA_float_get(op->ptr, "interpolation");
1354 teleport_ofs = RNA_float_get(op->ptr, "offset");
1355 selectable_only = RNA_boolean_get(op->ptr, "selectable_only");
1356 ray_dist = RNA_float_get(op->ptr, "distance");
1357
1359 xr,
1360 data->origin,
1361 data->direction,
1362 &ray_dist,
1363 selectable_only,
1364 teleport_axes,
1365 teleport_t,
1366 teleport_ofs);
1367
1369
1370 return OPERATOR_FINISHED;
1371 }
1372 default:
1373 /* XR events currently only support press and release. */
1376 return OPERATOR_CANCELLED;
1377 }
1378}
1379
1381{
1382 /* Identifiers. */
1383 ot->name = "XR Navigation Teleport";
1384 ot->idname = "WM_OT_xr_navigation_teleport";
1385 ot->description = "Set VR viewer location to controller raycast hit location";
1386
1387 /* Callbacks. */
1392
1393 /* Properties. */
1394 static const bool default_teleport_axes[3] = {true, true, true};
1395
1397 "teleport_axes",
1398 3,
1399 default_teleport_axes,
1400 "Teleport Axes",
1401 "Enabled teleport axes in navigation space");
1402 RNA_def_float(ot->srna,
1403 "interpolation",
1404 1.0f,
1405 0.0f,
1406 1.0f,
1407 "Interpolation",
1408 "Interpolation factor between viewer and hit locations",
1409 0.0f,
1410 1.0f);
1411 RNA_def_float(ot->srna,
1412 "offset",
1413 0.0f,
1414 0.0f,
1415 FLT_MAX,
1416 "Offset",
1417 "Offset along hit normal to subtract from final location",
1418 0.0f,
1419 FLT_MAX);
1420 RNA_def_boolean(ot->srna,
1421 "selectable_only",
1422 true,
1423 "Selectable Only",
1424 "Only allow selectable objects to influence raycast result");
1425 RNA_def_float(ot->srna,
1426 "distance",
1428 0.0,
1430 "",
1431 "Maximum raycast distance",
1432 0.0,
1435 ot->srna, "from_viewer", false, "From Viewer", "Use viewer pose as raycast origin");
1437 "axis",
1438 3,
1440 -1.0f,
1441 1.0f,
1442 "Axis",
1443 "Raycast axis in controller/viewer space",
1444 -1.0f,
1445 1.0f);
1446 RNA_def_float_color(ot->srna,
1447 "color",
1448 4,
1450 0.0f,
1451 1.0f,
1452 "Color",
1453 "Raycast color",
1454 0.0f,
1455 1.0f);
1456}
1457
1459
1460/* -------------------------------------------------------------------- */
1465
1467{
1469 wmXrData *xr = &wm->xr;
1470 bool reset_loc, reset_rot, reset_scale;
1471
1472 reset_loc = RNA_boolean_get(op->ptr, "location");
1473 reset_rot = RNA_boolean_get(op->ptr, "rotation");
1474 reset_scale = RNA_boolean_get(op->ptr, "scale");
1475
1476 if (reset_loc) {
1477 float loc[3];
1478 if (!reset_scale) {
1479 float nav_rotation[4], nav_scale;
1480
1481 WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
1482 WM_xr_session_state_nav_scale_get(xr, &nav_scale);
1483
1484 /* Adjust location based on scale. */
1485 mul_v3_v3fl(loc, xr->runtime->session_state.prev_base_pose.position, nav_scale);
1486 sub_v3_v3(loc, xr->runtime->session_state.prev_base_pose.position);
1487 mul_qt_v3(nav_rotation, loc);
1488 negate_v3(loc);
1489 }
1490 else {
1491 zero_v3(loc);
1492 }
1494 }
1495
1496 if (reset_rot) {
1497 float rot[4];
1498 unit_qt(rot);
1500 }
1501
1502 if (reset_scale) {
1503 if (!reset_loc) {
1504 float nav_location[3], nav_rotation[4], nav_scale;
1505 float nav_axes[3][3], v[3];
1506
1507 WM_xr_session_state_nav_location_get(xr, nav_location);
1508 WM_xr_session_state_nav_rotation_get(xr, nav_rotation);
1509 WM_xr_session_state_nav_scale_get(xr, &nav_scale);
1510
1511 /* Offset any location changes when changing scale. */
1512 mul_v3_v3fl(v, xr->runtime->session_state.prev_base_pose.position, nav_scale);
1514 mul_qt_v3(nav_rotation, v);
1515 add_v3_v3(nav_location, v);
1516
1517 /* Reset elevation to base pose value. */
1518 quat_to_mat3(nav_axes, nav_rotation);
1519 project_v3_v3v3_normalized(v, nav_location, nav_axes[2]);
1520 sub_v3_v3(nav_location, v);
1521
1522 WM_xr_session_state_nav_location_set(xr, nav_location);
1523 }
1525 }
1526
1527 return OPERATOR_FINISHED;
1528}
1529
1531{
1532 /* Identifiers. */
1533 ot->name = "XR Navigation Reset";
1534 ot->idname = "WM_OT_xr_navigation_reset";
1535 ot->description = "Reset VR navigation deltas relative to session base pose";
1536
1537 /* Callbacks. */
1540
1541 /* Properties. */
1542 RNA_def_boolean(ot->srna, "location", true, "Location", "Reset location deltas");
1543 RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "Reset rotation deltas");
1544 RNA_def_boolean(ot->srna, "scale", true, "Scale", "Reset scale deltas");
1545}
1546
1548
1549/* -------------------------------------------------------------------- */
1552
1561
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:996
SpaceType * BKE_spacetype_from_id(int spaceid)
Definition screen.cc:251
ARegionType * BKE_regiontype_from_id(const SpaceType *st, int regionid)
Definition screen.cc:261
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BVH_RAYCAST_DIST_MAX
#define LISTBASE_FOREACH(type, var, list)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4(float mat[4][4])
void unit_m4(float m[4][4])
void quat_to_mat3(float m[3][3], const float q[4])
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
void axis_angle_to_quat_single(float q[4], char axis, float angle)
float normalize_qt(float q[4])
void quat_to_mat4(float m[4][4], const float q[4])
void mul_qt_v3(const float q[4], float r[3])
void 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.cc:65
#define ELEM(...)
#define BLT_I18NCONTEXT_NAVIGATION
@ SCE_SNAP_TARGET_ONLY_SELECTABLE
@ SCE_SNAP_TARGET_ALL
@ RGN_TYPE_XR
@ SPACE_VIEW3D
@ V3D_XR_SESSION_MIRROR
@ V3D_RUNTIME_XR_SESSION_ROOT
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
#define OPERATOR_RETVAL_CHECK(ret)
@ 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)
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:172
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:114
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:273
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#define NC_WM
Definition WM_types.hh:371
@ KM_PRESS
Definition WM_types.hh:308
@ KM_RELEASE
Definition WM_types.hh:309
#define ND_XR_DATA_CHANGED
Definition WM_types.hh:415
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
#define U
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
#define fabsf(x)
#define rot(x, k)
uint pos
uint col
#define out
#define MEM_SAFE_FREE(v)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
static ulong state[N]
#define R
bool 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])
void snap_object_context_destroy(SnapObjectContext *sctx)
SnapObjectContext * snap_object_context_create(Scene *scene, int flag)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
void RNA_boolean_get_array(PointerRNA *ptr, const char *name, bool *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const bool *default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
#define FLT_MAX
Definition stdcycles.h:14
void * first
ListBase wm
Definition BKE_main.hh:276
ListBase screens
Definition BKE_main.hh:261
View3D_Runtime runtime
float viewer_rot[4]
float mat_other_prev[4][4]
float mat_prev[4][4]
wmEventType type
Definition WM_types.hh:754
short custom
Definition WM_types.hh:790
short val
Definition WM_types.hh:756
void * customdata
Definition WM_types.hh:804
wmOperatorStatus(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1078
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_XR_ACTION
@ EVT_DATA_XR
wmOperatorType * ot
Definition wm_files.cc:4226
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:56
void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4])
Definition wm_xr_draw.cc:37
void wm_xr_pose_scale_to_mat(const GHOST_XrPose *pose, float scale, float r_mat[4][4])
Definition wm_xr_draw.cc:43
void wm_xr_pose_scale_to_imat(const GHOST_XrPose *pose, float scale, float r_imat[4][4])
Definition wm_xr_draw.cc:61
void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4])
Definition wm_xr_draw.cc:53
static void orient_mat_z_normalized(float R[4][4], const float z_axis[3])
static void wm_xr_grab_init(wmOperator *op)
static void wm_xr_navigation_teleport(bContext *C, wmXrData *xr, const float origin[3], const float direction[3], float *ray_dist, bool selectable_only, const bool teleport_axes[3], float teleport_t, float teleport_ofs)
static void wm_xr_fly_init(wmOperator *op, const wmXrData *xr)
static void wm_xr_navigation_grab_bimanual_state_update(const wmXrActionData *actiondata, XrGrabData *data)
static void wm_xr_basenav_rotation_calc(const wmXrData *xr, const float nav_rotation[4], float r_rotation[4])
static wmOperatorStatus wm_xr_navigation_reset_exec(bContext *C, wmOperator *op)
static void wm_xr_grab_uninit(wmOperator *op)
static void WM_OT_xr_navigation_fly(wmOperatorType *ot)
static wmOperatorStatus wm_xr_navigation_teleport_exec(bContext *, wmOperator *)
static void wm_xr_navigation_grab_apply(wmXrData *xr, const wmXrActionData *actiondata, const XrGrabData *data, bool bimanual)
static void wm_xr_navlocks_apply(const float nav_mat[4][4], const float nav_inv[4][4], bool loc_lock, bool locz_lock, bool rotz_lock, float r_prev[4][4], float r_curr[4][4])
static bool wm_xr_navigation_grab_is_bimanual_ending(const wmXrActionData *actiondata, const XrGrabData *data)
static wmOperatorStatus wm_xr_navigation_fly_exec(bContext *, wmOperator *)
static void wm_xr_grab_compute_bimanual(const wmXrActionData *actiondata, const XrGrabData *data, const float nav_mat[4][4], const float nav_inv[4][4], bool reverse, float r_delta[4][4])
static void wm_xr_fly_uninit(wmOperator *op)
static bool wm_xr_operator_sessionactive(bContext *C)
#define XR_DEFAULT_FLY_SPEED_MOVE
static void wm_xr_raycast_uninit(wmOperator *op)
static wmOperatorStatus wm_xr_navigation_fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
void wm_xr_operatortypes_register()
static void wm_xr_raycast_update(wmOperator *op, const wmXrData *xr, const wmXrActionData *actiondata)
static bool wm_xr_navigation_grab_is_locked(const XrGrabData *data, const bool bimanual)
static void wm_xr_session_update_screen_on_exit_cb(const wmXrData *xr_data)
static wmOperatorStatus wm_xr_session_toggle_exec(bContext *C, wmOperator *)
static void wm_xr_session_update_screen(Main *bmain, const wmXrData *xr_data)
static bool wm_xr_operator_test_event(const wmOperator *op, const wmEvent *event)
static bool wm_xr_navigation_grab_can_do_bimanual(const wmXrActionData *actiondata, const XrGrabData *data)
static void WM_OT_xr_navigation_teleport(wmOperatorType *ot)
static void wm_xr_grab_update(wmOperator *op, const wmXrActionData *actiondata)
static void wm_xr_raycast(Scene *scene, Depsgraph *depsgraph, const float origin[3], const float direction[3], float *ray_dist, bool selectable_only, float r_location[3], float r_normal[3], int *r_index, const Object **r_ob, float r_obmat[4][4])
static const float g_xr_default_raycast_color[4]
static wmOperatorStatus wm_xr_navigation_grab_modal(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus wm_xr_navigation_teleport_modal(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus wm_xr_navigation_fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void WM_OT_xr_navigation_reset(wmOperatorType *ot)
static wmOperatorStatus wm_xr_navigation_teleport_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static const float g_xr_default_raycast_axis[3]
static wmOperatorStatus wm_xr_navigation_grab_exec(bContext *, wmOperator *)
static void WM_OT_xr_navigation_grab(wmOperatorType *ot)
@ XR_FLY_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 wmOperatorStatus wm_xr_navigation_grab_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void wm_xr_fly_compute_turn(eXrFlyMode mode, float speed, const float viewer_mat[4][4], const float nav_mat[4][4], const float nav_inv[4][4], float r_delta[4][4])
void WM_xr_session_state_nav_scale_set(wmXrData *xr, float scale)
bool WM_xr_session_state_nav_scale_get(const wmXrData *xr, float *r_scale)
void wm_xr_session_toggle(wmWindowManager *wm, wmWindow *session_root_win, wmXrSessionExitFn session_exit_fn)
bool WM_xr_session_state_nav_location_get(const wmXrData *xr, float r_location[3])
void WM_xr_session_state_nav_location_set(wmXrData *xr, const float location[3])
bool WM_xr_session_is_ready(const wmXrData *xr)
bool WM_xr_session_state_viewer_pose_location_get(const wmXrData *xr, float r_location[3])
bool WM_xr_session_exists(const wmXrData *xr)
void WM_xr_session_state_nav_rotation_set(wmXrData *xr, const float rotation[4])
bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_rotation[4])
bool WM_xr_session_state_nav_rotation_get(const wmXrData *xr, float r_rotation[4])