[Bf-blender-cvs] [8f1f756b839] master: Subdiv CCG: add utility functions for accessing multires vertex neighbors

Sergey Sharybin noreply at git.blender.org
Fri Oct 4 19:07:56 CEST 2019


Commit: 8f1f756b839942531c69a7608c25ea85de1beb8a
Author: Sergey Sharybin
Date:   Fri Oct 4 18:49:39 2019 +0200
Branches: master
https://developer.blender.org/rB8f1f756b839942531c69a7608c25ea85de1beb8a

Subdiv CCG: add utility functions for accessing multires vertex neighbors

This is to be used by the new sculpting tools.

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

M	source/blender/blenkernel/BKE_subdiv_ccg.h
M	source/blender/blenkernel/intern/subdiv_ccg.c
M	source/blender/editors/sculpt_paint/sculpt.c

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

diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index 9b7c613aa94..6e2733eb1ac 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -131,6 +131,9 @@ typedef struct SubdivCCG {
   /* Resolution of grid. All grids have matching resolution, and resolution
    * is same as ptex created for non-quad polygons. */
   int grid_size;
+  /* Size of a single element of a grid (including coordinate and all the other layers).
+   * Measured in bytes. */
+  int grid_element_size;
   /* Grids represent limit surface, with displacement applied. Grids are
    * corresponding to face-corners of coarse mesh, each grid has
    * grid_size^2 elements.
@@ -251,4 +254,43 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg,
                                       int *r_num_faces,
                                       int *r_num_loops);
 
+typedef struct SubdivCCGCoord {
+  /* Index of the grid within SubdivCCG::grids array. */
+  int grid_index;
+
+  /* Coordinate within the grid. */
+  int x, y;
+} SubdivCCGCoord;
+
+typedef struct SubdivCCGNeighbors {
+  SubdivCCGCoord *coords;
+  int size;
+
+  SubdivCCGCoord coords_fixed[256];
+} SubdivCCGNeighbors;
+
+void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord *coord);
+bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord);
+
+/* CCG element neighbors.
+ *
+ * Neighbors are considered:
+ *
+ * - For an inner elements of a grid other elements which are sharing same row or column (4
+ *   neighbor elements in total).
+ *
+ * - For the corner element a single neighboring element on every adjacent edge, single from
+ *   every gird.
+ *
+ * - For the boundary element two neighbor elements on the boundary (from same grid) and one
+ *   element inside of every neighboring grid. */
+
+/* Get actual neighbors of the given coordinate.
+ *
+ * SubdivCCGNeighbors.neighbors must be freed if it is not equal to
+ * SubdivCCGNeighbors.fixed_neighbors. */
+void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg,
+                                        const SubdivCCGCoord *coord,
+                                        SubdivCCGNeighbors *r_neighbors);
+
 #endif /* __BKE_SUBDIV_CCG_H__ */
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index bbd73db42bf..66db58ec683 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -129,6 +129,7 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg, Subdiv *subdiv)
   const int num_grids = topology_refiner_count_face_corners(topology_refiner);
   const int grid_size = BKE_subdiv_grid_size_from_level(subdiv_ccg->level);
   const int grid_area = grid_size * grid_size;
+  subdiv_ccg->grid_element_size = element_size;
   subdiv_ccg->num_grids = num_grids;
   subdiv_ccg->grids = MEM_calloc_arrayN(num_grids, sizeof(CCGElem *), "subdiv ccg grids");
   subdiv_ccg->grids_storage = MEM_calloc_arrayN(
@@ -1229,3 +1230,508 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg,
   *r_num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
   *r_num_loops = *r_num_faces * 4;
 }
