Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h3
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c229
3 files changed, 234 insertions, 0 deletions
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,