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:
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt_filter_mesh.c')
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c95
1 files changed, 91 insertions, 4 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index 7116ec77fa4..ac307df34fd 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -128,6 +128,8 @@ void SCULPT_filter_cache_free(SculptSession *ss)
MEM_SAFE_FREE(ss->filter_cache->prev_face_set);
MEM_SAFE_FREE(ss->filter_cache->automask);
MEM_SAFE_FREE(ss->filter_cache->surface_smooth_laplacian_disp);
+ MEM_SAFE_FREE(ss->filter_cache->sharpen_factor);
+ MEM_SAFE_FREE(ss->filter_cache->accum_disp);
MEM_SAFE_FREE(ss->filter_cache);
}
@@ -140,6 +142,7 @@ typedef enum eSculptMeshFilterTypes {
MESH_FILTER_RELAX = 5,
MESH_FILTER_RELAX_FACE_SETS = 6,
MESH_FILTER_SURFACE_SMOOTH = 7,
+ MESH_FILTER_SHARPEN = 8,
} eSculptMeshFilterTypes;
static EnumPropertyItem prop_mesh_filter_types[] = {
@@ -159,6 +162,7 @@ static EnumPropertyItem prop_mesh_filter_types[] = {
0,
"Surface Smooth",
"Smooth the surface of the mesh, preserving the volume"},
+ {MESH_FILTER_SHARPEN, "SHARPEN", 0, "Sharpen", "Sharpen the cavities of the mesh"},
{0, NULL, 0, NULL, NULL},
};
@@ -181,7 +185,8 @@ static bool sculpt_mesh_filter_needs_pmap(int filter_type, bool use_face_sets)
MESH_FILTER_SMOOTH,
MESH_FILTER_RELAX,
MESH_FILTER_RELAX_FACE_SETS,
- MESH_FILTER_SURFACE_SMOOTH);
+ MESH_FILTER_SURFACE_SMOOTH,
+ MESH_FILTER_SHARPEN);
}
static void mesh_filter_task_cb(void *__restrict userdata,
@@ -324,6 +329,26 @@ static void mesh_filter_task_cb(void *__restrict userdata,
ss->filter_cache->surface_smooth_shape_preservation);
break;
}
+ case MESH_FILTER_SHARPEN: {
+ const float smooth_ratio = ss->filter_cache->sharpen_smooth_ratio;
+
+ /* This filter can't work at full strength as it needs multiple iterations to reach a
+ * stable state. */
+ fade = clamp_f(fade, 0.0f, 0.5f);
+
+ float disp_sharpen[3];
+ copy_v3_v3(disp_sharpen, ss->filter_cache->accum_disp[vd.index]);
+ mul_v3_fl(disp_sharpen, 1.0f - ss->filter_cache->sharpen_factor[vd.index]);
+
+ float disp_avg[3];
+ float avg_co[3];
+ SCULPT_neighbor_coords_average(ss, avg_co, vd.index);
+ sub_v3_v3v3(disp_avg, avg_co, vd.co);
+ mul_v3_v3fl(
+ disp_avg, disp_avg, smooth_ratio * pow2f(ss->filter_cache->sharpen_factor[vd.index]));
+ add_v3_v3v3(disp, disp_avg, disp_sharpen);
+ break;
+ }
}
for (int it = 0; it < 3; it++) {
@@ -332,7 +357,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
}
}
- if (filter_type == MESH_FILTER_SURFACE_SMOOTH) {
+ if (ELEM(filter_type, MESH_FILTER_SURFACE_SMOOTH, MESH_FILTER_SHARPEN)) {
madd_v3_v3v3fl(final_pos, vd.co, disp, clamp_f(fade, 0.0f, 1.0f));
}
else {
@@ -348,6 +373,46 @@ static void mesh_filter_task_cb(void *__restrict userdata,
BKE_pbvh_node_mark_update(node);
}
+static void mesh_filter_sharpen_init_factors(SculptSession *ss)
+{
+ const int totvert = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totvert; i++) {
+ float avg[3];
+ SCULPT_neighbor_coords_average(ss, avg, i);
+ ss->filter_cache->sharpen_factor[i] = len_v3v3(avg, SCULPT_vertex_co_get(ss, i));
+ }
+ float max_factor = 0.0f;
+ for (int i = 0; i < totvert; i++) {
+ if (ss->filter_cache->sharpen_factor[i] > max_factor) {
+ max_factor = ss->filter_cache->sharpen_factor[i];
+ }
+ }
+
+ max_factor = 1.0f / max_factor;
+ for (int i = 0; i < totvert; i++) {
+ ss->filter_cache->sharpen_factor[i] *= max_factor;
+ ss->filter_cache->sharpen_factor[i] = 1.0f - pow2f(1.0f - ss->filter_cache->sharpen_factor[i]);
+ }
+}
+
+static void mesh_filter_sharpen_accumulate_displacement(SculptSession *ss)
+{
+ const int totvert = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totvert; i++) {
+ zero_v3(ss->filter_cache->accum_disp[i]);
+ }
+ for (int i = 0; i < totvert; i++) {
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+ float disp_n[3];
+ sub_v3_v3v3(disp_n, SCULPT_vertex_co_get(ss, i), SCULPT_vertex_co_get(ss, ni.index));
+ mul_v3_fl(disp_n, ss->filter_cache->sharpen_factor[i]);
+ add_v3_v3(ss->filter_cache->accum_disp[ni.index], disp_n);
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ }
+}
+
static void mesh_filter_surface_smooth_displace_task_cb(
void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
{
@@ -403,6 +468,10 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets);
BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false);
+ if (filter_type == MESH_FILTER_SHARPEN) {
+ mesh_filter_sharpen_accumulate_displacement(ss);
+ }
+
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
@@ -470,6 +539,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets);
BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false);
+ const int totvert = SCULPT_vertex_count_get(ss);
if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_pmap && !ob->sculpt->pmap) {
return OPERATOR_CANCELLED;
}
@@ -487,14 +557,22 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
}
if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_SURFACE_SMOOTH) {
- ss->filter_cache->surface_smooth_laplacian_disp = MEM_mallocN(
- 3 * sizeof(float) * SCULPT_vertex_count_get(ss), "surface smooth disp");
+ ss->filter_cache->surface_smooth_laplacian_disp = MEM_mallocN(3 * sizeof(float) * totvert,
+ "surface smooth disp");
ss->filter_cache->surface_smooth_shape_preservation = RNA_float_get(
op->ptr, "surface_smooth_shape_preservation");
ss->filter_cache->surface_smooth_current_vertex = RNA_float_get(
op->ptr, "surface_smooth_current_vertex");
}
+ if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_SHARPEN) {
+ ss->filter_cache->sharpen_smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio");
+ ss->filter_cache->sharpen_factor = MEM_mallocN(sizeof(float) * totvert, "sharpen factor");
+ ss->filter_cache->accum_disp = MEM_mallocN(3 * sizeof(float) * totvert, "orco");
+
+ mesh_filter_sharpen_init_factors(ss);
+ }
+
ss->filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
@@ -568,4 +646,13 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
"How much the position of each individual vertex influences the final result",
0.0f,
1.0f);
+ RNA_def_float(ot->srna,
+ "sharpen_smooth_ratio",
+ 0.35f,
+ 0.0f,
+ 1.0f,
+ "Smooth Ratio",
+ "How much smoothing is applied to polished surfaces",
+ 0.0f,
+ 1.0f);
}