diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-08-02 11:08:46 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-08-02 11:10:07 +0300 |
commit | f349a53c0815b7b6e5f7b432b10a4eeebe266341 (patch) | |
tree | 8e6c39419b0559766e1acddab1562f7fe7a5d31b /source | |
parent | 70d7805fa901d9678db3557f6e81877b6b94128a (diff) |
Fix T78691: Fly/Walk navigation ignores object channel locks
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_camera_control.c | 64 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_fly.c | 17 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_walk.c | 18 |
3 files changed, 67 insertions, 32 deletions
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index 7e63d650409..1d5b33e7b90 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -198,6 +198,56 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph } /** + * A version of #BKE_object_apply_mat4 that respects #Object.protectflag, + * applying the locking back to the view to avoid the view. + * This is needed so the view doesn't get out of sync with the object, + * causing visible jittering when in fly/walk mode for e.g. + * + * \note This could be exposed as an API option, as we might not want the view + * to be constrained by the thing it's controlling. + */ +static bool object_apply_mat4_with_protect(Object *ob, + const float obmat[4][4], + const bool use_parent, + /* Only use when applying lock. */ + RegionView3D *rv3d, + const float view_mat[4][4]) +{ + const bool use_protect = (ob->protectflag != 0); + bool view_changed = false; + + ObjectTfmProtectedChannels obtfm; + if (use_protect) { + BKE_object_tfm_protected_backup(ob, &obtfm); + } + + BKE_object_apply_mat4(ob, obmat, true, use_parent); + + if (use_protect) { + float obmat_noprotect[4][4], obmat_protect[4][4]; + + BKE_object_to_mat4(ob, obmat_noprotect); + BKE_object_tfm_protected_restore(ob, &obtfm, ob->protectflag); + BKE_object_to_mat4(ob, obmat_protect); + + if (!equals_m4m4(obmat_noprotect, obmat_protect)) { + /* Apply the lock protection back to the view, without this the view + * keeps moving, ignoring the object locking, causing jittering in some cases. */ + float diff_mat[4][4]; + float view_mat_protect[4][4]; + float obmat_noprotect_inv[4][4]; + invert_m4_m4(obmat_noprotect_inv, obmat_noprotect); + mul_m4_m4m4(diff_mat, obmat_protect, obmat_noprotect_inv); + + mul_m4_m4m4(view_mat_protect, diff_mat, view_mat); + ED_view3d_from_m4(view_mat_protect, rv3d->ofs, rv3d->viewquat, &rv3d->dist); + view_changed = true; + } + } + return view_changed; +} + +/** * Updates cameras from the ``rv3d`` values, optionally auto-keyframing. */ void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl, @@ -216,21 +266,25 @@ void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl, ID *id_key; + float view_mat[4][4]; + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + /* transform the parent or the camera? */ if (vctrl->root_parent) { Object *ob_update; - float view_mat[4][4]; float prev_view_imat[4][4]; float diff_mat[4][4]; float parent_mat[4][4]; invert_m4_m4(prev_view_imat, vctrl->view_mat_prev); - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); mul_m4_m4m4(diff_mat, view_mat, prev_view_imat); mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat); - BKE_object_apply_mat4(vctrl->root_parent, parent_mat, true, false); + if (object_apply_mat4_with_protect(vctrl->root_parent, parent_mat, false, rv3d, view_mat)) { + /* Calculate again since the view locking changes the matrix. */ + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + } ob_update = v3d->camera->parent; while (ob_update) { @@ -243,18 +297,16 @@ void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl, id_key = &vctrl->root_parent->id; } else { - float view_mat[4][4]; float scale_mat[4][4]; float scale_back[3]; /* even though we handle the scale matrix, this still changes over time */ copy_v3_v3(scale_back, v3d->camera->scale); - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); size_to_mat4(scale_mat, v3d->camera->scale); mul_m4_m4m4(view_mat, view_mat, scale_mat); - BKE_object_apply_mat4(v3d->camera, view_mat, true, true); + object_apply_mat4_with_protect(v3d->camera, view_mat, true, rv3d, view_mat); DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM); diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index cc19ecf35a8..556b5d51505 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -16,6 +16,10 @@ /** \file * \ingroup spview3d + * + * Interactive fly navigation modal operator (flying around in space). + * + * \note Similar logic to `view3d_walk.c` changes here may apply there too. */ /* defines VIEW3D_OT_fly modal operator */ @@ -998,19 +1002,6 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm) interp_v3_v3v3( dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC)))); - if (rv3d->persp == RV3D_CAMOB) { - Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control); - if (lock_ob->protectflag & OB_LOCK_LOCX) { - dvec[0] = 0.0; - } - if (lock_ob->protectflag & OB_LOCK_LOCY) { - dvec[1] = 0.0; - } - if (lock_ob->protectflag & OB_LOCK_LOCZ) { - dvec[2] = 0.0; - } - } - add_v3_v3(rv3d->ofs, dvec); if (rv3d->persp == RV3D_CAMOB) { diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 751e37f0235..64167b83655 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -16,6 +16,11 @@ /** \file * \ingroup spview3d + * + * Interactive walk navigation modal operator + * (similar to walking around in a first person game). + * + * \note Similar logic to `view3d_fly.c` changes here may apply there too. */ /* defines VIEW3D_OT_navigate - walk modal operator */ @@ -1295,19 +1300,6 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) sub_v3_v3v3(dvec, cur_loc, new_loc); } - if (rv3d->persp == RV3D_CAMOB) { - Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); - if (lock_ob->protectflag & OB_LOCK_LOCX) { - dvec[0] = 0.0f; - } - if (lock_ob->protectflag & OB_LOCK_LOCY) { - dvec[1] = 0.0f; - } - if (lock_ob->protectflag & OB_LOCK_LOCZ) { - dvec[2] = 0.0f; - } - } - /* scale the movement to the scene size */ mul_v3_v3fl(dvec_tmp, dvec, walk->grid); add_v3_v3(rv3d->ofs, dvec_tmp); |