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.h3
-rw-r--r--source/blender/blenkernel/intern/brush.c6
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c43
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c104
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h4
-rw-r--r--source/blender/makesdna/DNA_brush_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_brush.c1
8 files changed, 169 insertions, 3 deletions
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index 2277eb27ef1..7833ba9c046 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -311,6 +311,9 @@ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg,
SubdivCCGNeighbors *r_neighbors);
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int grid_index);
+void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ float r_point[3]);
typedef enum SubdivCCGAdjacencyType {
SUBDIV_CCG_ADJACENT_NONE,
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index af186dc4940..8cd30c2241f 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1481,6 +1481,11 @@ void BKE_brush_sculpt_reset(Brush *br)
br->curve_preset = BRUSH_CURVE_POW4;
br->spacing = 5;
break;
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
+ br->curve_preset = BRUSH_CURVE_SMOOTHER;
+ br->spacing = 10;
+ br->alpha = 1.0f;
+ break;
case SCULPT_TOOL_SLIDE_RELAX:
br->spacing = 10;
br->alpha = 1.0f;
@@ -1680,6 +1685,7 @@ void BKE_brush_sculpt_reset(Brush *br)
case SCULPT_TOOL_PAINT:
case SCULPT_TOOL_MASK:
case SCULPT_TOOL_DRAW_FACE_SETS:
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
br->add_col[0] = 0.75f;
br->add_col[1] = 0.75f;
br->add_col[2] = 0.75f;
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index ea8bae4737a..0997b42a19f 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -1933,4 +1933,47 @@ void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index)
subdiv_ccg->grid_hidden[grid_index] = BLI_BITMAP_NEW(key.grid_area, __func__);
}
+static void subdiv_ccg_coord_to_ptex_coord(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ int *r_ptex_face_index,
+ float *r_u,
+ float *r_v)
+{
+ Subdiv *subdiv = subdiv_ccg->subdiv;
+
+ const float grid_size = subdiv_ccg->grid_size;
+ const float grid_size_1_inv = 1.0f / (grid_size - 1);
+
+ const float grid_u = coord->x * grid_size_1_inv;
+ const float grid_v = coord->y * grid_size_1_inv;
+
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord->grid_index);
+ const SubdivCCGFace *faces = subdiv_ccg->faces;
+ const SubdivCCGFace *face = &faces[face_index];
+ const int *face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
+ *r_ptex_face_index = face_ptex_offset[face_index];
+
+ const float corner = coord->grid_index - face->start_grid_index;
+
+ if (face->num_grids == 4) {
+ BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, r_u, r_v);
+ }
+ else {
+ *r_ptex_face_index += corner;
+ *r_u = 1.0f - grid_v;
+ *r_v = 1.0f - grid_u;
+ }
+}
+
+void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ float r_point[3])
+{
+ Subdiv *subdiv = subdiv_ccg->subdiv;
+ int ptex_face_index;
+ float u, v;
+ subdiv_ccg_coord_to_ptex_coord(subdiv_ccg, coord, &ptex_face_index, &u, &v);
+ BKE_subdiv_eval_limit_point(subdiv, ptex_face_index, u, v, r_point);
+}
+
/** \} */
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 631961e342d..df0b2b380fa 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -722,6 +722,14 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
brush->sculpt_tool = SCULPT_TOOL_DRAW_FACE_SETS;
}
+ brush_name = "Multires Displacement Eraser";
+ brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2);
+ if (!brush) {
+ brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT);
+ id_us_min(&brush->id);
+ brush->sculpt_tool = SCULPT_TOOL_DISPLACEMENT_ERASER;
+ }
+
/* Use the same tool icon color in the brush cursor */
for (brush = bmain->brushes.first; brush; brush = brush->id.next) {
if (brush->ob_mode & OB_MODE_SCULPT) {
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 36f227d6cc7..d68b1226b40 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -204,6 +204,27 @@ const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, int index)
return SCULPT_vertex_co_get(ss, index);
}
+void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3])
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ case PBVH_BMESH:
+ copy_v3_v3(r_co, SCULPT_vertex_co_get(ss, index));
+ break;
+ case PBVH_GRIDS: {
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int vertex_index = index - grid_index * key->grid_area;
+
+ SubdivCCGCoord coord = {.grid_index = grid_index,
+ .x = vertex_index % key->grid_size,
+ .y = vertex_index / key->grid_size};
+ BKE_subdiv_ccg_eval_limit_point(ss->subdiv_ccg, &coord, r_co);
+ break;
+ }
+ }
+}
+
void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3])
{
if (ss->persistent_base) {
@@ -2236,6 +2257,8 @@ static float brush_strength(const Sculpt *sd,
case SCULPT_TOOL_DRAW_SHARP:
case SCULPT_TOOL_LAYER:
return alpha * flip * pressure * overlap * feather;
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
+ return alpha * pressure * overlap * feather;
case SCULPT_TOOL_CLOTH:
if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
/* Grab deform uses the same falloff as a regular grab brush. */
@@ -2908,6 +2931,73 @@ static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
}
}
+/** \name Sculpt Multires Displacement Eraser Brush
+ * \{ */
+
+static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float bstrength = clamp_f(ss->cache->bstrength, 0.0f, 1.0f);
+
+ float(*proxy)[3] = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ float limit_co[3];
+ float disp[3];
+ SCULPT_vertex_limit_surface_get(ss, vd.index, limit_co);
+ sub_v3_v3v3(disp, limit_co, vd.co);
+ mul_v3_v3fl(proxy[vd.i], disp, fade);
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_displacement_eraser_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ BKE_curvemapping_init(brush->curve);
+
+ /* Threaded loop over nodes. */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BLI_task_parallel_range(0, totnode, &data, do_displacement_eraser_brush_task_cb_ex, &settings);
+}
+
+/** \} */
+
static void do_draw_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
@@ -5700,6 +5790,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
case SCULPT_TOOL_DRAW_FACE_SETS:
SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode);
break;
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
+ do_displacement_eraser_brush(sd, ob, nodes, totnode);
+ break;
case SCULPT_TOOL_PAINT:
SCULPT_do_paint_brush(sd, ob, nodes, totnode);
break;
@@ -6251,6 +6344,8 @@ static const char *sculpt_tool_name(Sculpt *sd)
return "Cloth Brush";
case SCULPT_TOOL_DRAW_FACE_SETS:
return "Draw Face Sets";
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
+ return "Multires Displacement Eraser";
case SCULPT_TOOL_PAINT:
return "Paint Brush";
case SCULPT_TOOL_SMEAR:
@@ -6436,9 +6531,12 @@ static void sculpt_update_cache_invariants(
mul_m3_v3(mat, viewDir);
normalize_v3_v3(cache->true_view_normal, viewDir);
- cache->supports_gravity =
- (!ELEM(brush->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SIMPLIFY) &&
- (sd->gravity_factor > 0.0f));
+ cache->supports_gravity = (!ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_MASK,
+ SCULPT_TOOL_SMOOTH,
+ SCULPT_TOOL_SIMPLIFY,
+ SCULPT_TOOL_DISPLACEMENT_ERASER) &&
+ (sd->gravity_factor > 0.0f));
/* Get gravity vector in world space. */
if (cache->supports_gravity) {
if (sd->gravity_object) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index caa858a5372..b11a7005fb5 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -100,6 +100,10 @@ const float *SCULPT_vertex_color_get(SculptSession *ss, int index);
const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, int index);
void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3]);
+/* Returs the info of the limit surface when Multires is available, otherwise it returns the
+ * current coordinate of the vertex. */
+void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3]);
+
#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
typedef struct SculptVertexNeighborIter {
/* Storage */
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 503dba776a7..5d8eddaf5e1 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -810,6 +810,7 @@ typedef enum eBrushSculptTool {
SCULPT_TOOL_PAINT = 28,
SCULPT_TOOL_SMEAR = 29,
SCULPT_TOOL_BOUNDARY = 30,
+ SCULPT_TOOL_DISPLACEMENT_ERASER = 31,
} eBrushSculptTool;
/* Brush.uv_sculpt_tool */
@@ -847,6 +848,7 @@ typedef enum eBrushUVSculptTool {
SCULPT_TOOL_CLOTH, \
SCULPT_TOOL_THUMB, \
SCULPT_TOOL_LAYER, \
+ SCULPT_TOOL_DISPLACEMENT_ERASER, \
SCULPT_TOOL_DRAW_SHARP, \
SCULPT_TOOL_SLIDE_RELAX, \
SCULPT_TOOL_ELASTIC_DEFORM, \
@@ -866,6 +868,7 @@ typedef enum eBrushUVSculptTool {
SCULPT_TOOL_ROTATE, \
SCULPT_TOOL_THUMB, \
SCULPT_TOOL_DRAW_SHARP, \
+ SCULPT_TOOL_DISPLACEMENT_ERASER, \
SCULPT_TOOL_SLIDE_RELAX, \
SCULPT_TOOL_MASK) == 0)
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 852ddf32607..38916e2a45a 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -100,6 +100,7 @@ const EnumPropertyItem rna_enum_brush_sculpt_tool_items[] = {
{SCULPT_TOOL_CLOTH, "CLOTH", ICON_BRUSH_SCULPT_DRAW, "Cloth", ""},
{SCULPT_TOOL_SIMPLIFY, "SIMPLIFY", ICON_BRUSH_DATA, "Simplify", ""},
{SCULPT_TOOL_MASK, "MASK", ICON_BRUSH_MASK, "Mask", ""},
+ {SCULPT_TOOL_DISPLACEMENT_ERASER, "DISPLACEMENT_ERASER", ICON_BRUSH_SCULPT_DRAW, "Multires Displacement Eraser", ""},
{SCULPT_TOOL_PAINT, "PAINT", ICON_BRUSH_SCULPT_DRAW, "Paint", ""},
{SCULPT_TOOL_SMEAR, "SMEAR", ICON_BRUSH_SCULPT_DRAW, "Smear", ""},
{SCULPT_TOOL_DRAW_FACE_SETS, "DRAW_FACE_SETS", ICON_BRUSH_MASK, "Draw Face Sets", ""},