diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_subdiv_ccg.h | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subdiv_ccg.c | 108 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_cursor.c | 4 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 114 |
4 files changed, 158 insertions, 75 deletions
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index 7c0963680c5..409a0d1232b 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -265,6 +265,7 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg, typedef struct SubdivCCGNeighbors { SubdivCCGCoord *coords; int size; + int num_duplicates; SubdivCCGCoord coords_fixed[256]; } SubdivCCGNeighbors; @@ -288,9 +289,13 @@ bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivC /* Get actual neighbors of the given coordinate. * * SubdivCCGNeighbors.neighbors must be freed if it is not equal to - * SubdivCCGNeighbors.fixed_neighbors. */ + * SubdivCCGNeighbors.fixed_neighbors. + * + * If include_duplicates is true, vertices in other grids that match + * the current vertex are added at the end of the coords array. */ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, + const bool include_duplicates, 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 bdab444b77a..4e3ba532fb2 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -1268,9 +1268,13 @@ bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivC return true; } -BLI_INLINE void subdiv_ccg_neighbors_init(SubdivCCGNeighbors *neighbors, int size) +BLI_INLINE void subdiv_ccg_neighbors_init(SubdivCCGNeighbors *neighbors, + const int num_unique, + const int num_duplicates) { + const int size = num_unique + num_duplicates; neighbors->size = size; + neighbors->num_duplicates = num_duplicates; if (size < ARRAY_SIZE(neighbors->coords_fixed)) { neighbors->coords = neighbors->coords_fixed; } @@ -1397,18 +1401,27 @@ BLI_INLINE int prev_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const Sub * 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, + const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index]; + const int num_adjacent_grids = face->num_grids; - subdiv_ccg_neighbors_init(r_neighbors, face->num_grids); + subdiv_ccg_neighbors_init( + r_neighbors, num_adjacent_grids, (include_duplicates) ? num_adjacent_grids - 1 : 0); - for (int face_grid_index = 0; face_grid_index < face->num_grids; ++face_grid_index) { + int duplicate_face_grid_index = num_adjacent_grids; + for (int face_grid_index = 0; face_grid_index < num_adjacent_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; + + if (include_duplicates && neighbor_coord.grid_index != coord->grid_index) { + neighbor_coord.x = 0; + r_neighbors->coords[duplicate_face_grid_index++] = neighbor_coord; + } } } @@ -1439,6 +1452,7 @@ static int adjacent_vertex_index_from_coord(const SubdivCCG *subdiv_ccg, /* The corner is adjacent to a coarse vertex. */ static void neighbor_coords_corner_vertex_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, + const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { Subdiv *subdiv = subdiv_ccg->subdiv; @@ -1450,7 +1464,11 @@ static void neighbor_coords_corner_vertex_get(const SubdivCCG *subdiv_ccg, const int num_vertex_edges = topology_refiner->getNumVertexEdges(topology_refiner, adjacent_vertex_index); - subdiv_ccg_neighbors_init(r_neighbors, num_vertex_edges); + SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[adjacent_vertex_index]; + const int num_adjacent_faces = adjacent_vertex->num_adjacent_faces; + + subdiv_ccg_neighbors_init( + r_neighbors, num_vertex_edges, (include_duplicates) ? num_adjacent_faces - 1 : 0); StaticOrHeapIntStorage vertex_edges_storage; static_or_heap_storage_init(&vertex_edges_storage); @@ -1467,21 +1485,33 @@ static void neighbor_coords_corner_vertex_get(const SubdivCCG *subdiv_ccg, /* Depending edge orientation we use first (zero-based) or previous-to-last point. */ int edge_vertices_indices[2]; topology_refiner->getEdgeVertices(topology_refiner, edge_index, edge_vertices_indices); - int edge_point_index; + int edge_point_index, duplicate_edge_point_index; if (edge_vertices_indices[0] == adjacent_vertex_index) { - edge_point_index = 1; + duplicate_edge_point_index = 0; + edge_point_index = duplicate_edge_point_index + 1; } else { /* Edge "consists" of 2 grids, which makes it 2 * grid_size elements per edge. * The index of last edge element is 2 * grid_size - 1 (due to zero-based indices), * and we are interested in previous to last element. */ - edge_point_index = subdiv_ccg->grid_size * 2 - 2; + duplicate_edge_point_index = subdiv_ccg->grid_size * 2 - 1; + edge_point_index = duplicate_edge_point_index - 1; } SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index]; r_neighbors->coords[i] = adjacent_edge->boundary_coords[edge_face_index][edge_point_index]; } + if (include_duplicates) { + /* Add duplicates of the current grid vertex in adjacent faces if requested. */ + for (int i = 0, duplicate_i = num_vertex_edges; i < num_adjacent_faces; i++) { + SubdivCCGCoord neighbor_coord = adjacent_vertex->corner_coords[i]; + if (neighbor_coord.grid_index != coord->grid_index) { + r_neighbors->coords[duplicate_i++] = neighbor_coord; + } + } + } + static_or_heap_storage_free(&vertex_edges_storage); } @@ -1577,6 +1607,7 @@ static int prev_adjacent_edge_point_index(const SubdivCCG *subdiv_ccg, const int * coarse faces, but is not at the coarse vertex. */ static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, + const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { @@ -1586,46 +1617,59 @@ static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg, const SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[adjacent_edge_index]; /* 2 neighbor points along the edge, plus one inner point per every adjacent grid. */ - const int num_neighbor_coord = adjacent_edge->num_adjacent_faces + 2; - subdiv_ccg_neighbors_init(r_neighbors, num_neighbor_coord); + const int num_adjacent_faces = adjacent_edge->num_adjacent_faces; + subdiv_ccg_neighbors_init( + r_neighbors, num_adjacent_faces + 2, (include_duplicates) ? num_adjacent_faces - 1 : 0); const int point_index = adjacent_edge_point_index_from_coord( subdiv_ccg, coord, adjacent_edge_index); const int next_point_index = next_adjacent_edge_point_index(subdiv_ccg, point_index); const int prev_point_index = prev_adjacent_edge_point_index(subdiv_ccg, point_index); - r_neighbors->coords[0] = adjacent_edge->boundary_coords[0][prev_point_index]; - r_neighbors->coords[1] = adjacent_edge->boundary_coords[0][next_point_index]; - - for (int i = 0; i < adjacent_edge->num_adjacent_faces; ++i) { - SubdivCCGCoord grid_coord = adjacent_edge->boundary_coords[i][point_index]; + for (int i = 0, duplicate_i = num_adjacent_faces; i < num_adjacent_faces; ++i) { + SubdivCCGCoord *boundary_coords = adjacent_edge->boundary_coords[i]; + /* One step into the grid from the edge for each adjacent face. */ + SubdivCCGCoord grid_coord = boundary_coords[point_index]; r_neighbors->coords[i + 2] = coord_step_inside_from_boundary(subdiv_ccg, &grid_coord); + + if (grid_coord.grid_index == coord->grid_index) { + /* Prev and next along the edge for the current grid. */ + r_neighbors->coords[0] = boundary_coords[prev_point_index]; + r_neighbors->coords[1] = boundary_coords[next_point_index]; + } + else if (include_duplicates) { + /* Same coordinate on neighboring grids if requested. */ + r_neighbors->coords[duplicate_i + 2] = grid_coord; + duplicate_i++; + } } } /* The corner is at the middle of edge between faces. */ static void neighbor_coords_corner_edge_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, + const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { - neighbor_coords_edge_get(subdiv_ccg, coord, r_neighbors); + neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors); } /* Input coordinate is at one of 4 corners of its grid corners. */ static void neighbor_coords_corner_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, + const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { if (coord->x == 0 && coord->y == 0) { - neighbor_coords_corner_center_get(subdiv_ccg, coord, r_neighbors); + neighbor_coords_corner_center_get(subdiv_ccg, coord, include_duplicates, r_neighbors); } else { const int grid_size_1 = subdiv_ccg->grid_size - 1; if (coord->x == grid_size_1 && coord->y == grid_size_1) { - neighbor_coords_corner_vertex_get(subdiv_ccg, coord, r_neighbors); + neighbor_coords_corner_vertex_get(subdiv_ccg, coord, include_duplicates, r_neighbors); } else { - neighbor_coords_corner_edge_get(subdiv_ccg, coord, r_neighbors); + neighbor_coords_corner_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors); } } } @@ -1635,9 +1679,10 @@ static void neighbor_coords_corner_get(const SubdivCCG *subdiv_ccg, * other faces. */ static void neighbor_coords_boundary_inner_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, + const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { - subdiv_ccg_neighbors_init(r_neighbors, 4); + subdiv_ccg_neighbors_init(r_neighbors, 4, (include_duplicates) ? 1 : 0); if (coord->x == 0) { r_neighbors->coords[0] = coord_at_prev_row(subdiv_ccg, coord); @@ -1647,6 +1692,11 @@ static void neighbor_coords_boundary_inner_get(const SubdivCCG *subdiv_ccg, r_neighbors->coords[3].grid_index = prev_grid_index_from_coord(subdiv_ccg, coord); r_neighbors->coords[3].x = coord->y; r_neighbors->coords[3].y = 1; + + if (include_duplicates) { + r_neighbors->coords[4] = r_neighbors->coords[3]; + r_neighbors->coords[4].y = 0; + } } else if (coord->y == 0) { r_neighbors->coords[0] = coord_at_prev_col(subdiv_ccg, coord); @@ -1656,15 +1706,21 @@ static void neighbor_coords_boundary_inner_get(const SubdivCCG *subdiv_ccg, r_neighbors->coords[3].grid_index = next_grid_index_from_coord(subdiv_ccg, coord); r_neighbors->coords[3].x = 1; r_neighbors->coords[3].y = coord->x; + + if (include_duplicates) { + r_neighbors->coords[4] = r_neighbors->coords[3]; + r_neighbors->coords[4].x = 0; + } } } /* Input coordinate is on an edge between two faces. Need to check adjacency. */ static void neighbor_coords_boundary_outer_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, + const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { - neighbor_coords_edge_get(subdiv_ccg, coord, r_neighbors); + neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors); } /* Input coordinate is at one of 4 boundaries of its grid. @@ -1672,13 +1728,14 @@ static void neighbor_coords_boundary_outer_get(const SubdivCCG *subdiv_ccg, * a part of coarse face edge. */ static void neighbor_coords_boundary_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, + const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { if (is_inner_edge_grid_coordinate(subdiv_ccg, coord)) { - neighbor_coords_boundary_inner_get(subdiv_ccg, coord, r_neighbors); + neighbor_coords_boundary_inner_get(subdiv_ccg, coord, include_duplicates, r_neighbors); } else { - neighbor_coords_boundary_outer_get(subdiv_ccg, coord, r_neighbors); + neighbor_coords_boundary_outer_get(subdiv_ccg, coord, include_duplicates, r_neighbors); } } @@ -1687,7 +1744,7 @@ static void neighbor_coords_inner_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, SubdivCCGNeighbors *r_neighbors) { - subdiv_ccg_neighbors_init(r_neighbors, 4); + subdiv_ccg_neighbors_init(r_neighbors, 4, 0); r_neighbors->coords[0] = coord_at_prev_row(subdiv_ccg, coord); r_neighbors->coords[1] = coord_at_next_row(subdiv_ccg, coord); @@ -1697,6 +1754,7 @@ static void neighbor_coords_inner_get(const SubdivCCG *subdiv_ccg, void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, + const bool include_duplicates, SubdivCCGNeighbors *r_neighbors) { BLI_assert(coord->grid_index >= 0); @@ -1707,10 +1765,10 @@ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg, BLI_assert(coord->y < subdiv_ccg->grid_size); if (is_corner_grid_coord(subdiv_ccg, coord)) { - neighbor_coords_corner_get(subdiv_ccg, coord, r_neighbors); + neighbor_coords_corner_get(subdiv_ccg, coord, include_duplicates, r_neighbors); } else if (is_boundary_grid_coord(subdiv_ccg, coord)) { - neighbor_coords_boundary_get(subdiv_ccg, coord, r_neighbors); + neighbor_coords_boundary_get(subdiv_ccg, coord, include_duplicates, r_neighbors); } else { neighbor_coords_inner_get(subdiv_ccg, coord, r_neighbors); diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index b4956864723..e8c03d398c4 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1393,7 +1393,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) } /* Draw pose brush origin */ - if (brush->sculpt_tool == SCULPT_TOOL_POSE && !is_multires) { + if (brush->sculpt_tool == SCULPT_TOOL_POSE) { immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f); if (update_previews) { BKE_sculpt_update_object_for_edit(depsgraph, vc.obact, true, false); @@ -1446,7 +1446,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) } /* Draw pose brush line preview */ - if (brush->sculpt_tool == SCULPT_TOOL_POSE && !is_multires) { + if (brush->sculpt_tool == SCULPT_TOOL_POSE) { immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f); GPU_line_width(2.0f); immBegin(GPU_PRIM_LINES, 2); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 3538d7a7ca8..145bc77fb0f 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -211,14 +211,19 @@ static void sculpt_active_vertex_normal_get(SculptSession *ss, float normal[3]) #define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256 typedef struct SculptVertexNeighborIter { + /* Storage */ int *neighbors; int size; int capacity; - int neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY]; - int index; + /* Internal iterator. */ + int num_duplicates; int i; + + /* Public */ + int index; + bool is_duplicate; } SculptVertexNeighborIter; static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter, int neighbor_index) @@ -254,6 +259,7 @@ static void sculpt_vertex_neighbors_get_bmesh(SculptSession *ss, BMIter liter; BMLoop *l; iter->size = 0; + iter->num_duplicates = 0; iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY; iter->neighbors = iter->neighbors_fixed; @@ -276,6 +282,7 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, int i; MeshElemMap *vert_map = &ss->pmap[(int)index]; iter->size = 0; + iter->num_duplicates = 0; iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY; iter->neighbors = iter->neighbors_fixed; @@ -294,7 +301,8 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, } static void sculpt_vertex_neighbors_get_grids(SculptSession *ss, - int index, + const int index, + const bool include_duplicates, SculptVertexNeighborIter *iter) { /* TODO: optimize this. We could fill SculptVertexNeighborIter directly, @@ -309,9 +317,10 @@ static void sculpt_vertex_neighbors_get_grids(SculptSession *ss, .y = vertex_index / key->grid_size}; SubdivCCGNeighbors neighbors; - BKE_subdiv_ccg_neighbor_coords_get(ss->subdiv_ccg, &coord, &neighbors); + BKE_subdiv_ccg_neighbor_coords_get(ss->subdiv_ccg, &coord, include_duplicates, &neighbors); iter->size = 0; + iter->num_duplicates = neighbors.num_duplicates; iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY; iter->neighbors = iter->neighbors_fixed; @@ -327,7 +336,8 @@ static void sculpt_vertex_neighbors_get_grids(SculptSession *ss, } static void sculpt_vertex_neighbors_get(SculptSession *ss, - int index, + const int index, + const bool include_duplicates, SculptVertexNeighborIter *iter) { switch (BKE_pbvh_type(ss->pbvh)) { @@ -338,17 +348,28 @@ static void sculpt_vertex_neighbors_get(SculptSession *ss, sculpt_vertex_neighbors_get_bmesh(ss, index, iter); return; case PBVH_GRIDS: - sculpt_vertex_neighbors_get_grids(ss, index, iter); + sculpt_vertex_neighbors_get_grids(ss, index, include_duplicates, iter); return; } } +/* Iterator over neighboring vertices. */ #define sculpt_vertex_neighbors_iter_begin(ss, v_index, neighbor_iterator) \ - sculpt_vertex_neighbors_get(ss, v_index, &neighbor_iterator); \ + sculpt_vertex_neighbors_get(ss, v_index, false, &neighbor_iterator); \ for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \ neighbor_iterator.i++) { \ neighbor_iterator.index = ni.neighbors[ni.i]; +/* Iterate over neighboring and duplicate vertices (for PBVH_GRIDS). Duplicates come + * first since they are nearest for floodfill. */ +#define sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, v_index, neighbor_iterator) \ + sculpt_vertex_neighbors_get(ss, v_index, true, &neighbor_iterator); \ + for (neighbor_iterator.i = neighbor_iterator.size - 1; neighbor_iterator.i >= 0; \ + neighbor_iterator.i--) { \ + neighbor_iterator.index = ni.neighbors[ni.i]; \ + neighbor_iterator.is_duplicate = (ni.i >= \ + neighbor_iterator.size - neighbor_iterator.num_duplicates); + #define sculpt_vertex_neighbors_iter_end(neighbor_iterator) \ } \ if (neighbor_iterator.neighbors != neighbor_iterator.neighbors_fixed) { \ @@ -533,22 +554,20 @@ static void sculpt_floodfill_add_active( static void sculpt_floodfill_execute( SculptSession *ss, SculptFloodFill *flood, - bool (*func)(SculptSession *ss, int from_v, int to_v, void *userdata), + bool (*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata), void *userdata) { - /* TODO: multires support, taking into account duplicate vertices and - * correctly handling them in the pose, automask and mask expand callbacks. */ while (!BLI_gsqueue_is_empty(flood->queue)) { int from_v; BLI_gsqueue_pop(flood->queue, &from_v); SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, from_v, ni) + sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, from_v, ni) { const int to_v = ni.index; if (flood->visited_vertices[to_v] == 0) { flood->visited_vertices[to_v] = 1; - if (func(ss, from_v, to_v, userdata)) { + if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) { BLI_gsqueue_push(flood->queue, &to_v); } } @@ -1199,11 +1218,6 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test, static bool sculpt_automasking_enabled(SculptSession *ss, const Brush *br) { - // REMOVE WITH PBVH_GRIDS - if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { - return false; - } - if (sculpt_stroke_is_dynamic_topology(ss, br)) { return false; } @@ -1252,7 +1266,8 @@ typedef struct AutomaskFloodFillData { char symm; } AutomaskFloodFillData; -static bool automask_floodfill_cb(SculptSession *ss, int UNUSED(from_v), int to_v, void *userdata) +static bool automask_floodfill_cb( + SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata) { AutomaskFloodFillData *data = userdata; @@ -3638,10 +3653,6 @@ static void do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) float pose_initial_co[3]; float transform_rot[4][4], transform_trans[4][4], transform_trans_inv[4][4]; - if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { - return; - } - copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry); copy_v3_v3(pose_origin, ss->cache->pose_origin); @@ -3816,7 +3827,8 @@ typedef struct PoseFloodFillData { int tot_co; } PoseFloodFillData; -static bool pose_floodfill_cb(SculptSession *ss, int UNUSED(from_v), int to_v, void *userdata) +static bool pose_floodfill_cb( + SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata) { PoseFloodFillData *data = userdata; @@ -3830,8 +3842,10 @@ static bool pose_floodfill_cb(SculptSession *ss, int UNUSED(from_v), int to_v, v return true; } else if (check_vertex_pivot_symmetry(co, data->pose_initial_co, data->symm)) { - add_v3_v3(data->pose_origin, co); - data->tot_co++; + if (!is_duplicate) { + add_v3_v3(data->pose_origin, co); + data->tot_co++; + } } return false; @@ -5318,9 +5332,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe if (brush->sculpt_tool == SCULPT_TOOL_POSE && ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0) { - if (BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) { - sculpt_pose_brush_init(sd, ob, ss, brush, ss->cache->location, ss->cache->radius); - } + sculpt_pose_brush_init(sd, ob, ss, brush, ss->cache->location, ss->cache->radius); } /* Apply one type of brush action */ @@ -9130,25 +9142,37 @@ typedef struct MaskExpandFloodFillData { bool use_normals; } MaskExpandFloodFillData; -static bool mask_expand_floodfill_cb(SculptSession *ss, int from_v, int to_v, void *userdata) +static bool mask_expand_floodfill_cb( + SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata) { MaskExpandFloodFillData *data = userdata; - int to_it = ss->filter_cache->mask_update_it[from_v] + 1; - ss->filter_cache->mask_update_it[to_v] = to_it; - if (to_it > ss->filter_cache->mask_update_last_it) { - ss->filter_cache->mask_update_last_it = to_it; - } + if (!is_duplicate) { + int to_it = ss->filter_cache->mask_update_it[from_v] + 1; + ss->filter_cache->mask_update_it[to_v] = to_it; + if (to_it > ss->filter_cache->mask_update_last_it) { + ss->filter_cache->mask_update_last_it = to_it; + } - if (data->use_normals) { - float current_normal[3], prev_normal[3]; - sculpt_vertex_normal_get(ss, to_v, current_normal); - sculpt_vertex_normal_get(ss, from_v, prev_normal); - const float from_edge_factor = ss->filter_cache->edge_factor[from_v]; - ss->filter_cache->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) * from_edge_factor; - ss->filter_cache->normal_factor[to_v] = dot_v3v3(data->original_normal, current_normal) * - powf(from_edge_factor, data->edge_sensitivity); - CLAMP(ss->filter_cache->normal_factor[to_v], 0.0f, 1.0f); + if (data->use_normals) { + float current_normal[3], prev_normal[3]; + sculpt_vertex_normal_get(ss, to_v, current_normal); + sculpt_vertex_normal_get(ss, from_v, prev_normal); + const float from_edge_factor = ss->filter_cache->edge_factor[from_v]; + ss->filter_cache->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) * + from_edge_factor; + ss->filter_cache->normal_factor[to_v] = dot_v3v3(data->original_normal, current_normal) * + powf(from_edge_factor, data->edge_sensitivity); + CLAMP(ss->filter_cache->normal_factor[to_v], 0.0f, 1.0f); + } + } + else { + /* PBVH_GRIDS duplicate handling */ + ss->filter_cache->mask_update_it[to_v] = ss->filter_cache->mask_update_it[from_v]; + if (data->use_normals) { + ss->filter_cache->edge_factor[to_v] = ss->filter_cache->edge_factor[from_v]; + ss->filter_cache->normal_factor[to_v] = ss->filter_cache->normal_factor[from_v]; + } } return true; @@ -9169,10 +9193,6 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent mouse[0] = event->mval[0]; mouse[1] = event->mval[1]; - if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { - return OPERATOR_CANCELLED; - } - sculpt_vertex_random_access_init(ss); op->customdata = MEM_mallocN(2 * sizeof(float), "initial mouse position"); |