[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [46862] trunk/blender: Add input sample averaging to PaintStroke.

Nicholas Bishop nicholasbishop at gmail.com
Tue May 22 01:32:47 CEST 2012


Revision: 46862
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=46862
Author:   nicholasbishop
Date:     2012-05-21 23:32:46 +0000 (Mon, 21 May 2012)
Log Message:
-----------
Add input sample averaging to PaintStroke.

Averages input samples to make the brush stroke smoother. Only mouse
location is averaged right now, not pressure/tilt/etc.

The DNA is in struct Paint.num_input_samples, RNA is
Paint.input_samples. In combination with PaintStroke usage this change
applies to sculpt, vpaint, and wpaint.

The range of useful values varies quite a bit depending on input
device; mouse needs higher values to match tablet pen, so set max
samples pretty high (64).

Release note section:
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Sculpting#Input_Stroke_Averaging

Modified Paths:
--------------
    trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py
    trunk/blender/source/blender/blenloader/intern/readfile.c
    trunk/blender/source/blender/editors/sculpt_paint/paint_intern.h
    trunk/blender/source/blender/editors/sculpt_paint/paint_stroke.c
    trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c
    trunk/blender/source/blender/editors/sculpt_paint/sculpt.c
    trunk/blender/source/blender/makesdna/DNA_scene_types.h
    trunk/blender/source/blender/makesrna/intern/rna_sculpt_paint.c

Modified: trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py	2012-05-21 20:36:02 UTC (rev 46861)
+++ trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py	2012-05-21 23:32:46 UTC (rev 46862)
@@ -873,6 +873,8 @@
         layout.prop(sculpt, "show_brush")
         layout.prop(sculpt, "use_deform_only")
 
+        layout.prop(sculpt, "input_samples")
+
         self.unified_paint_settings(layout, context)
 
 
@@ -984,6 +986,8 @@
             col.prop(mesh, "use_mirror_x")
             col.prop(mesh, "use_mirror_topology")
 
+        col.prop(wpaint, "input_samples")
+        
         self.unified_paint_settings(col, context)
 
 # Commented out because the Apply button isn't an operator yet, making these settings useless
@@ -1014,6 +1018,8 @@
         col.prop(vpaint, "use_normal")
         col.prop(vpaint, "use_spray")
 
+        col.prop(vpaint, "input_samples")
+
         self.unified_paint_settings(col, context)
 
 # Commented out because the Apply button isn't an operator yet, making these settings useless

Modified: trunk/blender/source/blender/blenloader/intern/readfile.c
===================================================================
--- trunk/blender/source/blender/blenloader/intern/readfile.c	2012-05-21 20:36:02 UTC (rev 46861)
+++ trunk/blender/source/blender/blenloader/intern/readfile.c	2012-05-21 23:32:46 UTC (rev 46862)
@@ -4897,8 +4897,10 @@
 
 static void direct_link_paint(FileData *fd, Paint **paint)
 {
-/* TODO. is this needed */
+	/* TODO. is this needed */
 	(*paint) = newdataadr(fd, (*paint));
+	if (*paint && (*paint)->num_input_samples < 1)
+		(*paint)->num_input_samples = 1;
 }
 
 static void direct_link_scene(FileData *fd, Scene *sce)

Modified: trunk/blender/source/blender/editors/sculpt_paint/paint_intern.h
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/paint_intern.h	2012-05-21 20:36:02 UTC (rev 46861)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_intern.h	2012-05-21 23:32:46 UTC (rev 46862)
@@ -52,7 +52,7 @@
 
 /* paint_stroke.c */
 typedef int (*StrokeGetLocation)(struct bContext *C, float location[3], float mouse[2]);
-typedef int (*StrokeTestStart)(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+typedef int (*StrokeTestStart)(struct bContext *C, struct wmOperator *op, const float mouse[2]);
 typedef void (*StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke, struct PointerRNA *itemptr);
 typedef void (*StrokeDone)(const struct bContext *C, struct PaintStroke *stroke);
 

Modified: trunk/blender/source/blender/editors/sculpt_paint/paint_stroke.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/paint_stroke.c	2012-05-21 20:36:02 UTC (rev 46861)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_stroke.c	2012-05-21 23:32:46 UTC (rev 46862)
@@ -60,6 +60,12 @@
 #include <float.h>
 #include <math.h>
 
+typedef struct PaintSample {
+	float mouse[2];
+
+	/* TODO: other input properties, e.g. tablet pressure */
+} PaintSample;
+
 typedef struct PaintStroke {
 	void *mode_data;
 	void *smooth_stroke_cursor;
@@ -70,6 +76,12 @@
 	bglMats mats;
 	Brush *brush;
 
+	/* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
+	 * to smooth the stroke */
+	PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
+	int num_samples;
+	int cur_sample;
+
 	float last_mouse_position[2];
 
 	/* Set whether any stroke step has yet occurred
@@ -182,10 +194,11 @@
 }
 
 /* Returns zero if no sculpt changes should be made, non-zero otherwise */
-static int paint_smooth_stroke(PaintStroke *stroke, float output[2], wmEvent *event)
+static int paint_smooth_stroke(PaintStroke *stroke, float output[2],
+							   const PaintSample *sample)
 {
-	output[0] = event->x; 
-	output[1] = event->y;
+	output[0] = sample->mouse[0];
+	output[1] = sample->mouse[1];
 
 	if ((stroke->brush->flag & BRUSH_SMOOTH_STROKE) &&  
 	    !ELEM4(stroke->brush->sculpt_tool,
@@ -197,15 +210,16 @@
 	    !(stroke->brush->flag & BRUSH_RESTORE_MESH))
 	{
 		float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u;
-		float dx = stroke->last_mouse_position[0] - event->x, dy = stroke->last_mouse_position[1] - event->y;
+		float dx = stroke->last_mouse_position[0] - sample->mouse[0];
+		float dy = stroke->last_mouse_position[1] - sample->mouse[1];
 
 		/* If the mouse is moving within the radius of the last move,
 		 * don't update the mouse position. This allows sharp turns. */
 		if (dx * dx + dy * dy < stroke->brush->smooth_stroke_radius * stroke->brush->smooth_stroke_radius)
 			return 0;
 
-		output[0] = event->x * v + stroke->last_mouse_position[0] * u;
-		output[1] = event->y * v + stroke->last_mouse_position[1] * u;
+		output[0] = sample->mouse[0] * v + stroke->last_mouse_position[0] * u;
+		output[1] = sample->mouse[1] * v + stroke->last_mouse_position[1] * u;
 	}
 
 	return 1;
@@ -343,12 +357,52 @@
 	return keymap;
 }
 
+static void paint_stroke_add_sample(const Paint *paint,
+									PaintStroke *stroke,
+									float x, float y)
+{
+	PaintSample *sample = &stroke->samples[stroke->cur_sample];
+	int max_samples = MIN2(PAINT_MAX_INPUT_SAMPLES,
+						   MAX2(paint->num_input_samples, 1));
+
+	sample->mouse[0] = x;
+	sample->mouse[1] = y;
+
+	stroke->cur_sample++;
+	if (stroke->cur_sample >= max_samples)
+		stroke->cur_sample = 0;
+	if (stroke->num_samples < max_samples)
+		stroke->num_samples++;
+}
+
+static void paint_stroke_sample_average(const PaintStroke *stroke,
+										PaintSample *average)
+{
+	int i;
+	
+	memset(average, 0, sizeof(*average));
+
+	BLI_assert(stroke->num_samples > 0);
+	
+	for (i = 0; i < stroke->num_samples; i++)
+		add_v2_v2(average->mouse, stroke->samples[i].mouse);
+
+	mul_v2_fl(average->mouse, 1.0f / stroke->num_samples);
+
+	/*printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);*/
+}
+
 int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
+	Paint *p = paint_get_active(CTX_data_scene(C));
 	PaintStroke *stroke = op->customdata;
+	PaintSample sample_average;
 	float mouse[2];
 	int first = 0;
 
+	paint_stroke_add_sample(p, stroke, event->x, event->y);
+	paint_stroke_sample_average(stroke, &sample_average);
+
 	// let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
 	// this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
 	// since the 2D deltas are zero -- code in this file needs to be updated to use the
@@ -357,9 +411,8 @@
 		return OPERATOR_PASS_THROUGH;
 
 	if (!stroke->stroke_started) {
-		stroke->last_mouse_position[0] = event->x;
-		stroke->last_mouse_position[1] = event->y;
-		stroke->stroke_started = stroke->test_start(C, op, event);
+		copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
+		stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
 
 		if (stroke->stroke_started) {
 			stroke->smooth_stroke_cursor =
@@ -390,7 +443,7 @@
 	         (event->type == TIMER && (event->customdata == stroke->timer)) )
 	{
 		if (stroke->stroke_started) {
-			if (paint_smooth_stroke(stroke, mouse, event)) {
+			if (paint_smooth_stroke(stroke, mouse, &sample_average)) {
 				if (paint_space_stroke_enabled(stroke->brush)) {
 					if (!paint_space_stroke(C, op, event, mouse)) {
 						//ED_region_tag_redraw(ar);

Modified: trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c	2012-05-21 20:36:02 UTC (rev 46861)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c	2012-05-21 23:32:46 UTC (rev 46862)
@@ -2125,7 +2125,7 @@
 	return vgroup_validmap;
 }
 
-static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNUSED(mouse[2]))
 {
 	Scene *scene = CTX_data_scene(C);
 	struct PaintStroke *stroke = op->customdata;
@@ -2673,7 +2673,7 @@
 	}
 }
 
-static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *UNUSED(event))
+static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2]))
 {
 	ToolSettings *ts = CTX_data_tool_settings(C);
 	struct PaintStroke *stroke = op->customdata;

Modified: trunk/blender/source/blender/editors/sculpt_paint/sculpt.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/sculpt.c	2012-05-21 20:36:02 UTC (rev 46861)
+++ trunk/blender/source/blender/editors/sculpt_paint/sculpt.c	2012-05-21 23:32:46 UTC (rev 46862)
@@ -3224,7 +3224,7 @@
 }
 
 /* Initialize the stroke cache invariants from operator properties */
-static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, wmEvent *event)
+static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2])
 {
 	StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
 	Brush *brush = paint_brush(&sd->paint);
@@ -3247,14 +3247,7 @@
 	sculpt_init_mirror_clipping(ob, ss);
 
 	/* Initial mouse location */
-	if (event) {
-		ss->cache->initial_mouse[0] = event->x;
-		ss->cache->initial_mouse[1] = event->y;
-	}
-	else {
-		ss->cache->initial_mouse[0] = 0;
-		ss->cache->initial_mouse[1] = 0;
-	}
+	copy_v2_v2(ss->cache->initial_mouse, mouse);
 
 	mode = RNA_enum_get(op->ptr, "mode");
 	cache->invert = mode == BRUSH_STROKE_INVERT;
@@ -3768,18 +3761,18 @@
 }
 
 static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op,
-                                    wmEvent *event)
+                                    const float mouse[2])
 {
 	/* Don't start the stroke until mouse goes over the mesh.
 	 * note: event will only be null when re-executing the saved stroke. */
-	if (event == NULL || over_mesh(C, op, event->x, event->y)) {
+	if (over_mesh(C, op, mouse[0], mouse[1])) {
 		Object *ob = CTX_data_active_object(C);
 		SculptSession *ss = ob->sculpt;
 		Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
 
 		ED_view3d_init_mats_rv3d(ob, CTX_wm_region_view3d(C));
 

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-blender-cvs mailing list