[Bf-blender-cvs] [bad55d56bc7] master: Mesh: Parallelize remesh reprojections

Erik Abrahamsson noreply at git.blender.org
Wed Nov 2 23:25:10 CET 2022


Commit: bad55d56bc71ec9b5f2478de6a1ce350b474de57
Author: Erik Abrahamsson
Date:   Wed Nov 2 23:23:20 2022 +0100
Branches: master
https://developer.blender.org/rBbad55d56bc71ec9b5f2478de6a1ce350b474de57

Mesh: Parallelize remesh reprojections

In high poly meshes the reprojections after remesh can become slow.
This parallelizes reprojection of face sets, paint mask and vertex paint.
It also adds flags to disable dependency graph updates on
setting remesh options to remove UI lag.

Profiling of remeshing a 3.4M poly mesh (in sculpt mode):
Before: 19.6s
After: 8.7s

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

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

M	source/blender/blenkernel/intern/mesh_remesh_voxel.cc
M	source/blender/makesrna/intern/rna_mesh.c

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

diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc
index 62354c83df1..f38efd2cf65 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc
@@ -19,6 +19,7 @@
 #include "BLI_math_vec_types.hh"
 #include "BLI_math_vector.h"
 #include "BLI_span.hh"
+#include "BLI_task.hh"
 
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
@@ -302,17 +303,20 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, const Mesh *source)
         &target->vdata, CD_PAINT_MASK, CD_CONSTRUCT, nullptr, target->totvert);
   }
 
-  for (int i = 0; i < target->totvert; i++) {
-    float from_co[3];
-    BVHTreeNearest nearest;
-    nearest.index = -1;
-    nearest.dist_sq = FLT_MAX;
-    copy_v3_v3(from_co, target_verts[i].co);
-    BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
-    if (nearest.index != -1) {
-      target_mask[i] = source_mask[nearest.index];
+  blender::threading::parallel_for(IndexRange(target->totvert), 4096, [&](const IndexRange range) {
+    for (const int i : range) {
+      float from_co[3];
+      BVHTreeNearest nearest;
+      nearest.index = -1;
+      nearest.dist_sq = FLT_MAX;
+      copy_v3_v3(from_co, target_verts[i].co);
+      BLI_bvhtree_find_nearest(
+          bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
+      if (nearest.index != -1) {
+        target_mask[i] = source_mask[nearest.index];
+      }
     }
-  }
+  });
   free_bvhtree_from_mesh(&bvhtree);
 }
 
@@ -344,21 +348,24 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
   BVHTreeFromMesh bvhtree = {nullptr};
   BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2);
 
-  for (int i = 0; i < target->totpoly; i++) {
-    float from_co[3];
-    BVHTreeNearest nearest;
-    nearest.index = -1;
-    nearest.dist_sq = FLT_MAX;
-    const MPoly *mpoly = &target_polys[i];
-    BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co);
-    BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
-    if (nearest.index != -1) {
-      dst[i] = src[looptri[nearest.index].poly];
-    }
-    else {
-      dst[i] = 1;
+  blender::threading::parallel_for(IndexRange(target->totpoly), 2048, [&](const IndexRange range) {
+    for (const int i : range) {
+      float from_co[3];
+      BVHTreeNearest nearest;
+      nearest.index = -1;
+      nearest.dist_sq = FLT_MAX;
+      const MPoly *mpoly = &target_polys[i];
+      BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co);
+      BLI_bvhtree_find_nearest(
+          bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
+      if (nearest.index != -1) {
+        dst[i] = src[looptri[nearest.index].poly];
+      }
+      else {
+        dst[i] = 1;
+      }
     }
-  }
+  });
   free_bvhtree_from_mesh(&bvhtree);
   dst_face_sets.finish();
 }
