[Bf-blender-cvs] [f349a53c081] blender-v2.90-release: Fix T78691: Fly/Walk navigation ignores object channel locks

Campbell Barton noreply at git.blender.org
Sun Aug 2 10:10:57 CEST 2020


Commit: f349a53c0815b7b6e5f7b432b10a4eeebe266341
Author: Campbell Barton
Date:   Sun Aug 2 18:08:46 2020 +1000
Branches: blender-v2.90-release
https://developer.blender.org/rBf349a53c0815b7b6e5f7b432b10a4eeebe266341

Fix T78691: Fly/Walk navigation ignores object channel locks

===================================================================

M	source/blender/editors/space_view3d/view3d_camera_control.c
M	source/blender/editors/space_view3d/view3d_fly.c
M	source/blender/editors/space_view3d/view3d_walk.c

===================================================================

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
@@ -197,6 +197,56 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph
   return vctrl;
 }
 
+/**
+ * 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.
  */
@@ -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);



More information about the Bf-blender-cvs mailing list