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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2019-09-30 17:33:04 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-10-08 18:44:46 +0300
commit10ec207a6b1fdefe247b3e092d0b62a373ab1464 (patch)
treee214d53e0cfadf2687479c1574149329b6c95fd2 /source/blender/editors
parent52c02dc311714c47fd41cd585db4ce57997ee837 (diff)
Sculpt: support automasking, pose and mask expand for multires
These were the last remaining new sculpt tools that did not support multires. Performance could be improved still, but it should work. Fixes T68899
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c114
2 files changed, 69 insertions, 49 deletions
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");