@@ -399,19 +406,22 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
     MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
 
     if (domain == ATTR_DOMAIN_POINT) {
-      for (int i = 0; i < target->totvert; i++) {
-        BVHTreeNearest nearest;
-        nearest.index = -1;
-        nearest.dist_sq = FLT_MAX;
-        BLI_bvhtree_find_nearest(
-            bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
-
-        if (nearest.index != -1) {
-          memcpy(POINTER_OFFSET(target_data, size_t(i) * data_size),
-                 POINTER_OFFSET(source_data, size_t(nearest.index) * data_size),
-                 data_size);
-        }
-      }
+      blender::threading::parallel_for(
+          IndexRange(target->totvert), 4096, [&](const IndexRange range) {
+            for (const int i : range) {
+              BVHTreeNearest nearest;
+              nearest.index = -1;
+              nearest.dist_sq = FLT_MAX;
+              BLI_bvhtree_find_nearest(
+                  bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
+
+              if (nearest.index != -1) {
+                memcpy(POINTER_OFFSET(target_data, size_t(i) * data_size),
+                       POINTER_OFFSET(source_data, size_t(nearest.index) * data_size),
+                       data_size);
+              }
+            }
+          });
     }
     else {
       /* Lazily init vertex -> loop maps. */
@@ -438,46 +448,50 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
                                       target->totloop);
       }
 
-      for (int i = 0; i < target->totvert; i++) {
-        BVHTreeNearest nearest;
-        nearest.index = -1;
-        nearest.dist_sq = FLT_MAX;
-        BLI_bvhtree_find_nearest(
-            bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
-
-        if (nearest.index == -1) {
-          continue;
-        }
-
-        MeshElemMap *source_loops = source_lmap + nearest.index;
-        MeshElemMap *target_loops = target_lmap + i;
-
-        if (target_loops->count == 0 || source_loops->count == 0) {
-          continue;
-        }
-
-        /*
-         * Average color data for loops around the source vertex into
-         * the first target loop around the target vertex
-         */
-
-        CustomData_interp(source_cdata,
-                          target_cdata,
-                          source_loops->indices,
-                          nullptr,
-                          nullptr,
-                          source_loops->count,
-                          target_loops->indices[0]);
-
-        void *elem = POINTER_OFFSET(target_data, size_t(target_loops->indices[0]) * data_size);
-
-        /* Copy to rest of target loops. */
-        for (int j = 1; j < target_loops->count; j++) {
-          memcpy(POINTER_OFFSET(target_data, size_t(target_loops->indices[j]) * data_size),
-                 elem,
-                 data_size);
-        }
-      }
+      blender::threading::parallel_for(
+          IndexRange(target->totvert), 2048, [&](const IndexRange range) {
+            for (const int i : range) {
+              BVHTreeNearest nearest;
+              nearest.index = -1;
+              nearest.dist_sq = FLT_MAX;
+              BLI_bvhtree_find_nearest(
+                  bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
+
+              if (nearest.index == -1) {
+                continue;
+              }
+
+              MeshElemMap *source_loops = source_lmap + nearest.index;
+              MeshElemMap *target_loops = target_lmap + i;
+
+              if (target_loops->count == 0 || source_loops->count == 0) {
+                continue;
+              }
+
+              /*
+               * Average color data for loops around the source vertex into
+               * the first target loop around the target vertex
+               */
+
+              CustomData_interp(source_cdata,
+                                target_cdata,
+                                source_loops->indices,
+                                nullptr,
+                                nullptr,
+                                source_loops->count,
+                                target_loops->indices[0]);
+
+              void *elem = POINTER_OFFSET(target_data,
+                                          size_t(target_loops->indices[0]) * data_size);
+
+              /* Copy to rest of target loops. */
+              for (int j = 1; j < target_loops->count; j++) {
+                memcpy(POINTER_OFFSET(target_data, size_t(target_loops->indices[j]) * data_size),
+                       elem,
+                       data_size);
+              }
+            }
+          });
     }
   }
 
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index bad099815a4..f13132b5b7c 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -4024,6 +4024,7 @@ static void rna_def_mesh(BlenderRNA *brna)
                            "Size of the voxel in object space used for volume evaluation. Lower "
                            "values preserve finer details");
   RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+  RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
 
   prop = RNA_def_property(srna, "remesh_voxel_adaptivity", PROP_FLOAT, PROP_DISTANCE);
   RNA_def_property_float_sdna(prop, NULL, "remesh_voxel_adaptivity");
@@ -4035,11 +4036,13 @@ static void rna_def_mesh(BlenderRNA *brna)
       "Reduces the final face count by simplifying geometry where detail is not needed, "
       "generating triangles. A value greater than 0 disables Fix Poles");
   RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+  RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
 
   prop = RNA_def_property(srna, "use_remesh_fix_poles", PROP_BOOLEAN, PROP_NONE);
   RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_REMESH_FIX_POLES);
   RNA_def_property_ui_text(prop, "Fix Poles", "Produces less poles and a better topology flow");
   RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+  RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
 
   prop = RNA_def_property(srna, "use_remesh_preserve_volume", PROP_BOOLEAN, PROP_NONE);
   RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_REMESH_REPROJECT_VOLUME);
@@ -4048,29 +4051,34 @@ static void rna_def_mesh(BlenderRNA *brna)
       "Preserve Volume",
       "Projects the mesh to preserve the volume and details of the original mesh");
   RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+  RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
 
   prop = RNA_def_property(srna, "use_remesh_preserve_paint_mask", PROP_BOOLEAN, PROP_NONE);
   RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_REMESH_REPROJECT_PAINT_MASK);
   RNA_def_property_ui_text(prop, "Preserve Paint Mask", "Keep the current mask on the new mesh");
   RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+  RNA_def_property_flag(prop, PROP_NO_DEG_UP

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list