[Bf-blender-cvs] [d20f9923224] master: Mesh: Avoid copying positions in object mode modifier stack

Hans Goudey noreply at git.blender.org
Mon Feb 6 20:36:32 CET 2023


Commit: d20f9923224d2637374dd4390ae84c5041e3f9d3
Author: Hans Goudey
Date:   Mon Feb 6 14:34:16 2023 -0500
Branches: master
https://developer.blender.org/rBd20f9923224d2637374dd4390ae84c5041e3f9d3

Mesh: Avoid copying positions in object mode modifier stack

Remove the use of a separate contiguous positions array now that
they are stored that way in the first place. This allows removing the
complexity of tracking whether it is allocated and deformed in the
mesh modifier stack.

Instead of deferring the creation of the final mesh until after the
positions have been copied and deformed, create the final mesh
first and then deform its positions.

Since vertex and face normals are calculated lazily, we can rely on
individual modifiers to calculate them as necessary and simplify
the modifier stack. This was hard to change before because of the
separate array of deformed positions.

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

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

M	source/blender/blenkernel/intern/DerivedMesh.cc
M	source/blender/blenkernel/intern/modifier.cc

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

diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index c3d535a3e9d..bd0fdadec5c 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -661,23 +661,17 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
                                 GeometrySet **r_geometry_set)
 {
   using namespace blender::bke;
-  /* Input and final mesh. Final mesh is only created the moment the first
-   * constructive modifier is executed, or a deform modifier needs normals
-   * or certain data layers. */
+  /* Input mesh shouldn't be modified. */
   Mesh *mesh_input = (Mesh *)ob->data;
+  /* The final mesh is the result of calculating all enabled modifiers. */
   Mesh *mesh_final = nullptr;
+  /* The result of calculating all leading deform modifiers. */
   Mesh *mesh_deform = nullptr;
   /* This geometry set contains the non-mesh data that might be generated by modifiers. */
   GeometrySet geometry_set_final;
 
   BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
 
-  /* TODO: Remove use of `deformed_verts` in mesh modifier stack
-   * since mesh positions are now stored in a contiguous array. */
-  float(*deformed_verts)[3] = nullptr;
-  int num_deformed_verts = mesh_input->totvert;
-  bool isPrevDeform = false;
-
   /* Mesh with constructive modifiers but no deformation applied. Tracked
    * along with final mesh if undeformed / orco coordinates are requested
    * for texturing. */
@@ -761,20 +755,15 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
 
       if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
         blender::bke::ScopedModifierTimer modifier_timer{*md};
-        if (!deformed_verts) {
-          deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts);
-        }
-        else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
-          if (mesh_final == nullptr) {
-            mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
-            ASSERT_IS_VALID_MESH(mesh_final);
-          }
-          BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
+        if (!mesh_final) {
+          mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
+          ASSERT_IS_VALID_MESH(mesh_final);
         }
-
-        BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
-
-        isPrevDeform = true;
+        BKE_modifier_deform_verts(md,
+                                  &mectx,
+                                  mesh_final,
+                                  BKE_mesh_vert_positions_for_write(mesh_final),
+                                  mesh_final->totvert);
       }
       else {
         break;
@@ -786,10 +775,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
      * coordinates (like vertex paint). */
     if (r_deform) {
       mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true);
-
-      if (deformed_verts) {
-        BKE_mesh_vert_coords_apply(mesh_deform, deformed_verts);
-      }
     }
   }
 
@@ -858,36 +843,19 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
       }
     }
 
-    /* How to apply modifier depends on (a) what we already have as
-     * a result of previous modifiers (could be a Mesh or just
-     * deformed vertices) and (b) what type the modifier is. */
     if (mti->type == eModifierTypeType_OnlyDeform) {
-      /* No existing verts to deform, need to build them. */
-      if (!deformed_verts) {
-        if (mesh_final) {
-          /* Deforming a mesh, read the vertex locations
-           * out of the mesh and deform them. Once done with this
-           * run of deformers verts will be written back. */
-          deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts);
-        }
-        else {
-          deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts);
-        }
-      }
-      /* if this is not the last modifier in the stack then recalculate the normals
-       * to avoid giving bogus normals to the next modifier see: T23673. */
-      else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
-        if (mesh_final == nullptr) {
-          mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
-          ASSERT_IS_VALID_MESH(mesh_final);
-        }
-        BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
+      if (!mesh_final) {
+        mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
+        ASSERT_IS_VALID_MESH(mesh_final);
       }
-      BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
+      BKE_modifier_deform_verts(md,
+                                &mectx,
+                                mesh_final,
+                                BKE_mesh_vert_positions_for_write(mesh_final),
+                                mesh_final->totvert);
     }
     else {
       bool check_for_needs_mapping = false;
-      /* apply vertex coordinates or build a Mesh as necessary */
       if (mesh_final != nullptr) {
         if (have_non_onlydeform_modifiers_appled == false) {
           /* If we only deformed, we won't have initialized #CD_ORIGINDEX.
@@ -901,10 +869,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
         check_for_needs_mapping = true;
       }
 
-      if (deformed_verts) {
-        BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
-      }
-
       have_non_onlydeform_modifiers_appled = true;
 
       /* determine which data layers are needed by following modifiers */
@@ -985,11 +949,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
           BKE_id_free(nullptr, mesh_final);
         }
         mesh_final = mesh_next;
-
-        if (deformed_verts) {
-          MEM_freeN(deformed_verts);
-          deformed_verts = nullptr;
-        }
       }
 
       /* create an orco mesh in parallel */
@@ -1060,8 +1019,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
       mesh_final->runtime->deformed_only = false;
     }
 
-    isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
-
     if (sculpt_mode && md->type == eModifierType_Multires) {
       multires_applied = true;
     }
@@ -1073,22 +1030,14 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
     BKE_modifier_free_temporary_data(md);
   }
 
-  /* Yay, we are done. If we have a Mesh and deformed vertices,
-   * we need to apply these back onto the Mesh. If we have no
-   * Mesh then we need to build one. */
   if (mesh_final == nullptr) {
-    if (deformed_verts == nullptr && allow_shared_mesh) {
+    if (allow_shared_mesh) {
       mesh_final = mesh_input;
     }
     else {
       mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
     }
   }
-  if (deformed_verts) {
-    BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
-    MEM_freeN(deformed_verts);
-    deformed_verts = nullptr;
-  }
 
   /* Denotes whether the object which the modifier stack came from owns the mesh or whether the
    * mesh is shared across multiple objects since there are no effective modifiers. */
diff --git a/source/blender/blenkernel/intern/modifier.cc b/source/blender/blenkernel/intern/modifier.cc
index d0ccdedc136..580c08a51ba 100644
--- a/source/blender/blenkernel/intern/modifier.cc
+++ b/source/blender/blenkernel/intern/modifier.cc
@@ -1017,6 +1017,9 @@ void BKE_modifier_deform_verts(ModifierData *md,
     modwrap_dependsOnNormals(me);
   }
   mti->deformVerts(md, ctx, me, vertexCos, numVerts);
+  if (me) {
+    BKE_mesh_tag_coords_changed(me);
+  }
 }
 
 void BKE_modifier_deform_vertsEM(ModifierData *md,



More information about the Bf-blender-cvs mailing list