[Bf-blender-cvs] [23fd95458c2] master: Multires: Fix wrong or missing mask propagation

Sergey Sharybin noreply at git.blender.org
Wed May 13 12:13:06 CEST 2020


Commit: 23fd95458c264dc53f5ce94cd2c65404a69d0f6f
Author: Sergey Sharybin
Date:   Wed May 13 10:42:13 2020 +0200
Branches: master
https://developer.blender.org/rB23fd95458c264dc53f5ce94cd2c65404a69d0f6f

Multires: Fix wrong or missing mask propagation

Propagation when changing sculpt level was missing. In fact, the mask
was simply completely removed when changing sculpt level.

Subdivision worked for simple and linear subdivision, but Catmull-Clark
was giving empty results.

Fixes propagation part of T76386.

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

M	source/blender/blenkernel/intern/multires_reshape.c
M	source/blender/blenkernel/intern/multires_reshape.h
M	source/blender/blenkernel/intern/multires_reshape_smooth.c
M	source/blender/blenkernel/intern/multires_reshape_util.c

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

diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index c5184881b7c..e59b19638f8 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -216,19 +216,20 @@ void multiresModifier_subdivide_to_level(struct Object *object,
 
   multires_reshape_store_original_grids(&reshape_context);
   multires_reshape_ensure_grids(coarse_mesh, reshape_context.top.level);
-  multires_reshape_assign_final_coords_from_orig_mdisps(&reshape_context);
+  multires_reshape_assign_final_elements_from_orig_mdisps(&reshape_context);
+
+  /* Free original grids which makes it so smoothing with details thinks all the details were
+   * added against base mesh's limit surface. This is similar behavior to as if we've done all
+   * displacement in sculpt mode at the old top level and then propagated to the new top level.*/
+  multires_reshape_free_original_grids(&reshape_context);
 
   if (ELEM(mode, MULTIRES_SUBDIVIDE_LINEAR, MULTIRES_SUBDIVIDE_SIMPLE)) {
     multires_reshape_smooth_object_grids(&reshape_context, mode);
   }
   else {
-    /* Free original grids which makes it so smoothing with details thinks all the details were
-     * added against base mesh's limit surface. This is similar behavior to as if we've done all
-     * displacement in sculpt mode at the old top level and then propagated to the new top level.*/
-    multires_reshape_free_original_grids(&reshape_context);
-
     multires_reshape_smooth_object_grids_with_details(&reshape_context);
   }
+
   multires_reshape_object_grids_to_tangent_displacement(&reshape_context);
   multires_reshape_context_free(&reshape_context);
 
diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h
index 8eb90809c31..12816a455ee 100644
--- a/source/blender/blenkernel/intern/multires_reshape.h
+++ b/source/blender/blenkernel/intern/multires_reshape.h
@@ -275,7 +275,7 @@ void multires_reshape_assign_final_coords_from_mdisps(
     const MultiresReshapeContext *reshape_context);
 
 /* Reads from original CD_MIDTSPS, writes to the current mesh CD_MDISPS. */
-void multires_reshape_assign_final_coords_from_orig_mdisps(
+void multires_reshape_assign_final_elements_from_orig_mdisps(
     const MultiresReshapeContext *reshape_context);
 
 /* --------------------------------------------------------------------
diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c
index 0fe0ac4b66a..7312ac2bf5e 100644
--- a/source/blender/blenkernel/intern/multires_reshape_smooth.c
+++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c
@@ -95,6 +95,30 @@ typedef struct Edge {
   float sharpness;
 } Edge;
 
+/* Storage of data which is linearly interpolated from the reshape level to the top level. */
+
+typedef struct LinearGridElement {
+  float mask;
+} LinearGridElement;
+
+typedef struct LinearGrid {
+  LinearGridElement *elements;
+} LinearGrid;
+
+typedef struct LinearGrids {
+  int num_grids;
+  int level;
+
+  /* Cached size for the grid, for faster lookup. */
+  int grid_size;
+
+  /* Indexed by grid index. */
+  LinearGrid *grids;
+
+  /* Elements for all grids are allocated in a single array, for the allocation performance. */
+  LinearGridElement *elements_storage;
+} LinearGrids;
+
 /* Context which holds all information eeded during propagation and smoothing. */
 
 typedef struct MultiresReshapeSmoothContext {
@@ -122,6 +146,10 @@ typedef struct MultiresReshapeSmoothContext {
     Face *faces;
   } geometry;
 
+  /* Grids of data which is linearly interpolated between grid elements at the reshape level.
+   * The data is actually stored as a delta, which is then to be added to the higher levels. */
+  LinearGrids linear_delta_grids;
+
   /* Index i of this map indicates that base edge i is adjacent to at least one face. */
   BLI_bitmap *non_loose_base_edge_map;
 
@@ -150,51 +178,79 @@ typedef struct MultiresReshapeSmoothContext {
 /** \} */
 
 /* -------------------------------------------------------------------- */
-/** \name Masks
+/** \name Linear grids manipulation
  * \{ */
 
-/* Interpolate mask grid at a reshape level.
- * Will return 0 if there is no masks custom data layer. */
-static float interpolate_masks_grid(const MultiresReshapeSmoothContext *reshape_smooth_context,
-                                    const GridCoord *grid_coord)
+static void linear_grids_init(LinearGrids *linear_grids)
 {
-  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
-  if (reshape_context->orig.grid_paint_masks == NULL) {
-    return 0.0f;
-  }
+  linear_grids->num_grids = 0;
+  linear_grids->level = 0;
 
-  const GridPaintMask *grid = &reshape_context->orig.grid_paint_masks[grid_coord->grid_index];
-  const int grid_size = BKE_subdiv_grid_size_from_level(grid->level);
-  const int grid_size_1 = grid_size - 1;
-  const float grid_size_1_inv = 1.0f / (float)(grid_size_1);
+  linear_grids->grids = NULL;
+  linear_grids->elements_storage = NULL;
+}
 
-  const float x_f = grid_coord->u * grid_size_1;
-  const float y_f = grid_coord->v * grid_size_1;
+static void linear_grids_allocate(LinearGrids *linear_grids, int num_grids, int level)
+{
+  const size_t grid_size = BKE_subdiv_grid_size_from_level(level);
+  const size_t grid_area = grid_size * grid_size;
+  const size_t num_grid_elements = num_grids * grid_area;
 
-  const int x_i = x_f;
-  const int y_i = y_f;
-  const int x_n_i = (x_i == grid_size - 1) ? (x_i) : (x_i + 1);
-  const int y_n_i = (y_i == grid_size - 1) ? (y_i) : (y_i + 1);
+  linear_grids->num_grids = num_grids;
+  linear_grids->level = level;
+  linear_grids->grid_size = grid_size;
 
-  const int corners[4][2] = {{x_i, y_i}, {x_n_i, y_i}, {x_n_i, y_n_i}, {x_i, y_n_i}};
-  float mask_elements[4];
-  for (int i = 0; i < 4; ++i) {
-    GridCoord corner_grid_coord;
-    corner_grid_coord.grid_index = grid_coord->grid_index;
-    corner_grid_coord.u = corners[i][0] * grid_size_1_inv;
-    corner_grid_coord.v = corners[i][1] * grid_size_1_inv;
+  linear_grids->grids = MEM_malloc_arrayN(num_grids, sizeof(LinearGrid), "linear grids");
+  linear_grids->elements_storage = MEM_calloc_arrayN(
+      num_grid_elements, sizeof(LinearGridElement), "linear elements storage");
 
-    ReshapeConstGridElement element = multires_reshape_orig_grid_element_for_grid_coord(
-        reshape_context, &corner_grid_coord);
-    mask_elements[i] = element.mask;
+  for (int i = 0; i < num_grids; ++i) {
+    const size_t element_offset = grid_area * i;
+    linear_grids->grids[i].elements = &linear_grids->elements_storage[element_offset];
   }
+}
 
-  const float u = x_f - x_i;
-  const float v = y_f - y_i;
-  const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), u * v, (1.0f - u) * v};
+static LinearGridElement *linear_grid_element_get(const LinearGrids *linear_grids,
+                                                  const GridCoord *grid_coord)
+{
+  BLI_assert(grid_coord->grid_index >= 0);
+  BLI_assert(grid_coord->grid_index < linear_grids->num_grids);
+
+  const int grid_size = linear_grids->grid_size;
 
-  return mask_elements[0] * weights[0] + mask_elements[1] * weights[1] +
-         mask_elements[2] * weights[2] + mask_elements[3] * weights[3];
+  const int grid_x = lround(grid_coord->u * (grid_size - 1));
+  const int grid_y = lround(grid_coord->v * (grid_size - 1));
+  const int grid_element_index = grid_y * grid_size + grid_x;
+
+  LinearGrid *grid = &linear_grids->grids[grid_coord->grid_index];
+  return &grid->elements[grid_element_index];
+}
+
+static void linear_grids_free(LinearGrids *linear_grids)
+{
+  MEM_SAFE_FREE(linear_grids->grids);
+  MEM_SAFE_FREE(linear_grids->elements_storage);
+}
+
+static void linear_grid_element_init(LinearGridElement *linear_grid_element)
+{
+  linear_grid_element->mask = 0.0f;
+}
+
+/* result = a - b. */
+static void linear_grid_element_sub(LinearGridElement *result,
+                                    const LinearGridElement *a,
+                                    const LinearGridElement *b)
+{
+  result->mask = a->mask - b->mask;
+}
+
+static void linear_grid_element_interpolate(LinearGridElement *result,
+                                            const LinearGridElement elements[4],
+                                            const float weights[4])
+{
+  result->mask = elements[0].mask * weights[0] + elements[1].mask * weights[1] +
+                 elements[2].mask * weights[2] + elements[3].mask * weights[3];
 }
 
 /** \} */
@@ -465,6 +521,8 @@ static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context,
   reshape_smooth_context->geometry.num_faces = 0;
   reshape_smooth_context->geometry.faces = NULL;
 
+  linear_grids_init(&reshape_smooth_context->linear_delta_grids);
+
   reshape_smooth_context->non_loose_base_edge_map = NULL;
   reshape_smooth_context->reshape_subdiv = NULL;
   reshape_smooth_context->base_surface_grids = NULL;
@@ -483,6 +541,8 @@ static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_c
   MEM_SAFE_FREE(reshape_smooth_context->geometry.corners);
   MEM_SAFE_FREE(reshape_smooth_context->geometry.faces);
   MEM_SAFE_FREE(reshape_smooth_context->geometry.edges);
+
+  linear_grids_free(&reshape_smooth_context->linear_delta_grids);
 }
 
 static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_context)
@@ -1100,6 +1160,133 @@ static void reshape_subdiv_evaluate_limit_at_grid(
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name Linearly interpolated data
+ * \{ */
+
+static LinearGridElement linear_grid_element_orig_get(
+    const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord)
+{
+  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
+  const ReshapeConstGridElement orig_grid_element =
+      multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
+
+  LinearGridElement linear_grid_element;
+  linear_grid_element_init(&linear_grid_element);
+
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list