+
+/* =============================================================================
+ * Neighbors.
+ */
+
+void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord *coord)
+{
+  printf("%s: grid index: %d, coord: (%d, %d)\n", message, coord->grid_index, coord->x, coord->y);
+}
+
+bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+  if (coord->grid_index < 0 || coord->grid_index >= subdiv_ccg->num_grids) {
+    return false;
+  }
+  const int grid_size = subdiv_ccg->grid_size;
+  if (coord->x < 0 || coord->x >= grid_size) {
+    return false;
+  }
+  if (coord->y < 0 || coord->y >= grid_size) {
+    return false;
+  }
+  return true;
+}
+
+BLI_INLINE void subdiv_ccg_neighbors_init(SubdivCCGNeighbors *neighbors, int size)
+{
+  neighbors->size = size;
+  if (size < ARRAY_SIZE(neighbors->coords_fixed)) {
+    neighbors->coords = neighbors->coords_fixed;
+  }
+  else {
+    neighbors->coords = MEM_mallocN(sizeof(*neighbors->coords) * size,
+                                    "SubdivCCGNeighbors.coords");
+  }
+}
+
+/* Check whether given coordinate belongs to a grid corner. */
+BLI_INLINE bool is_corner_grid_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+  const int grid_size_1 = subdiv_ccg->grid_size - 1;
+  return (coord->x == 0 && coord->y == 0) || (coord->x == 0 && coord->y == grid_size_1) ||
+         (coord->x == grid_size_1 && coord->y == grid_size_1) ||
+         (coord->x == grid_size_1 && coord->y == 0);
+}
+
+/* Check whether given coordinate belongs to a grid boundary. */
+BLI_INLINE bool is_boundary_grid_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+  const int grid_size_1 = subdiv_ccg->grid_size - 1;
+  return coord->x == 0 || coord->y == 0 || coord->x == grid_size_1 || coord->y == grid_size_1;
+}
+
+/* Check whether coordinate is at the boundary between two grids of the same face. */
+BLI_INLINE bool is_inner_edge_grid_coordinate(const SubdivCCG *subdiv_ccg,
+                                              const SubdivCCGCoord *coord)
+{
+  const int grid_size_1 = subdiv_ccg->grid_size - 1;
+  if (coord->x == 0) {
+    return coord->y > 0 && coord->y < grid_size_1;
+  }
+  if (coord->y == 0) {
+    return coord->x > 0 && coord->x < grid_size_1;
+  }
+  return false;
+}
+
+BLI_INLINE SubdivCCGCoord coord_at_prev_row(const SubdivCCG *UNUSED(subdiv_ccg),
+                                            const SubdivCCGCoord *coord)
+{
+  BLI_assert(coord->y > 0);
+  SubdivCCGCoord result = *coord;
+  result.y -= 1;
+  return result;
+}
+BLI_INLINE SubdivCCGCoord coord_at_next_row(const SubdivCCG *subdiv_ccg,
+                                            const SubdivCCGCoord *coord)
+{
+  UNUSED_VARS_NDEBUG(subdiv_ccg);
+  BLI_assert(coord->y < subdiv_ccg->grid_size - 1);
+  SubdivCCGCoord result = *coord;
+  result.y += 1;
+  return result;
+}
+
+BLI_INLINE SubdivCCGCoord coord_at_prev_col(const SubdivCCG *UNUSED(subdiv_ccg),
+                                            const SubdivCCGCoord *coord)
+{
+  BLI_assert(coord->x > 0);
+  SubdivCCGCoord result = *coord;
+  result.x -= 1;
+  return result;
+}
+BLI_INLINE SubdivCCGCoord coord_at_next_col(const SubdivCCG *subdiv_ccg,
+                                            const SubdivCCGCoord *coord)
+{
+  UNUSED_VARS_NDEBUG(subdiv_ccg);
+  BLI_assert(coord->x < subdiv_ccg->grid_size - 1);
+  SubdivCCGCoord result = *coord;
+  result.x += 1;
+  return result;
+}
+
+BLI_INLINE SubdivCCGCoord coord_from_ccg_element(const SubdivCCG *subdiv_ccg, CCGElem *element)
+{
+  const size_t element_data_offset = (unsigned char *)element - subdiv_ccg->grids_storage;
+  const size_t element_global_index = element_data_offset / subdiv_ccg->grid_element_size;
+  const int grid_area = subdiv_ccg->grid_size * subdiv_ccg->grid_size;
+  const int grid_index = element_global_index / grid_area;
+  const size_t grid_start_element_index = grid_index * grid_area;
+  const int element_grid_index = element_global_index - grid_start_element_index;
+
+  const int y = element_grid_index / subdiv_ccg->grid_size;
+  const int x = element_grid_index - y * subdiv_ccg->grid_size;
+
+  SubdivCCGCoord result;
+  result.grid_index = grid_index;
+  result.x = x;
+  result.y = y;
+
+  return result;
+}
+
+/* For the input coordinate which is at the boundary of the grid do one step inside.  */
+static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_ccg,
+                                                      const SubdivCCGCoord *coord)
+
+{
+  SubdivCCGCoord result = *coord;
+  const int grid_size_1 = subdiv_ccg->grid_size - 1;
+  if (result.x == grid_size_1) {
+    --result.x;
+  }
+  else if (result.y == grid_size_1) {
+    --result.y;
+  }
+  else if (result.x == 0) {
+    ++result.x;
+  }
+  else if (result.y == 0) {
+    ++result.y;
+  }
+  else {
+    BLI_assert(!"non-boundary element given");
+  }
+  return result;
+}
+
+BLI_INLINE
+int next_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+  SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
+  const int face_grid_index = coord->grid_index;
+  int next_face_grid_index = face_grid_index + 1 - face->start_grid_index;
+  if (next_face_grid_index == face->num_grids) {
+    next_face_grid_index = 0;
+  }
+  return face->start_grid_index + next_face_grid_index;
+}
+BLI_INLINE int prev_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+  SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
+  const int face_grid_index = coord->grid_index;
+  int prev_face_grid_index = face_grid_index - 1 - face->start_grid_index;
+  if (prev_face_grid_index < 0) {
+    prev_face_grid_index = face->num_grids - 1;
+  }
+  return face->start_grid_index + prev_face_grid_index;
+}
+
+/* Simple case of getting neighbors of a corner coordinate: the corner is a face center, so
+ * can only iterate over grid of a single face, without looking into adjacency. */
+static void neighbor_coords_corner_center_get(const SubdivCCG *subdiv_ccg,
+                                              const SubdivCCGCoord *coord,
+                                              SubdivCCGNeighbors *r_neighbors)
+{
+  SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
+
+  subdiv_ccg_neighbors_init(r_neighbors, face->num_grids);
+
+  for (int face_grid_index = 0; face_grid_index < face->num_grids; ++face_grid_index) {
+    SubdivCCGCoord neighbor_coord;
+    neighbor_coord.grid_index = face->start_grid_index + face_grid_index;
+    neighbor_coord.x = 1;
+    neighbor_coord.y = 0;
+    r_neighbors->coords[face_grid_index] = neighbor_coord;
+  }
+}
+
+/* Get index within adjacent_vertices array for the given CCG coordinate. */
+static int adjacent_vertex_index_from_coord(const SubdivCCG *subdiv_ccg,
+                                            const Subdiv

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list