[Bf-blender-cvs] [4cd1941bb7d] sculpt-mode-features: Mesh Filter tool: Initial implementation

Pablo Dobarro noreply at git.blender.org
Thu Apr 11 15:19:04 CEST 2019


Commit: 4cd1941bb7dc9e13de803ee2c697b2182c9f93ad
Author: Pablo Dobarro
Date:   Thu Apr 11 15:18:44 2019 +0200
Branches: sculpt-mode-features
https://developer.blender.org/rB4cd1941bb7dc9e13de803ee2c697b2182c9f93ad

Mesh Filter tool: Initial implementation

This tool applies a deformation to all vertices in the sculpt taking the
mask into account. It is useful for creating surface detail or hard
surface sculpts. It is also the base for the implementation of the
transform tool.

Notes:
- The smooth filter needs multiple iterations. Right now it only applies
one iteration per tool action, so it is unusable in most cases. I don't
know if adding this is possible with the current smooth code while
supporting real-time preview.
- I'm not sure if it is properly integrated with the tool system and the
keymap (probably not).
- Only works with mesh, no dyntopo or multires.
- It still needs to ignore nodes with all vertices fully masked. Adding
this basic optimization will increase performance a lot when working
with high-resolution meshes.
- Previewing the deformation in real time is not the best option for
performance, I could add an operator that applies the filter without
preview.

===================================================================

M	release/scripts/presets/keyconfig/keymap_data/blender_default.py
M	release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h

===================================================================

diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 84e97d5b764..68454456b42 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -5783,6 +5783,17 @@ def km_3d_view_tool_sculpt_box_mask(params):
     )
 
 
