[Bf-blender-cvs] [a5dead2] master: Fix T44604 bad quality of rake with bezier curves.

Antony Riakiotakis noreply at git.blender.org
Thu May 7 18:10:58 CEST 2015


Commit: a5dead2e8cee27c33771f7d74020ef9e15beceee
Author: Antony Riakiotakis
Date:   Thu May 7 18:10:34 2015 +0200
Branches: master
https://developer.blender.org/rBa5dead2e8cee27c33771f7d74020ef9e15beceee

Fix T44604 bad quality of rake with bezier curves.

We can calculate tangents analytically for bezier curves, so just make
them awesome. New code uses forward differencing calculation for
efficiency just like curve calculation.

Picture before/after:

http://www.pasteall.org/pic/87843

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

M	source/blender/blenkernel/BKE_curve.h
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/intern/curve.c
M	source/blender/blenkernel/intern/paint.c
M	source/blender/editors/sculpt_paint/paint_stroke.c

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

diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 9de13ce..3ecd472 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -120,6 +120,7 @@ void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob,  struct ListBa
                           const bool for_render, const bool use_render_resolution);
 
 void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
+void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
 
 void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect);
 
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 34b645e..09ccc3d 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -144,6 +144,7 @@ float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level,
 
 /* stroke related */
 void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, const float mouse_pos[2]);
+void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, float rotation);
 
 void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
 
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 30ceaea..c27460b 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -1384,6 +1384,30 @@ void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float
 	}
 }
 
+/* forward differencing method for first derivative of cubic bezier curve */
+void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
+{
+	float rt0, rt1, rt2, f;
+	int a;
+
+	f = 1.0f / (float)it;
+
+	rt0 = 3.0f * (q1 - q0);
+	rt1 = f * (3.0f * (q3 - q0) + 9.0f * (q1 - q2));
+	rt2 = 6.0f * (q0 + q2)- 12.0f * q1;
+
+	q0 = rt0;
+	q1 = f * (rt1 + rt2);
+	q2 = 2.0f * f * rt1;
+
+	for (a = 0; a <= it; a++) {
+		*p = q0;
+		p = (float *)(((char *)p) + stride);
+		q0 += q1;
+		q1 += q2;
+	}
+}
+
 static void forward_diff_bezier_cotangent(const float p0[3], const float p1[3], const float p2[3], const float p3[3],
                                           float p[3], int it, int stride)
 {
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 1284ffd..0bda740 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -519,7 +519,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
 /* threshold to move before updating the brush rotation */
 #define RAKE_THRESHHOLD 20
 
-static void update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, float rotation)
+void paint_update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, float rotation)
 {
 	if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)
 		ups->brush_rotation = rotation;
@@ -527,7 +527,6 @@ static void update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush,
 		ups->brush_rotation = 0.0f;
 
 	if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)
-		/* here, translation contains the mouse coordinates. */
 		ups->brush_rotation_sec = rotation;
 	else
 		ups->brush_rotation_sec = 0.0f;
@@ -549,12 +548,12 @@ void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, cons
 
 			ups->last_rake_angle = rotation;
 
-			update_brush_rake_rotation(ups, brush, rotation);
+			paint_update_brush_rake_rotation(ups, brush, rotation);
 		}
 		/* make sure we reset here to the last rotation to avoid accumulating
 		 * values in case a random rotation is also added */
 		else {
-			update_brush_rake_rotation(ups, brush, ups->last_rake_angle);
+			paint_update_brush_rake_rotation(ups, brush, ups->last_rake_angle);
 		}
 	}
 	else {
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 2ae5447..d5c3e7e 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -347,7 +347,8 @@ static bool paint_brush_update(bContext *C,
 		if (!stroke->brush_init) {
 			copy_v2_v2(ups->last_rake, mouse_init);
 		}
-		else {
+		/* curve strokes do their own rake calculation */
+		else if (!(brush->flag & BRUSH_CURVE)) {
 			paint_calculate_rake_rotation(ups, brush, mouse_init);
 		}
 	}
@@ -954,6 +955,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
 	Brush *br = stroke->brush;
 
 	if (br->flag & BRUSH_CURVE) {
+		UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
 		const Scene *scene = CTX_data_scene(C);
 		const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
 		PaintCurve *pc = br->paint_curve;
@@ -974,29 +976,53 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
 		for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
 			int j;
 			float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
+			float tangents[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
 			PaintCurvePoint *pcp_next = pcp + 1;
+			bool do_rake = false;
 
-			for (j = 0; j < 2; j++)
+			for (j = 0; j < 2; j++) {
 				BKE_curve_forward_diff_bezier(
 				        pcp->bez.vec[1][j],
 				        pcp->bez.vec[2][j],
 				        pcp_next->bez.vec[0][j],
 				        pcp_next->bez.vec[1][j],
 				        data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
+			}
 
+			if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ||
+			    (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
+			{
+				do_rake = true;
+				for (j = 0; j < 2; j++) {
+					BKE_curve_forward_diff_tangent_bezier(
+					        pcp->bez.vec[1][j],
+					        pcp->bez.vec[2][j],
+					        pcp_next->bez.vec[0][j],
+					        pcp_next->bez.vec[1][j],
+					        tangents + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
+				}
+			}
 
 			for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
+				float rotation = 0.0f;
+				if (do_rake) {
+					normalize_v2_v2(&tangents[2 * j], &tangents[2 * j]);
+					rotation = atan2f(tangents[2 * j], tangents[2 * j + 1]);
+				}
+
 				if (!stroke->stroke_started) {
 					stroke->last_pressure = 1.0;
 					copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
 					stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
 
 					if (stroke->stroke_started) {
+						paint_update_brush_rake_rotation(ups, br, rotation);
 						paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0);
 						paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
 					}
 				}
 				else {
+					paint_update_brush_rake_rotation(ups, br, rotation);
 					paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
 				}
 			}




More information about the Bf-blender-cvs mailing list