[Bf-blender-cvs] [ae349eb2d50] master: Sculpt: Multires Heal Brush

Joseph Eagar noreply at git.blender.org
Thu Jan 20 02:29:26 CET 2022


Commit: ae349eb2d50524b030f702b8ed3fd75531d4db7e
Author: Joseph Eagar
Date:   Wed Jan 19 17:23:36 2022 -0800
Branches: master
https://developer.blender.org/rBae349eb2d50524b030f702b8ed3fd75531d4db7e

Sculpt: Multires Heal Brush

This brush fixes the random spikes that
occasionally happen in multires models.
These spikes can be nearly impossible to
fix manually and can make working with
multires a nightmare.

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

A	release/datafiles/icons/brush.sculpt.displacement_heal.dat
M	release/datafiles/icons/brush.sculpt.draw_sharp.dat
M	source/blender/blenkernel/BKE_subdiv_ccg.h
M	source/blender/blenkernel/intern/subdiv_ccg.c
M	source/blender/editors/datafiles/CMakeLists.txt
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_brush_types.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/makesdna/DNA_brush_enums.h
M	source/blender/makesrna/intern/rna_brush.c

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

diff --git a/release/datafiles/icons/brush.sculpt.displacement_heal.dat b/release/datafiles/icons/brush.sculpt.displacement_heal.dat
new file mode 100644
index 00000000000..24960495f21
Binary files /dev/null and b/release/datafiles/icons/brush.sculpt.displacement_heal.dat differ
diff --git a/release/datafiles/icons/brush.sculpt.draw_sharp.dat b/release/datafiles/icons/brush.sculpt.draw_sharp.dat
index 1877c0ae4d4..9bea1b02894 100644
Binary files a/release/datafiles/icons/brush.sculpt.draw_sharp.dat and b/release/datafiles/icons/brush.sculpt.draw_sharp.dat differ
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index b3aa966e0d0..2de16bbddd4 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -314,6 +314,17 @@ void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG *subdiv_ccg,
                                      const SubdivCCGCoord *coord,
                                      float r_point[3]);
 
+void BKE_subdiv_ccg_eval_limit_point_and_derivatives(const SubdivCCG *subdiv_ccg,
+                                                     const SubdivCCGCoord *coord,
+                                                     float r_point[3],
+                                                     float r_dPdu[3],
+                                                     float r_dPdv[3]);
+
+void BKE_subdiv_ccg_get_tangent_matrix(const SubdivCCG *subdiv_ccg,
+                                       const SubdivCCGCoord *coord,
+                                       float mat[3][3],
+                                       float r_point[3]);
+
 typedef enum SubdivCCGAdjacencyType {
   SUBDIV_CCG_ADJACENT_NONE,
   SUBDIV_CCG_ADJACENT_VERTEX,
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index 7d876acf776..2acf94cf7d1 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -37,6 +37,7 @@
 #include "BKE_ccg.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
+#include "BKE_multires.h"
 #include "BKE_subdiv.h"
 #include "BKE_subdiv_eval.h"
 
@@ -2102,4 +2103,38 @@ void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG *subdiv_ccg,
   BKE_subdiv_eval_limit_point(subdiv, ptex_face_index, u, v, r_point);
 }
 