+def km_3d_view_tool_sculpt_mesh_filter(params):
+    return (
+        "3D View Tool: Sculpt, Mesh Filter",
+        {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+        {"items": [
+            ("sculpt.mesh_filter", {"type": params.tool_tweak, "value": 'ANY'},
+             None)
+        ]},
+    )
+
+
 def km_3d_view_tool_paint_weight_sample_weight(params):
     return (
         "3D View Tool: Paint Weight, Sample Weight",
@@ -6222,6 +6233,7 @@ def generate_keymaps(params=None):
         km_3d_view_tool_edit_curve_extrude_cursor(params),
         km_3d_view_tool_sculpt_box_hide(params),
         km_3d_view_tool_sculpt_box_mask(params),
+        km_3d_view_tool_sculpt_mesh_filter(params),
         km_3d_view_tool_paint_weight_sample_weight(params),
         km_3d_view_tool_paint_weight_sample_vertex_group(params),
         km_3d_view_tool_paint_weight_gradient(params),
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 42953a05ca6..cb267549b05 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -976,6 +976,24 @@ class _defs_sculpt:
             keymap=(),
         )
 
+    @ToolDef.from_fn
+    def mesh_filter():
+        def draw_settings(context, layout, tool):
+            props = tool.operator_properties("sculpt.mesh_filter")
+            sub = layout.row()
+            sub.use_property_split = False
+            sub.prop(props, "type", expand=False)
+            sub.prop(props, "strength")
+
+        return dict(
+            idname="builtin.mesh_filter",
+            label="Mesh Filter",
+            icon="ops.sculpt.mesh_filter",
+            widget=None,
+            keymap= (),
+            draw_settings=draw_settings,
+        )
+
 
 class _defs_vertex_paint:
 
@@ -1856,6 +1874,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
             None,
             _defs_sculpt.hide_border,
             _defs_sculpt.mask_border,
+            _defs_sculpt.mesh_filter,
         ],
         'PAINT_TEXTURE': [
             _defs_texture_paint.generate_from_brushes,
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 991f47e6366..3f6b2835c16 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -253,6 +253,7 @@ typedef struct SculptSession {
 	float cursor_location[3];
 	float cursor_view_normal[3];
 	float cursor_normal[3];
+	bool use_orco;
 
 	/* Automasking active vertex */
 	MVert *active_vertex_mesh;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 7f57cc883aa..882cd0fb090 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1398,7 +1398,7 @@ static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float
 		if (sd->flags & (SCULPT_LOCK_X << i))
 			continue;
 
-		if ((ss->cache->flag & (CLIP_X << i)) && (fabsf(co[i]) <= ss->cache->clip_tolerance[i]))
+		if (ss->cache && (ss->cache->flag & (CLIP_X << i)) && (fabsf(co[i]) <= ss->cache->clip_tolerance[i]))
 			co[i] = 0.0f;
 		else
 			co[i] = val[i];
@@ -3954,7 +3954,7 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush, Unified
 
 	int n, totnode;
 	/* Build a list of all nodes that are potentially within the brush's area of influence */
-	const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original;
+	const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original || ss->use_orco;
 	const float radius_scale = 1.25f;
 	PBVHNode **nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
 
@@ -4234,6 +4234,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
 	const float radius_scale = 1.0f;
 	PBVHNode **nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
 
+	/* Disable global use_orco used in other operators */
+	ss->use_orco = false;
+
 	/* Only act if some verts are inside the brush area */
 	if (totnode) {
 		float location[3];
@@ -4395,7 +4398,7 @@ static void sculpt_combine_proxies_task_cb(
 	Object *ob = data->ob;
 
 	/* these brushes start from original coordinates */
-	const bool use_orco = ELEM(data->brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB);
+	bool use_orco = ss->use_orco || ELEM(data->brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB);
 
 	PBVHVertexIter vd;
 	PBVHProxyNode *proxies;
@@ -4447,7 +4450,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
 	BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
 
 	/* first line is tools that don't support proxies */
-	if (ss->cache->supports_gravity ||
+	if (ss->cache && ss->cache->supports_gravity ||
 	    (sculpt_tool_is_proxy_used(brush->sculpt_tool) == false))
 	{
 		SculptThreadedTaskData data = {
@@ -5641,7 +5644,8 @@ static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
 	if ((brush->flag & BRUSH_ANCHORED) ||
 	    (brush->sculpt_tool == SCULPT_TOOL_GRAB &&
 	     BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) ||
-	    (brush->flag & BRUSH_DRAG_DOT))
+	    (brush->flag & BRUSH_DRAG_DOT) ||
+	     ss->use_orco)
 	{
 		paint_mesh_restore_co(sd, ob);
 	}
@@ -6984,10 +6988,230 @@ static void SCULPT_OT_set_detail_size(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+typedef enum eSculptMeshFilterTypes {
+	MESH_FILTER_SMOOTH = 0,
+	MESH_FILTER_GROW = 1,
+	MESH_FILTER_SCALE = 2,
+	MESH_FILTER_DILATE = 3,
+	MESH_FILTER_SPHERE = 4,
+	MESH_FILTER_RANDOM = 5,
+} eSculptMeshFilterTypes;
+
+EnumPropertyItem prop_mesh_filter_types[] = {
+	{MESH_FILTER_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth mesh"},
+	{MESH_FILTER_GROW, "GROW", 0, "Grow", "Grow mesh"},
+	{MESH_FILTER_SCALE, "SCALE", 0, "Scale", "Scale mesh"},
+	{MESH_FILTER_DILATE, "DILATE", 0, "Dilate", "Dilate mesh"},
+	{MESH_FILTER_SPHERE, "SPHERE", 0, "Sphere", "Morph into sphere"},
+	{MESH_FILTER_RANDOM, "RANDOM", 0, "Random", "Randomize mesh"},
+	{0, NULL, 0, NULL, NULL},
+};
+
+
+static void mesh_filter_task_cb(
+        void *__restrict userdata,
+        const int i,
+        const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+	SculptThreadedTaskData *data = userdata;
+	SculptSession *ss = data->ob->sculpt;
+	PBVHNode *node = data->nodes[i];
+	Sculpt *sd = data->sd;
+
+	const int mode = data->filter_type;
+
+	PBVHVertexIter vd;
+
+	SculptOrigVertData orig_data;
+	float (*proxy)[3];
+	sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[i]);
+	proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[i])->co;
+
+	sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
+
+	BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
+		float val[3], avg[3], normal[3], disp[3], disp2[3], transform[3][3];
+		float fade = vd.mask? *vd.mask : 1.0f;
+		fade = 1 - fade;
+		fade *= data->filter_strength;
+		sculpt_orig_vert_data_update(&orig_data, &vd);
+		switch (mode) {
+			case MESH_FILTER_SMOOTH:
+				CLAMP(fade, -1.0f, 1.0f);
+				neighbor_average(ss, avg, vd.vert_indices[vd.i]);
+				sub_v3_v3v3(val, avg, orig_data.co);
+				madd_v3_v3v3fl(val, orig_data.co, val, fade);
+				sub_v3_v3v3(disp, val, orig_data.co);
+				copy_v3_v3(proxy[vd.i], disp);
+				break;
+			case MESH_FILTER_DILATE:
+				normal_short_to_float_v3(normal, vd.no);
+				mul_v3_v3fl(proxy[vd.i], normal, fade);
+				break;
+			case MESH_FILTER_GROW:
+				sub_v3_v3v3(disp, orig_data.co, data->ob->loc);
+				normalize_v3(disp);
+				mul_v3_v3fl(proxy[vd.i], disp, fade);
+			case MESH_FILTER_SCALE:
+				unit_m3(transform);
+				scale_m3_fl(transform, 1 + fade);
+				copy_v3_v3(val, orig_data.co);
+				mul_m3_v3(transform, val);
+				sub_v3_v3v3(disp, val, orig_data.co);
+				copy_v3_v3(proxy[vd.i], disp);
+				break;
+			case MESH_FILTER_SPHERE:
+				sub_v3_v3v3(disp, orig_data.co, data->ob->loc);
+				normalize_v3(disp);
+				if (fade > 0) {
+					mul_v3_v3fl(disp, disp, fade);
+				}
+				else {
+					mul_v3_v3fl(disp, disp, -fade);
+				}
+
+				unit_m3(transform);
+				if (fade > 0) {
+					scale_m3_fl(transform, 1 - fade);
+				}
+				else {
+					scale_m3_fl(transform, 1 + fade);
+				}
+				copy_v3_v3(val, orig_data.co);
+				mul_m3_v3(transform, val);
+				sub_v3_v3v3(disp2, val, orig_data.co);
+
+				mid_v3_v3v3(disp, disp, disp2);
+				mul_v3_v3fl(proxy[vd.i], disp, fade);
+				break;
+			case MESH_FILTER_RANDOM:
+				normal_short_to_float_v3(normal, vd.no);
+				float random = (float)rand()/(float)(RAND_MAX);
+				mul_v3_fl(normal, random - 0.5f);
+				mul_v3_v3fl(proxy[vd.i], normal, fade);
+				break;
+		}
+		if (vd.mvert)
+			vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+	} BKE_pbvh_vertex_iter_end;
+
+	BKE_pbvh_node_mark_redraw(node);
+}
+
+int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+	ARegion *ar = CTX_wm_region(C);
+	struct Scene *scene = CTX_data_scene(C);
+	Object *ob = CTX_data_active_object(C);
+	Depsgraph *depsgraph = CTX_data_depsgraph(C);
+	PBVH *pbvh = ob->sculpt->pbvh;
+	SculptSession *ss = ob->sculpt;
+	PBVHNode **nodes;
+	int totnode;
+	Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+	int mode = RNA_enum_get(op->ptr, "type");
+	float filter_strength = RNA_float_get(op->ptr, "strength");
+
+	/* Disable for multires and dyntopo for now */
+	if (BKE_pbvh_type(pbvh) != PBVH_FACES) {
+		ss->use_orco = false;
+		return OPERATOR_CANCELLED;
+	}
+
+	BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, mode == MESH_FILTER_SMOOTH, true);
+	sculpt_restore_mesh(sd, ob);
+	if (BKE_pbvh_type(pbvh) == PBVH_FACES && mode == MESH_FILTER_SMOOTH &

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list