diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-02-09 03:50:25 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-02-09 17:50:23 +0300 |
commit | 8e981efe38ae6d0760f08c49564010104eee78c6 (patch) | |
tree | de33177cee685849351e40724487f2c14ba13a94 /source/blender/editors/space_view3d | |
parent | 89ce270f6137aa359f0fa31cf19485f986bde131 (diff) |
3D View: support axis views with axis-aligned roll
Previously any of the named views could not have any roll,
this commit supports roll as long as it's axis-aligned (90,180,270 deg).
This is useful for snapping to views,
an improvement on cebd025e02f11.
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw.c | 34 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_edit.c | 93 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_utils.c | 116 |
3 files changed, 165 insertions, 78 deletions
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index d092de4fcce..7bfb0460c41 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -27,6 +27,7 @@ #include "BLI_math.h" #include "BLI_rect.h" #include "BLI_string.h" +#include "BLI_string_utils.h" #include "BLI_threads.h" #include "BLI_jitter_2d.h" @@ -1255,21 +1256,44 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, int xoffset, int *yoffs { RegionView3D *rv3d = ar->regiondata; const char *name = view3d_get_name(v3d, rv3d); + const char *name_array[3] = {name, NULL, NULL}; + int name_array_len = 1; const int font_id = BLF_default(); + /* 6 is the maximum size of the axis roll text. */ /* increase size for unicode languages (Chinese in utf-8...) */ #ifdef WITH_INTERNATIONAL - char tmpstr[96]; + char tmpstr[96 + 6]; #else - char tmpstr[32]; + char tmpstr[32 + 6]; #endif BLF_enable(font_id, BLF_SHADOW); BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); BLF_shadow_offset(font_id, 1, -1); + if (RV3D_VIEW_IS_AXIS(rv3d->view) && (rv3d->view_axis_roll != RV3D_VIEW_AXIS_ROLL_0)) { + const char *axis_roll; + switch (rv3d->view_axis_roll) { + case RV3D_VIEW_AXIS_ROLL_90: + axis_roll = " 90\xC2\xB0"; + break; + case RV3D_VIEW_AXIS_ROLL_180: + axis_roll = " 180\xC2\xB0"; + break; + default: + axis_roll = " -90\xC2\xB0"; + break; + } + name_array[name_array_len++] = axis_roll; + } + if (v3d->localvd) { - BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name); + name_array[name_array_len++] = IFACE_(" (Local)"); + } + + if (name_array_len > 1) { + BLI_string_join_array(tmpstr, sizeof(tmpstr), name_array, name_array_len); name = tmpstr; } @@ -1277,11 +1301,7 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, int xoffset, int *yoffs *yoffset -= U.widget_unit; -#ifdef WITH_INTERNATIONAL BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr)); -#else - BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr)); -#endif BLF_disable(font_id, BLF_SHADOW); } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 83fb87264e3..a045988cb55 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -700,9 +700,9 @@ static void viewrotate_apply_snap(ViewOpsData *vod) if (found) { /* lock 'quat_best' to an axis view if we can */ - rv3d->view = ED_view3d_quat_to_axis_view(quat_best, 0.01f); + ED_view3d_quat_to_axis_view(quat_best, 0.01f, &rv3d->view, &rv3d->view_axis_roll); if (rv3d->view != RV3D_VIEW_USER) { - ED_view3d_quat_from_axis_view(rv3d->view, quat_best); + ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, quat_best); } } else { @@ -3804,7 +3804,8 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar, const float quat_[4], - short view, + char view, + char view_axis_roll, int perspo, const float *align_to_quat, const int smooth_viewtx) @@ -3818,10 +3819,12 @@ static void axis_set_view(bContext *C, if (align_to_quat) { mul_qt_qtqt(quat, quat, align_to_quat); rv3d->view = view = RV3D_VIEW_USER; + rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; } if (align_to_quat == NULL) { rv3d->view = view; + rv3d->view_axis_roll = view_axis_roll; } if (rv3d->viewlock & RV3D_LOCKED) { @@ -3901,6 +3904,7 @@ static int view_axis_exec(bContext *C, wmOperator *op) RegionView3D *rv3d; static int perspo = RV3D_PERSP; int viewnum; + int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); /* no NULL check is needed, poll checks */ @@ -3928,58 +3932,73 @@ static int view_axis_exec(bContext *C, wmOperator *op) } if (RNA_boolean_get(op->ptr, "relative")) { - float z_rel[3]; + float quat_rotate[4]; + float quat_test[4]; - if (viewnum == RV3D_VIEW_RIGHT) { - negate_v3_v3(z_rel, rv3d->viewinv[0]); + if (viewnum == RV3D_VIEW_LEFT) { + axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI / 2.0f); } - else if (viewnum == RV3D_VIEW_LEFT) { - copy_v3_v3(z_rel, rv3d->viewinv[0]); + else if (viewnum == RV3D_VIEW_RIGHT) { + axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI / 2.0f); } else if (viewnum == RV3D_VIEW_TOP) { - negate_v3_v3(z_rel, rv3d->viewinv[1]); + axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI / 2.0f); } else if (viewnum == RV3D_VIEW_BOTTOM) { - copy_v3_v3(z_rel, rv3d->viewinv[1]); + axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI / 2.0f); } else if (viewnum == RV3D_VIEW_FRONT) { - negate_v3_v3(z_rel, rv3d->viewinv[2]); + unit_qt(quat_rotate); } else if (viewnum == RV3D_VIEW_BACK) { - copy_v3_v3(z_rel, rv3d->viewinv[2]); + axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI); } else { BLI_assert(0); } - float angle_max = FLT_MAX; - int view_closest = -1; + mul_qt_qtqt(quat_test, rv3d->viewquat, quat_rotate); + + float angle_best = FLT_MAX; + int view_best = -1; + int view_axis_roll_best = -1; for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) { - float quat[4]; - float mat[3][3]; - ED_view3d_quat_from_axis_view(i, quat); - quat[0] *= -1.0f; - quat_to_mat3(mat, quat); - if (align_quat) { - mul_qt_qtqt(quat, quat, align_quat); - } - const float angle_test = angle_normalized_v3v3(z_rel, mat[2]); - if (angle_max > angle_test) { - angle_max = angle_test; - view_closest = i; + for (int j = RV3D_VIEW_AXIS_ROLL_0; j <= RV3D_VIEW_AXIS_ROLL_270; j++) { + float quat_axis[4]; + ED_view3d_quat_from_axis_view(i, j, quat_axis); + if (align_quat) { + mul_qt_qtqt(quat_axis, quat_axis, align_quat); + } + const float angle_test = fabsf(angle_signed_qtqt(quat_axis, quat_test)); + if (angle_best > angle_test) { + angle_best = angle_test; + view_best = i; + view_axis_roll_best = j; + } } } - if (view_closest == -1) { - view_closest = RV3D_VIEW_FRONT; + if (view_best == -1) { + view_best = RV3D_VIEW_FRONT; + view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0; } - viewnum = view_closest; + + /* Disallow non-upright views in turn-table modes, + * it's too difficult to navigate out of them. */ + if ((U.flag & USER_TRACKBALL) == 0) { + if (!ELEM(view_best, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { + view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0; + } + } + + viewnum = view_best; + view_axis_roll = view_axis_roll_best; } /* Use this to test if we started out with a camera */ const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo; float quat[4]; - ED_view3d_quat_from_axis_view(viewnum, quat); - axis_set_view(C, v3d, ar, quat, viewnum, nextperspo, align_quat, smooth_viewtx); + ED_view3d_quat_from_axis_view(viewnum, view_axis_roll, quat); + axis_set_view(C, v3d, ar, quat, viewnum, view_axis_roll, nextperspo, align_quat, smooth_viewtx); perspo = rv3d->persp; @@ -4105,7 +4124,15 @@ static int view_camera_exec(bContext *C, wmOperator *op) else { /* return to settings of last view */ /* does view3d_smooth_view too */ - axis_set_view(C, v3d, ar, rv3d->lviewquat, rv3d->lview, rv3d->lpersp, NULL, smooth_viewtx); + axis_set_view(C, + v3d, + ar, + rv3d->lviewquat, + rv3d->lview, + rv3d->lview_axis_roll, + rv3d->lpersp, + NULL, + smooth_viewtx); } } @@ -4217,7 +4244,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op) if (view_opposite != RV3D_VIEW_USER) { rv3d->view = view_opposite; /* avoid float in-precision, just get a new orientation */ - ED_view3d_quat_from_axis_view(view_opposite, quat_new); + ED_view3d_quat_from_axis_view(view_opposite, rv3d->view_axis_roll, quat_new); } else { rv3d->view = RV3D_VIEW_USER; diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index e7d514baa41..08a4947dc18 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -408,6 +408,7 @@ void ED_view3d_lastview_store(RegionView3D *rv3d) { copy_qt_qt(rv3d->lviewquat, rv3d->viewquat); rv3d->lview = rv3d->view; + rv3d->lview_axis_roll = rv3d->view_axis_roll; if (rv3d->persp != RV3D_CAMOB) { rv3d->lpersp = rv3d->persp; } @@ -470,7 +471,7 @@ bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *ar char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp; ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, persp); } - else if (autopersp && ED_view3d_quat_is_axis_aligned(rv3d->viewquat)) { + else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) { rv3d->persp = RV3D_PERSP; } return true; @@ -781,14 +782,16 @@ static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_ int i; /* we could use rv3d->viewinv, but better not depend on view matrix being updated */ - if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, viewinv) == false)) { + if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, rv3d_src->view_axis_roll, viewinv) == + false)) { return; } invert_qt_normalized(viewinv); mul_qt_v3(viewinv, view_src_x); mul_qt_v3(viewinv, view_src_y); - if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, viewinv) == false)) { + if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, rv3d_dst->view_axis_roll, viewinv) == + false)) { return; } invert_qt_normalized(viewinv); @@ -903,8 +906,9 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip) if (ar->alignment == RGN_ALIGN_QSPLIT) { rv3d = ar->regiondata; if (rv3d->viewlock) { - if (!RV3D_VIEW_IS_AXIS(rv3d->view)) { + if (!RV3D_VIEW_IS_AXIS(rv3d->view) || (rv3d->view_axis_roll != RV3D_VIEW_AXIS_ROLL_0)) { rv3d->view = ED_view3d_lock_view_from_index(index_qsplit); + rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; rv3d->persp = RV3D_ORTHO; ED_view3d_lock(rv3d); } @@ -1304,19 +1308,62 @@ bool ED_view3d_distance_set_from_location(RegionView3D *rv3d, /* -------------------------------------------------------------------- */ /** \name View Axis Utilities * \{ */ -static float view3d_quat_axis[6][4] = { - {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, /* RV3D_VIEW_FRONT */ - {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, /* RV3D_VIEW_BACK */ - {0.5f, -0.5f, 0.5f, 0.5f}, /* RV3D_VIEW_LEFT */ - {0.5f, -0.5f, -0.5f, -0.5f}, /* RV3D_VIEW_RIGHT */ - {1.0f, 0.0f, 0.0f, 0.0f}, /* RV3D_VIEW_TOP */ - {0.0f, -1.0f, 0.0f, 0.0f}, /* RV3D_VIEW_BOTTOM */ + +/** + * Lookup by axis-view, axis-roll. + */ +static float view3d_quat_axis[6][4][4] = { + /* RV3D_VIEW_FRONT */ + { + {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, + {0.5f, -0.5f, -0.5f, 0.5f}, + {0, 0, -M_SQRT1_2, M_SQRT1_2}, + {-0.5f, 0.5f, -0.5f, 0.5f}, + }, + /* RV3D_VIEW_BACK */ + { + {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, + {0.5f, 0.5f, -0.5f, -0.5f}, + {M_SQRT1_2, M_SQRT1_2, 0, 0}, + {0.5f, 0.5f, 0.5f, 0.5f}, + }, + /* RV3D_VIEW_LEFT */ + { + {0.5f, -0.5f, 0.5f, 0.5f}, + {0, -M_SQRT1_2, 0.0f, M_SQRT1_2}, + {-0.5f, -0.5f, -0.5f, 0.5f}, + {-M_SQRT1_2, 0, -M_SQRT1_2, 0}, + }, + + /* RV3D_VIEW_RIGHT */ + { + {0.5f, -0.5f, -0.5f, -0.5f}, + {M_SQRT1_2, 0, -M_SQRT1_2, 0}, + {0.5f, 0.5f, -0.5f, 0.5f}, + {0, M_SQRT1_2, 0, M_SQRT1_2}, + }, + /* RV3D_VIEW_TOP */ + { + {1.0f, 0.0f, 0.0f, 0.0f}, + {M_SQRT1_2, 0, 0, M_SQRT1_2}, + {0, 0, 0, 1}, + {-M_SQRT1_2, 0, 0, M_SQRT1_2}, + }, + /* RV3D_VIEW_BOTTOM */ + { + {0.0f, -1.0f, 0.0f, 0.0f}, + {0, -M_SQRT1_2, -M_SQRT1_2, 0}, + {0, 0, -1, 0}, + {0, M_SQRT1_2, -M_SQRT1_2, 0}, + }, + }; -bool ED_view3d_quat_from_axis_view(const char view, float quat[4]) +bool ED_view3d_quat_from_axis_view(const char view, const char view_axis_roll, float quat[4]) { + BLI_assert(view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270); if (RV3D_VIEW_IS_AXIS(view)) { - copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]); + copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT][view_axis_roll]); return true; } else { @@ -1324,35 +1371,28 @@ bool ED_view3d_quat_from_axis_view(const char view, float quat[4]) } } -char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon) +bool ED_view3d_quat_to_axis_view(const float quat[4], + const float epsilon, + char *r_view, + char *r_view_axis_roll) { - /* quat values are all unit length */ + *r_view = RV3D_VIEW_USER; + *r_view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; - char view; - - for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) { - if (fabsf(angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT])) < epsilon) { - return view; + /* quat values are all unit length */ + for (int view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) { + for (int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270; + view_axis_roll++) { + if (fabsf(angle_signed_qtqt( + quat, view3d_quat_axis[view - RV3D_VIEW_FRONT][view_axis_roll])) < epsilon) { + *r_view = view; + *r_view_axis_roll = view_axis_roll; + return true; + } } } - return RV3D_VIEW_USER; -} - -/** - * Returns true if input view quaternion is aligned view axis in direction & angle. - */ -bool ED_view3d_quat_is_axis_aligned(const float viewquat[4]) -{ - float mat[3][3]; - quat_to_mat3(mat, viewquat); - for (int row = 0; row < 3; row++) { - int axis = axis_dominant_v3_single(mat[row]); - if (fabsf(fabsf(mat[row][axis]) - 1.0f) > 1e-4f) { - return false; - } - } - return true; + return false; } char ED_view3d_lock_view_from_index(int index) @@ -1391,7 +1431,7 @@ char ED_view3d_axis_view_opposite(char view) bool ED_view3d_lock(RegionView3D *rv3d) { - return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat); + return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, rv3d->viewquat); } /** \} */ |