+void BKE_subdiv_ccg_eval_limit_point_and_derivatives(const SubdivCCG *subdiv_ccg,
+                                                     const SubdivCCGCoord *coord,
+                                                     float r_point[3],
+                                                     float r_dPdu[3],
+                                                     float r_dPdv[3])
+{
+  Subdiv *subdiv = subdiv_ccg->subdiv;
+  int ptex_face_index;
+  float u, v;
+  subdiv_ccg_coord_to_ptex_coord(subdiv_ccg, coord, &ptex_face_index, &u, &v);
+  BKE_subdiv_eval_limit_point_and_derivatives(
+      subdiv, ptex_face_index, u, v, r_point, r_dPdu, r_dPdv);
+}
+
+void BKE_subdiv_ccg_get_tangent_matrix(const SubdivCCG *subdiv_ccg,
+                                       const SubdivCCGCoord *coord,
+                                       float mat[3][3],
+                                       float r_point[3])
+{
+  int ptex_face_index;
+  float u, v;
+  float du[3], dv[3];
+
+  const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord->grid_index);
+  const SubdivCCGFace *faces = subdiv_ccg->faces;
+  const SubdivCCGFace *face = &faces[face_index];
+  const float corner = coord->grid_index - face->start_grid_index;
+
+  subdiv_ccg_coord_to_ptex_coord(subdiv_ccg, coord, &ptex_face_index, &u, &v);
+
+  BKE_subdiv_ccg_eval_limit_point_and_derivatives(subdiv_ccg, coord, r_point, du, dv);
+  BKE_multires_construct_tangent_matrix(mat, du, dv, corner);
+}
+
 /** \} */
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 8d32eba1766..1ec4b443bd2 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -751,7 +751,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
   brush.sculpt.cloth
   brush.sculpt.crease
   brush.sculpt.displacement_eraser
