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