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
path: root/source
diff options
context:
space:
mode:
authorAntony Riakiotakis <kalast@gmail.com>2015-05-07 19:10:34 +0300
committerAntony Riakiotakis <kalast@gmail.com>2015-05-07 19:10:48 +0300
commita5dead2e8cee27c33771f7d74020ef9e15beceee (patch)
tree22d3954a595245b00dcb8875f278c67e8faa3752 /source
parenta2eb94b47032502a65027db4b241a40e56f767eb (diff)
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
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_curve.h1
-rw-r--r--source/blender/blenkernel/BKE_paint.h1
-rw-r--r--source/blender/blenkernel/intern/curve.c24
-rw-r--r--source/blender/blenkernel/intern/paint.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c30
5 files changed, 57 insertions, 6 deletions
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 9de13ce9240..3ecd472f65b 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 34b645ea62c..09ccc3dced7 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 30ceaea89b8..c27460b81c0 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 1284ffda0ff..0bda740af53 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 2ae544706df..d5c3e7e7fab 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));
}
}