-  brush.sculpt.displacement_smear
+  brush.sculpt.displacement_heal
   brush.sculpt.draw
   brush.sculpt.draw_face_sets
   brush.sculpt.draw_sharp
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 5ac13ebdd93..9d07471c7bd 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -2229,6 +2229,7 @@ static float brush_strength(const Sculpt *sd,
     case SCULPT_TOOL_DRAW_SHARP:
     case SCULPT_TOOL_LAYER:
       return alpha * flip * pressure * overlap * feather;
+    case SCULPT_TOOL_DISPLACEMENT_HEAL:
     case SCULPT_TOOL_DISPLACEMENT_ERASER:
       return alpha * pressure * overlap * feather;
     case SCULPT_TOOL_CLOTH:
@@ -3400,6 +3401,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
     case SCULPT_TOOL_DISPLACEMENT_SMEAR:
       SCULPT_do_displacement_smear_brush(sd, ob, nodes, totnode);
       break;
+    case SCULPT_TOOL_DISPLACEMENT_HEAL:
+      SCULPT_do_displacement_heal_brush(sd, ob, nodes, totnode);
+      break;
     case SCULPT_TOOL_PAINT:
       SCULPT_do_paint_brush(sd, ob, nodes, totnode);
       break;
@@ -3950,6 +3954,8 @@ static const char *sculpt_tool_name(Sculpt *sd)
       return "Multires Displacement Eraser";
     case SCULPT_TOOL_DISPLACEMENT_SMEAR:
       return "Multires Displacement Smear";
+    case SCULPT_TOOL_DISPLACEMENT_HEAL:
+      return "Multires Heal";
     case SCULPT_TOOL_PAINT:
       return "Paint Brush";
     case SCULPT_TOOL_SMEAR:
diff --git a/source/blender/editors/sculpt_paint/sculpt_brush_types.c b/source/blender/editors/sculpt_paint/sculpt_brush_types.c
index c2acc361a79..5d0f4f2e30e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_brush_types.c
+++ b/source/blender/editors/sculpt_paint/sculpt_brush_types.c
@@ -2845,3 +2845,181 @@ void SCULPT_do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 }
 
 /** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Multires Heal Brush
+ * \{ */
+
+BLI_INLINE int grid_xy_to_vertex(int x, int y, int grid_i, int gridsize)
+{
+  return grid_i * gridsize * gridsize + y * gridsize + x;
+}
+
+typedef struct DisplacementHealTaskData {
+  Object *ob;
+  Brush *brush;
+  Sculpt *sd;
+  PBVHNode **nodes;
+  BLI_bitmap *bitmap;
+  float plane_view[3];
+  float bstrength;
+} DisplacementHealTaskData;
+
+static void do_displacement_heal_cb(void *__restrict userdata,
+                                    const int n,
+                                    const TaskParallelTLS *__restrict tls)
+{
+  DisplacementHealTaskData *data = userdata;
+  SculptSession *ss = data->ob->sculpt;
+
+  PBVHNode *node = data->nodes[n];
+
+  CCGElem **grids;
+
+  int *grid_indices, totgrid, maxgrid, gridsize;
+  const float bstrength = data->bstrength;
+
+  BKE_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid, &maxgrid, &gridsize, &grids);
+
+  float(*disps)[3] = MEM_calloc_arrayN(gridsize * gridsize, sizeof(float) * 3, __func__);
+  float(*mats)[16] = MEM_calloc_arrayN(gridsize * gridsize, sizeof(float) * 16, __func__);
+  float(*limits)[3] = MEM_calloc_arrayN(gridsize * gridsize, sizeof(float) * 3, __func__);
+
+  bool modified = false;
+
+  for (int i = 0; i < totgrid; i++) {
+    const int grid_i = grid_indices[i];
+
+    for (int x = 0; x < gridsize; x++) {
+      for (int y = 0; y < gridsize; y++) {
+        int vertex = grid_xy_to_vertex(x, y, grid_i, gridsize);
+
+        SubdivCCGCoord coord = {.grid_index = grid_i, .x = x, .y = y};
+        int locali = y * gridsize + x;
+        float mat[3][3], p[3];
+
+        BKE_subdiv_ccg_get_tangent_matrix(ss->subdiv_ccg, &coord, mat, p);
+        copy_m3_m3(mats[locali], mat);
+
+        invert_m3(mat);
+
+        float disp[3];
+        copy_v3_v3(disp, SCULPT_vertex_co_get(ss, vertex));
+        sub_v3_v3(disp, p);
+        mul_v3_m3v3(disp, mat, disp);
+
+        float test = dot_v3v3(disp, disp);
+        if (isnan(test) || isinf(test)) {
+          zero_v3(disp);
+        }
+
+        copy_v3_v3(disps[locali], disp);
+        copy_v3_v3(limits[locali], p);
+      }
+    }
+
+    for (int x = 0; x < gridsize; x++) {
+      for (int y = 0; y < gridsize; y++) {
+        int locali = y * gridsize + x;
+
+        int vertex = grid_xy_to_vertex(x, y, grid_i, gridsize);
+        float *disp = disps[locali];
+        float avg[3] = {0.0f, 0.0f, 0.0f};
+        float tot = 0.0f;
+
+        for (int x2 = x - 1; x2 <= x + 1; x2++) {
+          for (int y2 = y - 1; y2 <= y + 1; y2++) {
+            if (x2 < 0 || y2 < 0 || x2 >= gridsize || y2 >= gridsize) {
+              continue;
+            }
+
+            int local2 = y2 * gridsize + x2;
+
+            add_v3_v3(avg, disps[local2]);
+            tot += 1.0f;
+          }
+        }
+
+        if (tot == 0.0f) {
+          continue;
+        }
+
+        mul_v3_fl(avg, 1.0 / tot);
+
+        if (dot_v3v3(avg, avg) == 0.0f || dot_v3v3(disp, disp) == 0.0f) {
+          continue;
+        }
+
+        float ratio = len_v3(disp) / len_v3(avg);
+
+        if (ratio < 1.0f) {
+          continue;
+        }
+
+        modified = true;
+
+        ratio = pow(ratio, 0.1f);
+        float tmp[3];
+
+        copy_v3_v3(tmp, disp);
+        mul_v3_fl(tmp, 1.0f / ratio);
+        mul_v3_m3v3(tmp, mats[locali], tmp);
+        add_v3_v3(tmp, limits[locali]);
+
+        float *co = (float *)SCULPT_vertex_co_get(ss, vertex);
+        float test = dot_v3v3(co, co);
+
+        if (isnan(test) || isinf(test)) {
+          copy_v3_v3(co, tmp);
+        }
+        else {
+          interp_v3_v3v3(co, co, tmp, bstrength);
+        }
+      }
+    }
+  }
+
+  MEM_SAFE_FREE(disps);
+  MEM_SAFE_FREE(mats);
+  MEM_SAFE_FREE(limits);
+
+  if (modified) {
+    BKE_pbvh_node_mark_update(node);
+  }
+}
+
+void SCULPT_do_displacement_heal_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+  SculptSession *ss = ob->sculpt;
+ 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list