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:
authorCampbell Barton <ideasman42@gmail.com>2012-08-27 13:44:56 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-08-27 13:44:56 +0400
commit13254cde8c7ca38af2dcec35efdb9f8f9b3bca46 (patch)
treea6d62e3b3948af458b5a8913293412393a540a96 /source
parent4035bf16e75acde1ef77d8a176edc95dbad70f35 (diff)
Alternate mask spline feather offset calculation method: now there are 2 [Even | Smooth]
- Even preserves thickness but can give unsightly loops - Smooth gives nicer shape but can give unsightly feather/spline mismatch for 'S' shapes created by beziers. This is an example where smooth works much nicer. http://www.graphicall.org/ftp/ideasman42/mask_compare.png
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/mask.c19
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c170
-rw-r--r--source/blender/blenlib/BLI_math_vector.h3
-rw-r--r--source/blender/blenlib/intern/math_vector.c23
-rw-r--r--source/blender/makesdna/DNA_mask_types.h20
-rw-r--r--source/blender/makesrna/intern/rna_mask.c13
6 files changed, 219 insertions, 29 deletions
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 5182c52605a..f73fb3879b8 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -1194,17 +1194,6 @@ void BKE_mask_calc_handle_point(MaskSpline *spline, MaskSplinePoint *point)
mask_calc_point_handle(point, point_prev, point_next);
}
-static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dist)
-{
- if (!equals_v2v2(v2, v1)) {
- float nor[2];
-
- sub_v2_v2v2(nor, v1, v2);
- normalize_v2(nor);
- madd_v2_v2v2fl(v1, v2, nor, dist);
- }
-}
-
void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *point, const float u)
{
/* TODO! - make this interpolate between siblings - not always midpoint! */
@@ -1246,8 +1235,8 @@ void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *p
length_average /= (float)length_tot;
weight_average /= (float)length_tot;
- enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
- enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
+ dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
+ dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
point->bezt.weight = weight_average;
}
}
@@ -1279,8 +1268,8 @@ void BKE_mask_calc_handle_point_auto(MaskSpline *spline, MaskSplinePoint *point,
/* preserve length by applying it back */
if (do_recalc_length == FALSE) {
- enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
- enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
+ dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
+ dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
}
}
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index 9d9f1665a7b..065dc38c81e 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -507,15 +507,12 @@ void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*fe
#undef BUCKET_INDEX
}
-/**
- * values align with #BKE_mask_spline_differentiate_with_resolution_ex
- * when \a resol arguments match.
- */
-float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline,
- int *tot_feather_point,
- const unsigned int resol,
- const int do_feather_isect
- ))[2]
+/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */
+static float (*mask_spline_feather_differentiated_points_with_resolution_ex__even(MaskSpline *spline,
+ int *tot_feather_point,
+ const unsigned int resol,
+ const int do_feather_isect
+ ))[2]
{
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
MaskSplinePoint *point_curr, *point_prev;
@@ -583,6 +580,161 @@ float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpl
return feather;
}
+/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */
+static float (*mask_spline_feather_differentiated_points_with_resolution_ex__double(MaskSpline *spline,
+ int *tot_feather_point,
+ const unsigned int resol,
+ const int do_feather_isect
+ ))[2]
+{
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+
+ MaskSplinePoint *point_curr, *point_prev;
+ float (*feather)[2], (*fp)[2];
+ const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
+ int a;
+
+ if (spline->tot_point <= 1) {
+ /* nothing to differentiate */
+ *tot_feather_point = 0;
+ return NULL;
+ }
+
+ /* len+1 because of 'forward_diff_bezier' function */
+ *tot_feather_point = tot;
+ feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline vets");
+
+ a = spline->tot_point - 1;
+ if (spline->flag & MASK_SPLINE_CYCLIC)
+ a++;
+
+ point_prev = points_array;
+ point_curr = point_prev + 1;
+
+ while (a--) {
+ BezTriple local_prevbezt;
+ BezTriple local_bezt;
+ float point_prev_n[2], point_curr_n[2], tvec[2];
+ float weight_prev, weight_curr;
+ float len_base, len_feather, len_scalar;
+
+ BezTriple *bezt_prev;
+ BezTriple *bezt_curr;
+ int j;
+
+ if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
+ point_curr = points_array;
+
+ bezt_prev = &point_prev->bezt;
+ bezt_curr = &point_curr->bezt;
+
+ /* modified copy for feather */
+ local_prevbezt = *bezt_prev;
+ local_bezt = *bezt_curr;
+
+ bezt_prev = &local_prevbezt;
+ bezt_curr = &local_bezt;
+
+ /* calc the normals */
+ sub_v2_v2v2(tvec, bezt_prev->vec[1], bezt_prev->vec[0]);
+ normalize_v2(tvec);
+ point_prev_n[0] = -tvec[1];
+ point_prev_n[1] = tvec[0];
+
+ sub_v2_v2v2(tvec, bezt_curr->vec[1], bezt_curr->vec[0]);
+ normalize_v2(tvec);
+ point_curr_n[0] = -tvec[1];
+ point_curr_n[1] = tvec[0];
+
+ weight_prev = bezt_prev->weight;
+ weight_curr = bezt_curr->weight;
+
+ mul_v2_fl(point_prev_n, weight_prev);
+ mul_v2_fl(point_curr_n, weight_curr);
+
+ /* before we transform verts */
+ len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
+
+ // add_v2_v2(bezt_prev->vec[0], point_prev_n); // not needed
+ add_v2_v2(bezt_prev->vec[1], point_prev_n);
+ add_v2_v2(bezt_prev->vec[2], point_prev_n);
+
+ add_v2_v2(bezt_curr->vec[0], point_curr_n);
+ add_v2_v2(bezt_curr->vec[1], point_curr_n);
+ // add_v2_v2(bezt_curr->vec[2], point_curr_n); // not needed
+
+ len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
+
+ /* scale by chane in length */
+ len_scalar = len_feather / len_base;
+ dist_ensure_v2_v2fl(bezt_prev->vec[2], bezt_prev->vec[1], len_scalar * len_v2v2(bezt_prev->vec[2], bezt_prev->vec[1]));
+ dist_ensure_v2_v2fl(bezt_curr->vec[0], bezt_curr->vec[1], len_scalar * len_v2v2(bezt_curr->vec[0], bezt_curr->vec[1]));
+
+
+ for (j = 0; j < 2; j++) {
+ BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j],
+ bezt_curr->vec[0][j], bezt_curr->vec[1][j],
+ &(*fp)[j], resol, 2 * sizeof(float));
+ }
+
+
+ /* scale by the uw's */
+ if (point_prev->tot_uw) {
+ for (j = 0; j < resol; j++, fp++) {
+ float u = (float) j / resol;
+ float weight_uw, weight_scalar;
+ float co[2];
+
+ /* TODO - these calls all calculate similar things
+ * could be unified for some speed */
+ BKE_mask_point_segment_co(spline, point_prev, u, co);
+
+ weight_uw = BKE_mask_point_weight(spline, point_prev, u);
+ weight_scalar = BKE_mask_point_weight_scalar(spline, point_prev, u);
+
+ dist_ensure_v2_v2fl(*fp, co, len_v2v2(*fp, co) * (weight_uw / weight_scalar));
+ }
+ }
+ else {
+ fp += resol;
+ }
+
+ if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
+ copy_v2_v2(*fp, bezt_curr->vec[1]);
+ }
+
+ point_prev = point_curr;
+ point_curr++;
+ }
+
+ if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) {
+ BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot);
+ }
+
+ return feather;
+}
+
+/**
+ * values align with #BKE_mask_spline_differentiate_with_resolution_ex
+ * when \a resol arguments match.
+ */
+float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline,
+ int *tot_feather_point,
+ const unsigned int resol,
+ const int do_feather_isect
+ ))[2]
+{
+ switch (spline->offset_mode) {
+ case MASK_SPLINE_OFFSET_EVEN:
+ return mask_spline_feather_differentiated_points_with_resolution_ex__even(spline, tot_feather_point, resol, do_feather_isect);
+ break;
+ case MASK_SPLINE_OFFSET_SMOOTH:
+ default:
+ return mask_spline_feather_differentiated_points_with_resolution_ex__double(spline, tot_feather_point, resol, do_feather_isect);
+ break;
+ }
+}
+
float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height,
int *tot_feather_point, const int do_feather_isect))[2]
{
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 8499a7f219c..eef8c9daaef 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -220,6 +220,9 @@ MINLINE void normal_float_to_short_v3(short r[3], const float n[3]);
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]);
+void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist);
+void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist);
+
/***************************** Array Functions *******************************/
/* attempted to follow fixed length vertex functions. names could be improved*/
double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size);
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 5cda1c0b81f..4196bab0474 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -451,6 +451,29 @@ void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
if (max[2] < vec[2]) max[2] = vec[2];
}
+/** ensure \a v1 is \a dist from \a v2 */
+void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist)
+{
+ if (!equals_v3v3(v2, v1)) {
+ float nor[3];
+
+ sub_v3_v3v3(nor, v1, v2);
+ normalize_v3(nor);
+ madd_v3_v3v3fl(v1, v2, nor, dist);
+ }
+}
+
+void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist)
+{
+ if (!equals_v2v2(v2, v1)) {
+ float nor[2];
+
+ sub_v2_v2v2(nor, v1, v2);
+ normalize_v2(nor);
+ madd_v2_v2v2fl(v1, v2, nor, dist);
+ }
+}
+
/***************************** Array Functions *******************************/
double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size)
diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h
index 6c7f7aa2471..bf388d8c018 100644
--- a/source/blender/makesdna/DNA_mask_types.h
+++ b/source/blender/makesdna/DNA_mask_types.h
@@ -82,13 +82,14 @@ typedef struct MaskSplinePoint {
typedef struct MaskSpline {
struct MaskSpline *next, *prev;
- int flag; /* defferent spline flag (closed, ...) */
+ short flag; /* defferent spline flag (closed, ...) */
+ char offset_mode; /* feather offset method */
+ char weight_interp; /* weight interpolation */
+
int tot_point; /* total number of points */
MaskSplinePoint *points; /* points which defines spline itself */
MaskParent parent; /* parenting information of the whole spline */
- int weight_interp, pad; /* weight interpolation */
-
MaskSplinePoint *points_deform; /* deformed copy of 'points' BezTriple data - not saved */
} MaskSpline;
@@ -146,8 +147,17 @@ enum {
};
/* MaskSpline->weight_interp */
-#define MASK_SPLINE_INTERP_LINEAR 1
-#define MASK_SPLINE_INTERP_EASE 2
+enum {
+ MASK_SPLINE_INTERP_LINEAR = 1,
+ MASK_SPLINE_INTERP_EASE = 2
+};
+
+/* MaskSpline->offset_mode */
+enum {
+ MASK_SPLINE_OFFSET_EVEN = 0,
+ MASK_SPLINE_OFFSET_SMOOTH = 1
+};
+
/* ob->restrictflag */
#define MASK_RESTRICT_VIEW 1
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index a6571a2db4f..719baed8edb 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -540,6 +540,12 @@ static void rna_def_maskSpline(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem spline_offset_mode_items[] = {
+ {MASK_SPLINE_OFFSET_EVEN, "EVEN", 0, "Even", "Calculate even feather offset"},
+ {MASK_SPLINE_OFFSET_SMOOTH, "SMOOTH", 0, "Smooth", "Calculate feather offset as a second curve"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
StructRNA *srna;
PropertyRNA *prop;
@@ -548,6 +554,13 @@ static void rna_def_maskSpline(BlenderRNA *brna)
srna = RNA_def_struct(brna, "MaskSpline", NULL);
RNA_def_struct_ui_text(srna, "Mask spline", "Single spline used for defining mask shape");
+ /* offset mode */
+ prop = RNA_def_property(srna, "offset_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "offset_mode");
+ RNA_def_property_enum_items(prop, spline_offset_mode_items);
+ RNA_def_property_ui_text(prop, "Feather Offset", "The method used for calculating the feather offset");
+ RNA_def_property_update(prop, 0, "rna_Mask_update_data");
+
/* weight interpolation */
prop = RNA_def_property(srna, "weight_interpolation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "weight_interp");