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_subdiv_ccg.h7
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c108
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c114
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");