[Bf-blender-cvs] [037cf920b42] master: Sculpt: mesh abstraction API

Pablo Dobarro noreply at git.blender.org
Wed Aug 14 22:59:40 CEST 2019


Commit: 037cf920b42d9b3404687235c524516e50a31561
Author: Pablo Dobarro
Date:   Wed Aug 14 22:54:23 2019 +0200
Branches: master
https://developer.blender.org/rB037cf920b42d9b3404687235c524516e50a31561

Sculpt: mesh abstraction API

These functions make possible porting the tools from the sculpt branch, making them compatible with PBVH_FACES and PBVH_BMESH without duplicating the code. They can also help to simplify some existing code.

These functions should not be used when working with PBVH_GRIDS data in SculptSession. PBVH_GRIDS needs to be removed from the sculpt code and converted to PBVH_FACES to be compatible with this API.

Reviewed By: brecht

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

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

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/editors/sculpt_paint/sculpt.c

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

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index cbe250d0ac8..37667599488 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -259,6 +259,8 @@ typedef struct SculptSession {
 
   struct StrokeCache *cache;
 
+  int active_vertex_index;
+
   union {
     struct {
       struct SculptVertexPaintGeomMap gmap;
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 3806868e060..62544efad2c 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -301,6 +301,7 @@ typedef struct PBVHVertexIter {
   int gx;
   int gy;
   int i;
+  int index;
 
   /* grid */
   struct CCGElem **grids;
@@ -369,6 +370,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
             continue; \
           vi.co = vi.mvert->co; \
           vi.no = vi.mvert->no; \
+          vi.index = vi.vert_indices[vi.i]; \
           if (vi.vmask) \
             vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \
         } \
@@ -385,6 +387,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
             continue; \
           vi.co = vi.bm_vert->co; \
           vi.fno = vi.bm_vert->no; \
+          vi.index = BM_elem_index_get(vi.bm_vert); \
           vi.mask = BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \
         }
 
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index efaac6e97cf..cdd82b8ced3 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -92,6 +92,235 @@
 #include <stdlib.h>
 #include <string.h>
 
+/* Sculpt PBVH abstraction API */
+
+/* Do not use these functions while working with PBVH_GRIDS data in SculptSession */
+
+static int sculpt_active_vertex_get(SculptSession *ss)
+{
+  switch (BKE_pbvh_type(ss->pbvh)) {
+    case PBVH_FACES:
+      return ss->active_vertex_index;
+    case PBVH_BMESH:
+      return ss->active_vertex_index;
+    default:
+      return 0;
+  }
+}
+
+static int sculpt_vertex_count_get(SculptSession *ss)
+{
+  switch (BKE_pbvh_type(ss->pbvh)) {
+    case PBVH_FACES:
+      return ss->totvert;
+    case PBVH_BMESH:
+      return BM_mesh_elem_count(BKE_pbvh_get_bmesh(ss->pbvh), BM_VERT);
+    default:
+      return 0;
+  }
+}
+
+static void sculpt_vertex_normal_get(SculptSession *ss, int index, float no[3])
+{
+  switch (BKE_pbvh_type(ss->pbvh)) {
+    case PBVH_FACES:
+      normal_short_to_float_v3(no, ss->mvert[index].no);
+      return;
+    case PBVH_BMESH:
+      copy_v3_v3(no, BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->no);
+    default:
+      return;
+  }
+}
+
+static float *sculpt_vertex_co_get(SculptSession *ss, int index)
+{
+  switch (BKE_pbvh_type(ss->pbvh)) {
+    case PBVH_FACES:
+      return ss->mvert[index].co;
+    case PBVH_BMESH:
+      return BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co;
+    default:
+      return NULL;
+  }
+}
+
+static void sculpt_vertex_co_set(SculptSession *ss, int index, float co[3])
+{
+  switch (BKE_pbvh_type(ss->pbvh)) {
+    case PBVH_FACES:
+      copy_v3_v3(ss->mvert[index].co, co);
+      return;
+    case PBVH_BMESH:
+      copy_v3_v3(BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co, co);
+      return;
+    default:
+      return;
+  }
+}
+
+static void sculpt_vertex_mask_set(SculptSession *ss, int index, float mask)
+{
+  BMVert *v;
+  float *mask_p;
+  switch (BKE_pbvh_type(ss->pbvh)) {
+    case PBVH_FACES:
+      ss->vmask[index] = mask;
+      return;
+    case PBVH_BMESH:
+      v = BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index);
+      mask_p = BM_ELEM_CD_GET_VOID_P(v, CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK));
+      *(mask_p) = mask;
+      return;
+    default:
+      return;
+  }
+}
+
+static float sculpt_vertex_mask_get(SculptSession *ss, int index)
+{
+  BMVert *v;
+  float *mask;
+  switch (BKE_pbvh_type(ss->pbvh)) {
+    case PBVH_FACES:
+      return ss->vmask[index];
+    case PBVH_BMESH:
+      v = BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index);
+      mask = BM_ELEM_CD_GET_VOID_P(v, CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK));
+      return *mask;
+    default:
+      return 0;
+  }
+}
+
+static void sculpt_vertex_tag_update(SculptSession *ss, int index)
+{
+  switch (BKE_pbvh_type(ss->pbvh)) {
+    case PBVH_FACES:
+      ss->mvert[index].flag |= ME_VERT_PBVH_UPDATE;
+      return;
+    case PBVH_BMESH:
+      return;
+    default:
+      return;
+  }
+}
+
+#define SCULPT_VERTEX_NEIGHBOUR_FIXED_CAPACITY 256
+
+typedef struct SculptVertexNeighbourIter {
+  int *neighbours;
+  int size;
+  int capacity;
+
+  int neighbours_fixed[SCULPT_VERTEX_NEIGHBOUR_FIXED_CAPACITY];
+
+  int index;
+  int i;
+} SculptVertexNeighbourIter;
+
+static void sculpt_vertex_neighbour_add(SculptVertexNeighbourIter *iter, int neighbour_index)
+{
+  for (int i = 0; i < iter->size; i++) {
+    if (iter->neighbours[i] == neighbour_index) {
+      return;
+    }
+  }
+
+  if (iter->size >= iter->capacity) {
+    iter->capacity += SCULPT_VERTEX_NEIGHBOUR_FIXED_CAPACITY;
+
+    if (iter->neighbours == iter->neighbours_fixed) {
+      iter->neighbours = MEM_mallocN(iter->capacity * sizeof(int), "neighbour array");
+      memcpy(iter->neighbours, iter->neighbours_fixed, sizeof(int) * iter->size);
+    }
+    else {
+      iter->neighbours = MEM_reallocN_id(
+          iter->neighbours, iter->capacity * sizeof(int), "neighbour array");
+    }
+  }
+
+  iter->neighbours[iter->size] = neighbour_index;
+  iter->size++;
+}
+
+static void sculpt_vertex_neighbours_get_bmesh(SculptSession *ss,
+                                               int index,
+                                               SculptVertexNeighbourIter *iter)
+{
+  BMVert *v = BM_vert_at_index(ss->bm, index);
+  BMIter liter;
+  BMLoop *l;
+  iter->size = 0;
+  iter->capacity = SCULPT_VERTEX_NEIGHBOUR_FIXED_CAPACITY;
+  iter->neighbours = iter->neighbours_fixed;
+
+  int i = 0;
+  BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+    const BMVert *adj_v[2] = {l->prev->v, l->next->v};
+    for (i = 0; i < ARRAY_SIZE(adj_v); i++) {
+      const BMVert *v_other = adj_v[i];
+      if (BM_elem_index_get(v_other) != (int)index) {
+        sculpt_vertex_neighbour_add(iter, BM_elem_index_get(v_other));
+      }
+    }
+  }
+}
+
+static void sculpt_vertex_neighbours_get_faces(SculptSession *ss,
+                                               int index,
+                                               SculptVertexNeighbourIter *iter)
+{
+  int i;
+  MeshElemMap *vert_map = &ss->pmap[(int)index];
+  iter->size = 0;
+  iter->capacity = SCULPT_VERTEX_NEIGHBOUR_FIXED_CAPACITY;
+  iter->neighbours = iter->neighbours_fixed;
+
+  for (i = 0; i < ss->pmap[(int)index].count; i++) {
+    const MPoly *p = &ss->mpoly[vert_map->indices[i]];
+    unsigned f_adj_v[2];
+    if (poly_get_adj_loops_from_vert(p, ss->mloop, (int)index, f_adj_v) != -1) {
+      int j;
+      for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
+        if (vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2) {
+          if (f_adj_v[j] != (int)index) {
+            sculpt_vertex_neighbour_add(iter, f_adj_v[j]);
+          }
+        }
+      }
+    }
+  }
+}
+
+static void sculpt_vertex_neighbours_get(SculptSession *ss,
+                                         int index,
+                                         SculptVertexNeighbourIter *iter)
+{
+  switch (BKE_pbvh_type(ss->pbvh)) {
+    case PBVH_FACES:
+      sculpt_vertex_neighbours_get_faces(ss, index, iter);
+      return;
+    case PBVH_BMESH:
+      sculpt_vertex_neighbours_get_bmesh(ss, index, iter);
+      return;
+    default:
+      break;
+  }
+}
+
+#define sculpt_vertex_neighbours_iter_begin(ss, v_index, neighbour_iterator) \
+  sculpt_vertex_neighbours_get(ss, v_index, &neighbour_iterator); \
+  for (neighbour_iterator.i = 0; neighbour_iterator.i < neighbour_iterator.size; \
+       neighbour_iterator.i++) { \
+    neighbour_iterator.index = ni.neighbours[ni.i];
+
+#define sculpt_vertex_neighbours_iter_end(neighbour_iterator) \
+  } \
+  if (neighbour_iterator.neighbours != neighbour_iterator.neighbours_fixed) { \
+    MEM_freeN(neighbour_iterator.neighbours); \
+  }
+
 /** \name Tool Capabilities
  *
  * Avoid duplicate checks, internal logic only,



More information about the Bf-blender-cvs mailing list