[Bf-blender-cvs] [ad5ac8c833c] sculpt-mode-features: Mask filter: Dirty and constrast mask filters
Pablo Dobarro
noreply at git.blender.org
Fri Jun 7 16:28:17 CEST 2019
Commit: ad5ac8c833caa0c902054ba7e7dddf926769cd82
Author: Pablo Dobarro
Date: Fri Jun 7 16:27:59 2019 +0200
Branches: sculpt-mode-features
https://developer.blender.org/rBad5ac8c833caa0c902054ba7e7dddf926769cd82
Mask filter: Dirty and constrast mask filters
The funcionality should be the same as the dirty vertex colors operator.
This filter can be used to generate cavity mask for sculpting and
painting. I also added a contrast filter to control the cavity mask.
The contrast filter can be implemented with a real time preview in a
future version instead of incrementing the contrast with fixed steps.
===================================================================
M release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
M source/blender/editors/sculpt_paint/sculpt.c
M source/blender/editors/sculpt_paint/sculpt_intern.h
===================================================================
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index a1a0f7cd636..5ce53e3990d 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -979,6 +979,7 @@ class _defs_sculpt:
sub.use_property_split = False
sub.prop(props, "type", expand=False)
sub.prop(props, "iterations")
+ sub.prop(props, "dirty_only")
return dict(
idname="builtin.mask_filter",
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 9dc592c51f5..d22750c1f89 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1674,6 +1674,43 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert)
}
}
+static float neighbor_dirty_mask(SculptSession *ss, const int vert)
+{
+ const MeshElemMap *vert_map = &ss->pmap[vert];
+ const MVert *mvert = ss->mvert;
+
+ int i = 0;
+ int total = 0;
+ float avg[3];
+ zero_v3(avg);
+ for (i = 0; i < vert_map->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, vert, f_adj_v) != -1) {
+ int j;
+ for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
+ float normalized[3];
+ sub_v3_v3v3(normalized, mvert[f_adj_v[j]].co, mvert[vert].co);
+ normalize_v3(normalized);
+ add_v3_v3(avg, normalized);
+ total++;
+ }
+ }
+ }
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ float normal[3];
+ normal_short_to_float_v3(normal, mvert[vert].no);
+ float dot = dot_v3v3(avg, normal);
+ float ang = acos(dot);
+ if (ang < DEG2RAD(0)) {
+ ang = DEG2RAD(0);
+ }
+ return ang;
+ }
+ return 0;
+}
+
static float neighbor_min_mask(SculptSession *ss, const int vert, float *prev_mask)
{
const MeshElemMap *vert_map = &ss->pmap[vert];
@@ -8221,6 +8258,8 @@ typedef enum eSculptMaskFilterTypes {
MASK_FILTER_SHARPEN = 1,
MASK_FILTER_GROW = 2,
MASK_FILTER_SHRINK = 3,
+ MASK_FILTER_DIRTY = 4,
+ MASK_FILTER_CONTRAST = 5,
} eSculptMaskFilterTypes;
EnumPropertyItem prop_mask_filter_types[] = {
@@ -8228,6 +8267,8 @@ EnumPropertyItem prop_mask_filter_types[] = {
{MASK_FILTER_SHARPEN, "SHARPEN", 0, "Sharpen Mask", "Sharpen mask"},
{MASK_FILTER_GROW, "GROW", 0, "Grow Mask", "Grow mask"},
{MASK_FILTER_SHRINK, "SHRINK", 0, "Shrink Mask", "Shrink mask"},
+ {MASK_FILTER_DIRTY, "DIRTY", 0, "Dirty Mask", "Dirty mask"},
+ {MASK_FILTER_CONTRAST, "CONTRAST", 0, "Contrast Mask", "Contrast mask"},
{0, NULL, 0, NULL, NULL},
};
@@ -8246,6 +8287,7 @@ static void mask_filter_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
{
float val;
+ float contrast, delta, gain, offset;
switch (mode) {
case MASK_FILTER_BLUR:
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
@@ -8287,6 +8329,28 @@ static void mask_filter_task_cb(void *__restrict userdata,
CLAMP(*vd.mask, 0.0f, 1.0f);
}
break;
+ case MASK_FILTER_DIRTY:
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
+ val = neighbor_dirty_mask(ss, vd.vert_indices[vd.i]);
+ data->prev_mask[vd.vert_indices[vd.i]] = val;
+ }
+ break;
+ case MASK_FILTER_CONTRAST:
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
+ contrast = 0.1;
+ delta = contrast / 2.0f;
+ gain = 1.0f - delta * 2.0f;
+ if (contrast > 0) {
+ gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON);
+ offset = gain * (-delta);
+ }
+ else {
+ delta *= -1;
+ offset = gain * (delta);
+ }
+ *vd.mask = gain * (*vd.mask) + offset;
+ }
+ break;
}
if (vd.mvert)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@@ -8332,8 +8396,12 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
}
+ if (mode == MASK_FILTER_DIRTY) {
+ iterations = 1;
+ }
+
for (int i = 0; i < iterations; i++) {
- if (ELEM(mode, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) {
+ if (ELEM(mode, MASK_FILTER_GROW, MASK_FILTER_SHRINK, MASK_FILTER_DIRTY)) {
prev_mask = MEM_dupallocN(ss->vmask);
}
@@ -8355,6 +8423,38 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
MEM_freeN(prev_mask);
}
+ if (mode == MASK_FILTER_DIRTY) {
+ float min = FLT_MAX;
+ float max = FLT_MIN;
+ for (int i = 0; i < ss->totvert; i++) {
+ float val = prev_mask[i];
+ if (val < min) {
+ min = val;
+ }
+ if (val > max) {
+ max = val;
+ }
+ }
+
+ float range = max - min;
+ if (range < 0.0001f) {
+ range = 0;
+ }
+ else {
+ range = 1.0f / range;
+ }
+
+ bool dirty_only = RNA_boolean_get(op->ptr, "dirty_only");
+ for (int i = 0; i < ss->totvert; i++) {
+ ss->vmask[i] += 1 - ((prev_mask[i] - min) * range);
+ if (dirty_only) {
+ ss->vmask[i] = fmin(ss->vmask[i], 0.5) * 2.0f;
+ }
+ CLAMP(ss->vmask[i], 0.0f, 1.0f);
+ }
+ MEM_freeN(prev_mask);
+ }
+
sculpt_undo_push_end();
if (nodes)
@@ -8383,6 +8483,7 @@ void SCULPT_OT_mask_filter(struct wmOperatorType *ot)
/* rna */
ot->prop = RNA_def_enum(ot->srna, "type", prop_mask_filter_types, MASK_FILTER_BLUR, "Type", "");
ot->prop = RNA_def_int(ot->srna, "iterations", 1, 1, 100, "Iterations", "", 1, 50);
+ ot->prop = RNA_def_boolean(ot->srna, "dirty_only", false, "Dirty Only", "");
}
static void do_color_fill_task_cb(void *__restrict userdata,
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 2f83a12c8b6..dedbcc59ef2 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -303,6 +303,8 @@ typedef struct FilterCache {
/* unmasked nodes */
PBVHNode **nodes;
int totnode;
+
+ float *dirty_mask;
} FilterCache;
typedef struct StrokeCache {
More information about the Bf-blender-cvs
mailing list