Blender V4.3
view3d_navigate_view_ndof.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
9#include "BLI_math_rotation.h"
10#include "BLI_math_vector.h"
11
12#include "WM_api.hh"
13
14#include "ED_screen.hh"
15
16#include "view3d_intern.hh"
17#include "view3d_navigate.hh" /* own include */
18
19/* -------------------------------------------------------------------- */
23#ifdef WITH_INPUT_NDOF
24
25enum {
26 HAS_TRANSLATE = (1 << 0),
27 HAS_ROTATE = (1 << 0),
28};
29
30static bool ndof_has_translate(const wmNDOFMotionData *ndof,
31 const View3D *v3d,
32 const RegionView3D *rv3d)
33{
34 return !is_zero_v3(ndof->tvec) && !ED_view3d_offset_lock_check(v3d, rv3d);
35}
36
37static bool ndof_has_rotate(const wmNDOFMotionData *ndof, const RegionView3D *rv3d)
38{
39 return !is_zero_v3(ndof->rvec) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0);
40}
41
45static float view3d_ndof_pan_speed_calc_ex(RegionView3D *rv3d, const float depth_pt[3])
46{
47 float speed = rv3d->pixsize * NDOF_PIXELS_PER_SECOND;
48
49 if (rv3d->is_persp) {
50 speed *= ED_view3d_calc_zfac(rv3d, depth_pt);
51 }
52
53 return speed;
54}
55
56static float view3d_ndof_pan_speed_calc_from_dist(RegionView3D *rv3d, const float dist)
57{
58 float viewinv[4];
59 float tvec[3];
60
61 BLI_assert(dist >= 0.0f);
62
63 copy_v3_fl3(tvec, 0.0f, 0.0f, dist);
64 /* rv3d->viewinv isn't always valid */
65# if 0
66 mul_mat3_m4_v3(rv3d->viewinv, tvec);
67# else
68 invert_qt_qt_normalized(viewinv, rv3d->viewquat);
69 mul_qt_v3(viewinv, tvec);
70# endif
71
72 return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
73}
74
75static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d)
76{
77 float tvec[3];
78 negate_v3_v3(tvec, rv3d->ofs);
79
80 return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
81}
82
89static void view3d_ndof_pan_zoom(const wmNDOFMotionData *ndof,
90 ScrArea *area,
91 ARegion *region,
92 const bool has_translate,
93 const bool has_zoom)
94{
95 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
96 float view_inv[4];
97 float pan_vec[3];
98
99 if (has_translate == false && has_zoom == false) {
100 return;
101 }
102
103 WM_event_ndof_pan_get(ndof, pan_vec, false);
104
105 if (has_zoom) {
106 /* zoom with Z */
107
108 /* Zoom!
109 * velocity should be proportional to the linear velocity attained by rotational motion
110 * of same strength [got that?] proportional to `arclength = radius * angle`.
111 */
112
113 pan_vec[2] = 0.0f;
114
115 /* "zoom in" or "translate"? depends on zoom mode in user settings? */
116 if (ndof->tvec[2]) {
117 float zoom_distance = rv3d->dist * ndof->dt * ndof->tvec[2];
118
119 if (U.ndof_flag & NDOF_ZOOM_INVERT) {
120 zoom_distance = -zoom_distance;
121 }
122
123 rv3d->dist += zoom_distance;
124 }
125 }
126 else {
127 /* dolly with Z */
128
129 /* all callers must check */
130 if (has_translate) {
131 BLI_assert(ED_view3d_offset_lock_check((View3D *)area->spacedata.first, rv3d) == false);
132 }
133 }
134
135 if (has_translate) {
136 const float speed = view3d_ndof_pan_speed_calc(rv3d);
137
138 mul_v3_fl(pan_vec, speed * ndof->dt);
139
140 /* transform motion from view to world coordinates */
141 invert_qt_qt_normalized(view_inv, rv3d->viewquat);
142 mul_qt_v3(view_inv, pan_vec);
143
144 /* move center of view opposite of hand motion (this is camera mode, not object mode) */
145 sub_v3_v3(rv3d->ofs, pan_vec);
146
147 if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
148 view3d_boxview_sync(area, region);
149 }
150 }
151}
152
153static void view3d_ndof_orbit(const wmNDOFMotionData *ndof,
154 ScrArea *area,
155 ARegion *region,
156 ViewOpsData *vod,
157 const bool apply_dyn_ofs)
158{
159 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
160 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
161
162 float view_inv[4];
163
165
166 ED_view3d_persp_ensure(vod->depsgraph, v3d, region);
167
168 rv3d->view = RV3D_VIEW_USER;
169
170 invert_qt_qt_normalized(view_inv, rv3d->viewquat);
171
172 if (U.ndof_flag & NDOF_TURNTABLE) {
173 float rot[3];
174
175 /* Turntable view code adapted for 3D mouse use. */
176 float angle, quat[4];
177 float xvec[3] = {1, 0, 0};
178
179 /* only use XY, ignore Z */
180 WM_event_ndof_rotate_get(ndof, rot);
181
182 /* Determine the direction of the x vector (for rotating up and down) */
183 mul_qt_v3(view_inv, xvec);
184
185 /* Perform the up/down rotation */
186 angle = ndof->dt * rot[0];
187 axis_angle_to_quat(quat, xvec, angle);
188 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
189
190 /* Perform the orbital rotation */
191 angle = ndof->dt * rot[1];
192
193 /* Update the onscreen axis-angle indicator. */
194 rv3d->rot_angle = angle;
195 rv3d->rot_axis[0] = 0;
196 rv3d->rot_axis[1] = 0;
197 rv3d->rot_axis[2] = 1;
198
199 axis_angle_to_quat_single(quat, 'Z', angle);
200 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
201 }
202 else {
203 float quat[4];
204 float axis[3];
205 float angle = WM_event_ndof_to_axis_angle(ndof, axis);
206
207 /* transform rotation axis from view to world coordinates */
208 mul_qt_v3(view_inv, axis);
209
210 /* Update the onscreen axis-angle indicator. */
211 rv3d->rot_angle = angle;
212 copy_v3_v3(rv3d->rot_axis, axis);
213
214 axis_angle_to_quat(quat, axis, angle);
215
216 /* apply rotation */
217 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
218 }
219
220 if (apply_dyn_ofs) {
222 }
223}
224
225void view3d_ndof_fly(const wmNDOFMotionData *ndof,
226 View3D *v3d,
227 RegionView3D *rv3d,
228 const bool use_precision,
229 const short protectflag,
230 bool *r_has_translate,
231 bool *r_has_rotate)
232{
233 bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
234 bool has_rotate = ndof_has_rotate(ndof, rv3d);
235
236 float view_inv[4];
237 invert_qt_qt_normalized(view_inv, rv3d->viewquat);
238
239 rv3d->rot_angle = 0.0f; /* Disable onscreen rotation indicator. */
240
241 if (has_translate) {
242 /* ignore real 'dist' since fly has its own speed settings,
243 * also its overwritten at this point. */
244 float speed = view3d_ndof_pan_speed_calc_from_dist(rv3d, 1.0f);
245 float trans[3], trans_orig_y;
246
247 if (use_precision) {
248 speed *= 0.2f;
249 }
250
251 WM_event_ndof_pan_get(ndof, trans, false);
252 mul_v3_fl(trans, speed * ndof->dt);
253 trans_orig_y = trans[1];
254
255 if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
256 trans[1] = 0.0f;
257 }
258
259 /* transform motion from view to world coordinates */
260 mul_qt_v3(view_inv, trans);
261
262 if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
263 /* replace world z component with device y (yes it makes sense) */
264 trans[2] = trans_orig_y;
265 }
266
267 if (rv3d->persp == RV3D_CAMOB) {
268 /* respect camera position locks */
269 if (protectflag & OB_LOCK_LOCX) {
270 trans[0] = 0.0f;
271 }
272 if (protectflag & OB_LOCK_LOCY) {
273 trans[1] = 0.0f;
274 }
275 if (protectflag & OB_LOCK_LOCZ) {
276 trans[2] = 0.0f;
277 }
278 }
279
280 if (!is_zero_v3(trans)) {
281 /* move center of view opposite of hand motion
282 * (this is camera mode, not object mode) */
283 sub_v3_v3(rv3d->ofs, trans);
284 has_translate = true;
285 }
286 else {
287 has_translate = false;
288 }
289 }
290
291 if (has_rotate) {
292 const float turn_sensitivity = 1.0f;
293
294 float rotation[4];
295 float axis[3];
296 float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis);
297
298 if (fabsf(angle) > 0.0001f) {
299 has_rotate = true;
300
301 if (use_precision) {
302 angle *= 0.2f;
303 }
304
305 /* transform rotation axis from view to world coordinates */
306 mul_qt_v3(view_inv, axis);
307
308 /* apply rotation to view */
309 axis_angle_to_quat(rotation, axis, angle);
310 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
311
312 if (U.ndof_flag & NDOF_LOCK_HORIZON) {
313 /* force an upright viewpoint
314 * TODO: make this less... sudden */
315 float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
316 float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */
317
318 /* find new inverse since viewquat has changed */
319 invert_qt_qt_normalized(view_inv, rv3d->viewquat);
320 /* could apply reverse rotation to existing view_inv to save a few cycles */
321
322 /* transform view vectors to world coordinates */
323 mul_qt_v3(view_inv, view_horizon);
324 mul_qt_v3(view_inv, view_direction);
325
326 /* find difference between view & world horizons
327 * true horizon lives in world xy plane, so look only at difference in z */
328 angle = -asinf(view_horizon[2]);
329
330 /* rotate view so view horizon = world horizon */
331 axis_angle_to_quat(rotation, view_direction, angle);
332 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
333 }
334
335 rv3d->view = RV3D_VIEW_USER;
336 }
337 else {
338 has_rotate = false;
339 }
340 }
341
342 *r_has_translate = has_translate;
343 *r_has_rotate = has_rotate;
344}
345
348/* -------------------------------------------------------------------- */
356static int view3d_ndof_cameraview_pan_zoom(ViewOpsData *vod, const wmNDOFMotionData *ndof)
357{
358 View3D *v3d = vod->v3d;
359 ARegion *region = vod->region;
360 RegionView3D *rv3d = vod->rv3d;
361
362 if (v3d->camera && (rv3d->persp == RV3D_CAMOB) && (v3d->flag2 & V3D_LOCK_CAMERA) == 0) {
363 /* pass */
364 }
365 else {
367 }
368
369 const float pan_speed = NDOF_PIXELS_PER_SECOND;
370 const bool has_translate = !is_zero_v2(ndof->tvec);
371 const bool has_zoom = ndof->tvec[2] != 0.0f;
372
373 float pan_vec[3];
374 WM_event_ndof_pan_get(ndof, pan_vec, true);
375
376 mul_v3_fl(pan_vec, ndof->dt);
377 /* NOTE: unlike image and clip views, the 2D pan doesn't have to be scaled by the zoom level.
378 * #ED_view3d_camera_view_pan already takes the zoom level into account. */
379 mul_v2_fl(pan_vec, pan_speed);
380
381 /* NOTE(@ideasman42): In principle rotating could pass through to regular
382 * non-camera NDOF behavior (exiting the camera-view and rotating).
383 * Disabled this block since in practice it's difficult to control NDOF devices
384 * to perform some rotation with absolutely no translation. Causing rotation to
385 * randomly exit from the user perspective. Adjusting the dead-zone could avoid
386 * the motion feeling *glitchy* although in my own tests even then it didn't work reliably.
387 * Leave rotating out of camera-view disabled unless it can be made to work reliably. */
388 if (!(has_translate || has_zoom)) {
389 // return OPERATOR_PASS_THROUGH;
390 }
391
392 bool changed = false;
393
394 if (has_translate) {
395 /* Use the X & Y of `pan_vec`. */
396 if (ED_view3d_camera_view_pan(region, pan_vec)) {
397 changed = true;
398 }
399 }
400
401 if (has_zoom) {
402 if (ED_view3d_camera_view_zoom_scale(rv3d, max_ff(0.0f, 1.0f - pan_vec[2]))) {
403 changed = true;
404 }
405 }
406
407 if (changed) {
408 ED_region_tag_redraw(region);
409 return OPERATOR_FINISHED;
410 }
411 return OPERATOR_CANCELLED;
412}
413
416/* -------------------------------------------------------------------- */
420static int ndof_orbit_invoke_impl(bContext *C,
421 ViewOpsData *vod,
422 const wmEvent *event,
423 PointerRNA * /*ptr*/)
424{
425 if (event->type != NDOF_MOTION) {
426 return OPERATOR_CANCELLED;
427 }
428
429 const Depsgraph *depsgraph = vod->depsgraph;
430 View3D *v3d = vod->v3d;
431 RegionView3D *rv3d = vod->rv3d;
432 char xform_flag = 0;
433
434 const wmNDOFMotionData *ndof = static_cast<const wmNDOFMotionData *>(event->customdata);
435
436 /* off by default, until changed later this function */
437 rv3d->rot_angle = 0.0f;
438
439 if (ndof->progress != P_FINISHING) {
440 const bool has_rotation = ndof_has_rotate(ndof, rv3d);
441 /* if we can't rotate, fallback to translate (locked axis views) */
442 const bool has_translate = ndof_has_translate(ndof, v3d, rv3d) &&
444 const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
445
446 if (has_translate || has_zoom) {
447 view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
448 xform_flag |= HAS_TRANSLATE;
449 }
450
451 if (has_rotation) {
452 view3d_ndof_orbit(ndof, vod->area, vod->region, vod, true);
453 xform_flag |= HAS_ROTATE;
454 }
455 }
456
458 if (xform_flag) {
460 v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
461 }
462
464
465 return OPERATOR_FINISHED;
466}
467
468static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
469{
470 if (event->type != NDOF_MOTION) {
471 return OPERATOR_CANCELLED;
472 }
473
474 return view3d_navigate_invoke_impl(C, op, event, &ViewOpsType_ndof_orbit);
475}
476
477void VIEW3D_OT_ndof_orbit(wmOperatorType *ot)
478{
479 /* identifiers */
480 ot->name = "NDOF Orbit View";
481 ot->description = "Orbit the view using the 3D mouse";
482 ot->idname = ViewOpsType_ndof_orbit.idname;
483
484 /* api callbacks */
485 ot->invoke = ndof_orbit_invoke;
487
488 /* flags */
489 ot->flag = 0;
490}
491
494/* -------------------------------------------------------------------- */
498static int ndof_orbit_zoom_invoke_impl(bContext *C,
499 ViewOpsData *vod,
500 const wmEvent *event,
501 PointerRNA * /*ptr*/)
502{
503 if (event->type != NDOF_MOTION) {
504 return OPERATOR_CANCELLED;
505 }
506
507 const wmNDOFMotionData *ndof = static_cast<const wmNDOFMotionData *>(event->customdata);
508
509 if (U.ndof_flag & NDOF_CAMERA_PAN_ZOOM) {
510 const int camera_retval = view3d_ndof_cameraview_pan_zoom(vod, ndof);
511 if (camera_retval != OPERATOR_PASS_THROUGH) {
512 return camera_retval;
513 }
514 }
515
516 View3D *v3d = vod->v3d;
517 RegionView3D *rv3d = vod->rv3d;
518 char xform_flag = 0;
519
520 /* off by default, until changed later this function */
521 rv3d->rot_angle = 0.0f;
522
523 if (ndof->progress == P_FINISHING) {
524 /* pass */
525 }
526 else if ((rv3d->persp == RV3D_ORTHO) && RV3D_VIEW_IS_AXIS(rv3d->view)) {
527 /* if we can't rotate, fallback to translate (locked axis views) */
528 const bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
529 const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d);
530
531 if (has_translate || has_zoom) {
532 view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, true);
533 xform_flag |= HAS_TRANSLATE;
534 }
535 }
536 else {
537 /* NOTE: based on feedback from #67579, users want to have pan and orbit enabled at once.
538 * It's arguable that orbit shouldn't pan (since we have a pan only operator),
539 * so if there are users who like to separate orbit/pan operations - it can be a preference. */
540 const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) ||
542 const bool has_rotation = ndof_has_rotate(ndof, rv3d);
543 bool has_translate, has_zoom;
544
545 if (is_orbit_around_pivot) {
546 /* Orbit preference or forced lock (Z zooms). */
547 has_translate = !is_zero_v2(ndof->tvec) && ndof_has_translate(ndof, v3d, rv3d);
548 has_zoom = (ndof->tvec[2] != 0.0f);
549 }
550 else {
551 /* Free preference (Z translates). */
552 has_translate = ndof_has_translate(ndof, v3d, rv3d);
553 has_zoom = false;
554 }
555
556 /* Rotation first because dynamic offset resets offset otherwise (and disables panning). */
557 if (has_rotation) {
558 const float dist_backup = rv3d->dist;
559 if (!is_orbit_around_pivot) {
560 ED_view3d_distance_set(rv3d, 0.0f);
561 }
562 view3d_ndof_orbit(ndof, vod->area, vod->region, vod, is_orbit_around_pivot);
563 xform_flag |= HAS_ROTATE;
564 if (!is_orbit_around_pivot) {
565 ED_view3d_distance_set(rv3d, dist_backup);
566 }
567 }
568
569 if (has_translate || has_zoom) {
570 view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
571 xform_flag |= HAS_TRANSLATE;
572 }
573 }
574
575 ED_view3d_camera_lock_sync(vod->depsgraph, v3d, rv3d);
576 if (xform_flag) {
578 v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
579 }
580
582
583 return OPERATOR_FINISHED;
584}
585
586static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
587{
588 if (event->type != NDOF_MOTION) {
589 return OPERATOR_CANCELLED;
590 }
591
592 return view3d_navigate_invoke_impl(C, op, event, &ViewOpsType_ndof_orbit_zoom);
593}
594
595void VIEW3D_OT_ndof_orbit_zoom(wmOperatorType *ot)
596{
597 /* identifiers */
598 ot->name = "NDOF Orbit View with Zoom";
599 ot->description = "Orbit and zoom the view using the 3D mouse";
600 ot->idname = ViewOpsType_ndof_orbit_zoom.idname;
601
602 /* api callbacks */
603 ot->invoke = ndof_orbit_zoom_invoke;
605
606 /* flags */
607 ot->flag = 0;
608}
609
612/* -------------------------------------------------------------------- */
616static int ndof_pan_invoke_impl(bContext *C,
617 ViewOpsData *vod,
618 const wmEvent *event,
619 PointerRNA * /*ptr*/)
620{
621 if (event->type != NDOF_MOTION) {
622 return OPERATOR_CANCELLED;
623 }
624
625 const wmNDOFMotionData *ndof = static_cast<const wmNDOFMotionData *>(event->customdata);
626
627 if (U.ndof_flag & NDOF_CAMERA_PAN_ZOOM) {
628 const int camera_retval = view3d_ndof_cameraview_pan_zoom(vod, ndof);
629 if (camera_retval != OPERATOR_PASS_THROUGH) {
630 return camera_retval;
631 }
632 }
633
634 const Depsgraph *depsgraph = vod->depsgraph;
635 View3D *v3d = vod->v3d;
636 RegionView3D *rv3d = vod->rv3d;
637 ARegion *region = vod->region;
638 char xform_flag = 0;
639
640 const bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
641 const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
642
643 /* we're panning here! so erase any leftover rotation from other operators */
644 rv3d->rot_angle = 0.0f;
645
646 if (!(has_translate || has_zoom)) {
647 return OPERATOR_CANCELLED;
648 }
649
650 ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
651
652 if (ndof->progress != P_FINISHING) {
653 ScrArea *area = vod->area;
654
655 if (has_translate || has_zoom) {
656 view3d_ndof_pan_zoom(ndof, area, region, has_translate, has_zoom);
657 xform_flag |= HAS_TRANSLATE;
658 }
659 }
660
662 if (xform_flag) {
663 ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, xform_flag & HAS_TRANSLATE);
664 }
665
666 ED_region_tag_redraw(region);
667
668 return OPERATOR_FINISHED;
669}
670
671static int ndof_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
672{
673 if (event->type != NDOF_MOTION) {
674 return OPERATOR_CANCELLED;
675 }
676
677 return view3d_navigate_invoke_impl(C, op, event, &ViewOpsType_ndof_pan);
678}
679
680void VIEW3D_OT_ndof_pan(wmOperatorType *ot)
681{
682 /* identifiers */
683 ot->name = "NDOF Pan View";
684 ot->description = "Pan the view with the 3D mouse";
685 ot->idname = ViewOpsType_ndof_pan.idname;
686
687 /* api callbacks */
688 ot->invoke = ndof_pan_invoke;
690
691 /* flags */
692 ot->flag = 0;
693}
694
697/* -------------------------------------------------------------------- */
704static int ndof_all_invoke_impl(bContext *C,
705 ViewOpsData *vod,
706 const wmEvent *event,
707 PointerRNA * /*ptr*/)
708{
709 /* weak!, but it works */
710 const int ndof_flag = U.ndof_flag;
711 int ret;
712
713 U.ndof_flag &= ~NDOF_MODE_ORBIT;
714
715 ret = ndof_orbit_zoom_invoke_impl(C, vod, event, nullptr);
716
717 U.ndof_flag = ndof_flag;
718
719 return ret;
720}
721
722static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
723{
724 if (event->type != NDOF_MOTION) {
725 return OPERATOR_CANCELLED;
726 }
727
728 return view3d_navigate_invoke_impl(C, op, event, &ViewOpsType_ndof_all);
729}
730
731void VIEW3D_OT_ndof_all(wmOperatorType *ot)
732{
733 /* identifiers */
734 ot->name = "NDOF Transform View";
735 ot->description = "Pan and rotate the view with the 3D mouse";
736 ot->idname = ViewOpsType_ndof_all.idname;
737
738 /* api callbacks */
739 ot->invoke = ndof_all_invoke;
741
742 /* flags */
743 ot->flag = 0;
744}
745
746const ViewOpsType ViewOpsType_ndof_orbit = {
748 /*idname*/ "VIEW3D_OT_ndof_orbit",
749 /*poll_fn*/ nullptr,
750 /*init_fn*/ ndof_orbit_invoke_impl,
751 /*apply_fn*/ nullptr,
752};
753
754const ViewOpsType ViewOpsType_ndof_orbit_zoom = {
756 /*idname*/ "VIEW3D_OT_ndof_orbit_zoom",
757 /*poll_fn*/ nullptr,
758 /*init_fn*/ ndof_orbit_zoom_invoke_impl,
759 /*apply_fn*/ nullptr,
760};
761
762const ViewOpsType ViewOpsType_ndof_pan = {
763 /*flag*/ VIEWOPS_FLAG_NONE,
764 /*idname*/ "VIEW3D_OT_ndof_pan",
765 /*poll_fn*/ nullptr,
766 /*init_fn*/ ndof_pan_invoke_impl,
767 /*apply_fn*/ nullptr,
768};
769
770const ViewOpsType ViewOpsType_ndof_all = {
772 /*idname*/ "VIEW3D_OT_ndof_all",
773 /*poll_fn*/ nullptr,
774 /*init_fn*/ ndof_all_invoke_impl,
775 /*apply_fn*/ nullptr,
776};
777
778#endif /* WITH_INPUT_NDOF */
779
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE float max_ff(float a, float b)
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void axis_angle_to_quat_single(float q[4], char axis, float angle)
void mul_qt_v3(const float q[4], float r[3])
void invert_qt_qt_normalized(float q1[4], const float q2[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE bool is_zero_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
@ OB_LOCK_LOCY
@ OB_LOCK_LOCZ
@ OB_LOCK_LOCX
#define NDOF_PIXELS_PER_SECOND
@ NDOF_MODE_ORBIT
@ NDOF_ZOOM_INVERT
@ NDOF_LOCK_HORIZON
@ NDOF_TURNTABLE
@ NDOF_CAMERA_PAN_ZOOM
@ NDOF_FLY_HELICOPTER
#define RV3D_VIEW_IS_AXIS(view)
#define RV3D_LOCK_FLAGS(rv3d)
@ RV3D_CAMOB
@ RV3D_ORTHO
@ RV3D_LOCK_ROTATION
@ RV3D_BOXVIEW
@ V3D_LOCK_CAMERA
@ RV3D_VIEW_USER
@ OPERATOR_PASS_THROUGH
bool ED_operator_view3d_active(bContext *C)
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
void ED_view3d_distance_set(RegionView3D *rv3d, float dist)
bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *region)
bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
bool ED_view3d_camera_view_zoom_scale(RegionView3D *rv3d, const float scale)
void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, bool calc_dist)
bool ED_view3d_camera_view_pan(ARegion *region, const float event_ofs[2])
float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3])
bool ED_view3d_camera_lock_autokey(View3D *v3d, RegionView3D *rv3d, bContext *C, bool do_rotate, bool do_translate)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
@ P_FINISHING
Definition WM_types.hh:816
unsigned int U
Definition btGjkEpa3.h:78
const Depsgraph * depsgraph
#define asinf(x)
#define fabsf(x)
#define rot(x, k)
return ret
float viewinv[4][4]
struct Object * camera
Depsgraph * depsgraph
ARegion * region
RegionView3D * rv3d
short type
Definition WM_types.hh:722
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(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
const char * description
Definition WM_types.hh:996
void view3d_boxview_sync(ScrArea *area, ARegion *region)
int view3d_navigate_invoke_impl(bContext *C, wmOperator *op, const wmEvent *event, const ViewOpsType *nav_type)
void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4])
@ VIEWOPS_FLAG_NONE
@ VIEWOPS_FLAG_ORBIT_SELECT
@ NDOF_MOTION
wmOperatorType * ot
Definition wm_files.cc:4125