41static bool is_bounding_box_in_frustum(
const float projmat[4][4],
52 HAS_TRANSLATE = (1 << 0),
53 HAS_ROTATE = (1 << 0),
56static bool ndof_has_translate(
const wmNDOFMotionData &ndof,
63static bool ndof_has_translate_pan(
const wmNDOFMotionData &ndof,
70static bool ndof_has_rotate(
const wmNDOFMotionData &ndof,
const RegionView3D *rv3d)
78static float view3d_ndof_pan_speed_calc_ex(
RegionView3D *rv3d,
const float depth_pt[3])
89static float view3d_ndof_pan_speed_calc_from_dist(
RegionView3D *rv3d,
const float dist)
105 return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
108static float view3d_ndof_pan_speed_calc(
RegionView3D *rv3d)
120 return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
129static void view3d_ndof_pan_zoom(
const wmNDOFMotionData &ndof,
132 const bool has_translate,
137 if (has_translate ==
false && has_zoom ==
false) {
141 blender::float3 pan_vec = WM_event_ndof_translation_get_for_navigation(ndof);
147 float zoom_distance = rv3d->
dist * ndof.dt * pan_vec[2];
148 rv3d->
dist += zoom_distance;
175 const float fly_speed[3] = {6.5f, 3.3f, 8.0f};
176 pan_vec[0] *= fly_speed[0] * ndof.dt;
177 pan_vec[1] *= fly_speed[1] * ndof.dt;
178 pan_vec[2] *= fly_speed[2] * ndof.dt;
181 const float speed = view3d_ndof_pan_speed_calc(rv3d);
182 pan_vec *= speed * ndof.dt;
199static void view3d_ndof_orbit(
const wmNDOFMotionData &ndof,
203 const bool apply_dyn_ofs)
220 float angle, quat[4];
221 float xvec[3] = {1, 0, 0};
222 float yvec[3] = {0, 1, 0};
241 if (yvec[2] < 0.0f) {
257 float angle = ndof.dt * WM_event_ndof_rotation_get_axis_angle_for_navigation(ndof, axis);
274 if (ndof_orbit_center_is_auto(v3d, rv3d)) {
289void view3d_ndof_fly(
const wmNDOFMotionData &ndof,
292 const bool use_precision,
293 const short protectflag,
294 bool *r_has_translate,
297 bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
298 bool has_rotate = ndof_has_rotate(ndof, rv3d);
308 float speed = view3d_ndof_pan_speed_calc_from_dist(rv3d, 1.0f);
315 blender::float3 trans = (speed * ndof.dt) * WM_event_ndof_translation_get(ndof);
316 trans_orig_y = trans[1];
327 trans[2] = trans_orig_y;
347 has_translate =
true;
350 has_translate =
false;
357 float angle = ndof.dt * WM_event_ndof_rotation_get_axis_angle(ndof, axis);
376 float view_horizon[3] = {1.0f, 0.0f, 0.0f};
377 float view_direction[3] = {0.0f, 0.0f, -1.0f};
403 *r_has_translate = has_translate;
404 *r_has_rotate = has_rotate;
428 "This test should not run from a camera view unless the camera is locked to the viewport");
460static std::optional<float3> ndof_orbit_center_calc_from_bounds(Depsgraph *
depsgraph,
464 std::optional<Bounds<float3>> bounding_box = std::nullopt;
467 bool do_zoom =
false;
474 if (bounding_box.has_value()) {
478 bounding_box->scale_from_center(
float3(0.8));
480 if (is_bounding_box_in_frustum(rv3d->
persmat, *bounding_box)) {
484 const float3 center = bounding_box->center();
485 if (ndof_orbit_center_is_valid(rv3d, center)) {
493static float ndof_read_zbuf(
ARegion *region)
502 const int region_center[2] = {region->
winx / 2, region->
winy / 2};
515static std::optional<float3> ndof_orbit_center_calc_from_zbuf(Depsgraph *
depsgraph,
520 const float depth_near = ndof_read_zbuf(region);
524 float region_center_x = region->
winx / 2.0f;
525 float region_center_y = region->
winy / 2.0f;
534 const float scale_margin = 1.05f;
559static std::optional<float3> ndof_orbit_center_calc(Depsgraph *
depsgraph,
578 std::optional<float3> center_test = ndof_orbit_center_calc_from_bounds(
depsgraph, area, region);
579 if (!center_test.has_value()) {
580 center_test = ndof_orbit_center_calc_from_zbuf(
depsgraph, area, region);
596 const wmNDOFMotionData &ndof)
609 blender::float3 pan_vec = WM_event_ndof_translation_get_for_navigation(ndof);
611 const bool has_translate = !
is_zero_v2(pan_vec);
612 const bool has_zoom = pan_vec[2] != 0.0f;
627 if (!(has_translate || has_zoom)) {
631 bool changed =
false;
673 const wmNDOFMotionData &ndof = *
static_cast<const wmNDOFMotionData *
>(
event->customdata);
679 const bool has_rotation = ndof_has_rotate(ndof, rv3d);
682 ndof_has_translate(ndof, v3d, rv3d);
683 const bool has_zoom = (rv3d->
is_persp ==
false) && WM_event_ndof_translation_has_zoom(ndof);
685 if (has_translate || has_zoom) {
686 view3d_ndof_pan_zoom(ndof, vod->
area, vod->
region, has_translate, has_zoom);
687 xform_flag |= HAS_TRANSLATE;
691 view3d_ndof_orbit(ndof, vod->
area, vod->
region, vod,
true);
692 xform_flag |= HAS_ROTATE;
699 v3d, rv3d,
C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
719 ot->name =
"NDOF Orbit View";
720 ot->description =
"Orbit the view using the 3D mouse";
721 ot->idname = ViewOpsType_ndof_orbit.idname;
724 ot->invoke = ndof_orbit_invoke;
746 const wmNDOFMotionData &ndof = *
static_cast<const wmNDOFMotionData *
>(
event->customdata);
749 const wmOperatorStatus camera_retval = view3d_ndof_cameraview_pan_zoom(vod, ndof);
751 return camera_retval;
766 if (ndof_orbit_center_is_auto(v3d, rv3d)) {
768 if (std::optional<float3> center_test = ndof_orbit_center_calc(
786 const bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
787 const bool has_zoom = WM_event_ndof_translation_has_zoom(ndof) &&
790 if (has_translate || has_zoom) {
791 view3d_ndof_pan_zoom(ndof, vod->
area, vod->
region, has_translate,
true);
792 xform_flag |= HAS_TRANSLATE;
801 const bool has_rotation = ndof_has_rotate(ndof, rv3d);
802 bool has_translate, has_zoom;
804 if (is_orbit_around_pivot) {
806 has_translate = ndof_has_translate_pan(ndof, v3d, rv3d);
807 has_zoom = WM_event_ndof_translation_has_zoom(ndof);
811 has_translate = ndof_has_translate(ndof, v3d, rv3d);
817 const float dist_backup = rv3d->
dist;
818 if (!is_orbit_around_pivot) {
821 view3d_ndof_orbit(ndof, vod->
area, vod->
region, vod, is_orbit_around_pivot);
822 xform_flag |= HAS_ROTATE;
823 if (!is_orbit_around_pivot) {
828 if (has_translate || has_zoom) {
829 view3d_ndof_pan_zoom(ndof, vod->
area, vod->
region, has_translate, has_zoom);
830 xform_flag |= HAS_TRANSLATE;
837 v3d, rv3d,
C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
857 ot->name =
"NDOF Orbit View with Zoom";
858 ot->description =
"Orbit and zoom the view using the 3D mouse";
859 ot->idname = ViewOpsType_ndof_orbit_zoom.idname;
862 ot->invoke = ndof_orbit_zoom_invoke;
884 const wmNDOFMotionData &ndof = *
static_cast<const wmNDOFMotionData *
>(
event->customdata);
887 const wmOperatorStatus camera_retval = view3d_ndof_cameraview_pan_zoom(vod, ndof);
889 return camera_retval;
899 const bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
900 const bool has_zoom = (rv3d->
is_persp ==
false) && WM_event_ndof_translation_has_zoom(ndof);
905 if (!(has_translate || has_zoom)) {
914 if (has_translate || has_zoom) {
915 view3d_ndof_pan_zoom(ndof, area, region, has_translate, has_zoom);
916 xform_flag |= HAS_TRANSLATE;
942 ot->name =
"NDOF Pan View";
943 ot->description =
"Pan the view with the 3D mouse";
944 ot->idname = ViewOpsType_ndof_pan.idname;
947 ot->invoke = ndof_pan_invoke;
972 const uint8_t ndof_navigation_mode_backup =
U.ndof_navigation_mode;
975 ret = ndof_orbit_zoom_invoke_impl(
C, vod, event,
nullptr);
977 U.ndof_navigation_mode = ndof_navigation_mode_backup;
994 ot->name =
"NDOF Transform View";
995 ot->description =
"Pan and rotate the view with the 3D mouse";
996 ot->idname = ViewOpsType_ndof_all.idname;
999 ot->invoke = ndof_all_invoke;
1008 "VIEW3D_OT_ndof_orbit",
1010 ndof_orbit_invoke_impl,
1016 "VIEW3D_OT_ndof_orbit_zoom",
1018 ndof_orbit_zoom_invoke_impl,
1024 "VIEW3D_OT_ndof_pan",
1026 ndof_pan_invoke_impl,
1032 "VIEW3D_OT_ndof_all",
1034 ndof_all_invoke_impl,
bool BKE_layer_collection_has_selected_objects(const Scene *scene, ViewLayer *view_layer, LayerCollection *lc)
#define BLI_assert_msg(a, msg)
MINLINE float max_ff(float a, float b)
#define ISECT_AABB_PLANE_IN_FRONT_ALL
int isect_aabb_planes_v3(const float(*planes)[4], int totplane, const float bbmin[3], const float bbmax[3])
void planes_from_projmat(const float mat[4][4], float left[4], float right[4], float bottom[4], float top[4], float near[4], float far[4])
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 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
MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT
void BLI_rcti_init_pt_radius(struct rcti *rect, const int xy[2], int size)
#define UNUSED_VARS_NDEBUG(...)
ViewLayer * DEG_get_evaluated_view_layer(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
#define NDOF_IS_ORBIT_AROUND_CENTER_MODE(userdef)
#define NDOF_PIXELS_PER_SECOND
@ NDOF_NAVIGATION_MODE_FLY
@ NDOF_ORBIT_CENTER_SELECTED
#define RV3D_VIEW_IS_AXIS(view)
#define RV3D_LOCK_FLAGS(rv3d)
bool ED_operator_view3d_active(bContext *C)
void ED_region_tag_redraw(ARegion *region)
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_distance_set_from_location(RegionView3D *rv3d, const float dist_co[3], float dist_min)
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 view3d_region_operator_needs_gpu(ARegion *region)
bool ED_view3d_unproject_v3(const ARegion *region, float regionx, float regiony, float regionz, float world[3])
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)
float ED_view3d_dist_soft_min_get(const View3D *v3d, bool use_persp_range)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
BPy_StructRNA * depsgraph
VecBase< float, 3 > float3
struct Object * ob_center
LayerCollection * active_collection
void view3d_depths_rect_create(ARegion *region, rcti *rect, ViewDepths *r_d)
float view3d_depth_near(ViewDepths *d)
void view3d_boxview_sync(ScrArea *area, ARegion *region)
wmOperatorStatus 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])
bool view3d_calc_point_in_selected_bounds(Depsgraph *depsgraph, struct ViewLayer *view_layer_eval, const View3D *v3d, const blender::float3 &point, const float scale_margin)
@ VIEWOPS_FLAG_ORBIT_SELECT
std::optional< blender::Bounds< blender::float3 > > view3d_calc_minmax_selected(Depsgraph *depsgraph, ScrArea *area, ARegion *region, bool use_all_regions, bool clip_bounds, bool *r_do_zoom)
std::optional< blender::Bounds< blender::float3 > > view3d_calc_minmax_visible(Depsgraph *depsgraph, ScrArea *area, ARegion *region, bool use_all_regions, bool clip_bounds)