[Bf-blender-cvs] [2ba2d2bd9de] blender-v2.92-release: Fix T76936: Mesh shape amended upon undoing in sculpt mode

Sergey Sharybin noreply at git.blender.org
Fri Jan 22 12:26:08 CET 2021


Commit: 2ba2d2bd9ded9b944ff94894bc09d695cdb5bae0
Author: Sergey Sharybin
Date:   Wed Jan 20 12:13:48 2021 +0100
Branches: blender-v2.92-release
https://developer.blender.org/rB2ba2d2bd9ded9b944ff94894bc09d695cdb5bae0

Fix T76936: Mesh shape amended upon undoing in sculpt mode

Was happening when there are deform modifiers prior to the multires.

There are detail in the comment around sculpt_undo_refine_subdiv(),
but briefly: the subdiv was refined with wrong base mesh coordinates.

Differential Revision: https://developer.blender.org/D10158

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

M	source/blender/editors/sculpt_paint/sculpt_undo.c

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

diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 443aee81696..938080b392d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -55,7 +55,7 @@
 #include "BKE_subsurf.h"
 #include "BKE_undo_system.h"
 
-/* XXX: Ideally should be no direct call to such low level things. */
+/* TODO(sergey): Ideally should be no direct call to such low level things. */
 #include "BKE_subdiv_eval.h"
 
 #include "DEG_depsgraph.h"
@@ -609,6 +609,32 @@ static int sculpt_undo_bmesh_restore(bContext *C,
   return false;
 }
 
+/* Geometry updates (such as Apply Base, for example) will re-evaluate the object and refine its
+ * Subdiv descriptor. Upon undo it is required that mesh, grids, and subdiv all stay consistent
+ * with each other. This means that when geometry coordinate changes the undo should refine the
+ * subdiv to the new coarse mesh coordinates. Tricky part is: this needs to happen without using
+ * dependency graph tag: tagging object for geometry update will either loose sculpted data from
+ * the sculpt grids, or will wrongly "commit" them to the CD_MDISPS.
+ *
+ * So what we do instead is do minimum object evaluation to get base mesh coordinates for the
+ * multires modifier input. While this is expensive, it is less expensive than dependency graph
+ * evaluation and is only happening when geometry coordinates changes on undo.
+ *
+ * Note that the dependency graph is ensured to be evaluated prior to the undo step is decoded,
+ * so if the object's modifier stack references other object it is all fine. */
+static void sculpt_undo_refine_subdiv(Depsgraph *depsgraph,
+                                      SculptSession *ss,
+                                      Object *object,
+                                      struct Subdiv *subdiv)
+{
+  float(*deformed_verts)[3] = BKE_multires_create_deformed_base_mesh_vert_coords(
+      depsgraph, object, ss->multires.modifier, NULL);
+
+  BKE_subdiv_eval_refine_from_mesh(subdiv, object->data, deformed_verts);
+
+  MEM_freeN(deformed_verts);
+}
+
 static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase *lb)
 {
   Scene *scene = CTX_data_scene(C);
@@ -620,6 +646,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
   SculptUndoNode *unode;
   bool update = false, rebuild = false, update_mask = false, update_visibility = false;
   bool need_mask = false;
+  bool need_refine_subdiv = false;
 
   for (unode = lb->first; unode; unode = unode->next) {
     /* Restore pivot. */
@@ -731,6 +758,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
         break;
 
       case SCULPT_UNDO_GEOMETRY:
+        need_refine_subdiv = true;
         sculpt_undo_geometry_restore(unode, ob);
         BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask, false);
         break;
@@ -762,8 +790,8 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
     }
   }
 
-  if (subdiv_ccg != NULL) {
-    BKE_subdiv_eval_refine_from_mesh(subdiv_ccg->subdiv, ob->data, NULL);
+  if (subdiv_ccg != NULL && need_refine_subdiv) {
+    sculpt_undo_refine_subdiv(depsgraph, ss, ob, subdiv_ccg->subdiv);
   }
 
   if (update || rebuild) {



More information about the Bf-blender-cvs mailing list