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
diff options
context:
space:
mode:
authorYimingWu <xp8110@outlook.com>2022-02-22 07:54:35 +0300
committerYimingWu <xp8110@outlook.com>2022-02-22 07:54:35 +0300
commit2234bfbcdb14299aa2ed28ed3ee6682c6d9a7a0c (patch)
tree909692b6362d5c49e0908f397e78ceeb409da985
parent0f2e0a25e13d2d67f3d08d068ba11e255794bb6b (diff)
GPencil: Simplify sample modifier improvements.
1. Now handles cyclic strokes correctly. 2. Added a sharp threshold value to allow preservation of sharp corners. Reviewed By: Antonio Vazquez (antoniov), Aleš Jelovčan (frogstomp) Ref D14044
-rw-r--r--source/blender/blenkernel/BKE_gpencil_geom.h6
-rw-r--r--source/blender/blenkernel/intern/gpencil_curve.c2
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc98
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_trace_utils.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c3
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc2
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_svg.cc2
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c8
10 files changed, 94 insertions, 35 deletions
diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h
index eb61bd32eee..4127030e96f 100644
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@ -208,11 +208,13 @@ void BKE_gpencil_point_coords_apply_with_mat4(struct bGPdata *gpd,
* \param gpd: Grease pencil data-block
* \param gps: Stroke to sample
* \param dist: Distance of one segment
+ * \param sharp_threshold: Threshold for preserving sharp corners
*/
bool BKE_gpencil_stroke_sample(struct bGPdata *gpd,
struct bGPDstroke *gps,
- float dist,
- bool select);
+ const float dist,
+ const bool select,
+ const float sharp_threshold);
/**
* Apply smooth position to stroke point.
* \param gps: Stroke to smooth
diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c
index 5ce45f6df5a..ee6b77e6463 100644
--- a/source/blender/blenkernel/intern/gpencil_curve.c
+++ b/source/blender/blenkernel/intern/gpencil_curve.c
@@ -443,7 +443,7 @@ static void gpencil_convert_spline(Main *bmain,
}
if (sample > 0.0f) {
- BKE_gpencil_stroke_sample(gpd, gps, sample, false);
+ BKE_gpencil_stroke_sample(gpd, gps, sample, false, 0);
}
/* Recalc fill geometry. */
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index 365171b300f..1823d84d48d 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -202,8 +202,8 @@ static int stroke_march_next_point(const bGPDstroke *gps,
int next_point_index = index_next_pt;
bGPDspoint *pt = nullptr;
- if (!(next_point_index < gps->totpoints)) {
- return -1;
+ if (next_point_index == gps->totpoints) {
+ next_point_index = 0;
}
copy_v3_v3(step_start, current);
@@ -211,15 +211,33 @@ static int stroke_march_next_point(const bGPDstroke *gps,
copy_v3_v3(point, &pt->x);
remaining_till_next = len_v3v3(point, step_start);
- while (remaining_till_next < remaining_march) {
+ while (remaining_till_next < remaining_march && next_point_index) {
remaining_march -= remaining_till_next;
pt = &gps->points[next_point_index];
+ if (pt->flag & GP_SPOINT_TEMP_TAG) {
+ pt = &gps->points[next_point_index];
+ copy_v3_v3(result, &pt->x);
+ *pressure = gps->points[next_point_index].pressure;
+ *strength = gps->points[next_point_index].strength;
+ memcpy(vert_color, gps->points[next_point_index].vert_color, sizeof(float[4]));
+
+ *index_from = next_point_index == 0 ? (gps->totpoints - 1) : (next_point_index - 1);
+ *index_to = next_point_index;
+ *ratio_result = 1.0f;
+ next_point_index++;
+ return next_point_index == 0 ? gps->totpoints : next_point_index;
+ }
+ next_point_index++;
copy_v3_v3(point, &pt->x);
copy_v3_v3(step_start, point);
- next_point_index++;
if (!(next_point_index < gps->totpoints)) {
- next_point_index = gps->totpoints - 1;
- break;
+ if (gps->flag & GP_STROKE_CYCLIC) {
+ next_point_index = 0;
+ }
+ else {
+ next_point_index = gps->totpoints - 1;
+ break;
+ }
}
pt = &gps->points[next_point_index];
copy_v3_v3(point, &pt->x);
@@ -232,35 +250,37 @@ static int stroke_march_next_point(const bGPDstroke *gps,
*strength = gps->points[next_point_index].strength;
memcpy(vert_color, gps->points[next_point_index].vert_color, sizeof(float[4]));
- *index_from = next_point_index - 1;
+ *index_from = next_point_index == 0 ? (gps->totpoints - 1) : (next_point_index - 1);
*index_to = next_point_index;
*ratio_result = 1.0f;
return 0;
}
+ *index_from = next_point_index == 0 ? (gps->totpoints - 1) : (next_point_index - 1);
+ *index_to = next_point_index;
+
float ratio = remaining_march / remaining_till_next;
interp_v3_v3v3(result, step_start, point, ratio);
+ *ratio_result = ratio;
+
*pressure = interpf(
- gps->points[next_point_index].pressure, gps->points[next_point_index - 1].pressure, ratio);
+ gps->points[next_point_index].pressure, gps->points[*index_from].pressure, ratio);
*strength = interpf(
- gps->points[next_point_index].strength, gps->points[next_point_index - 1].strength, ratio);
+ gps->points[next_point_index].strength, gps->points[*index_from].strength, ratio);
interp_v4_v4v4(vert_color,
- gps->points[next_point_index - 1].vert_color,
+ gps->points[*index_from].vert_color,
gps->points[next_point_index].vert_color,
ratio);
- *index_from = next_point_index - 1;
- *index_to = next_point_index;
- *ratio_result = ratio;
-
- return next_point_index;
+ return next_point_index == 0 ? gps->totpoints : next_point_index;
}
static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
const int index_next_pt,
const float *current,
const float dist,
+ const float sharp_threshold,
float *result)
{
float remaining_till_next = 0.0f;
@@ -270,8 +290,8 @@ static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
int next_point_index = index_next_pt;
bGPDspoint *pt = nullptr;
- if (!(next_point_index < gps->totpoints)) {
- return -1;
+ if (next_point_index == gps->totpoints) {
+ next_point_index = 0;
}
copy_v3_v3(step_start, current);
@@ -279,15 +299,29 @@ static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
copy_v3_v3(point, &pt->x);
remaining_till_next = len_v3v3(point, step_start);
- while (remaining_till_next < remaining_march) {
+ while (remaining_till_next < remaining_march && next_point_index) {
remaining_march -= remaining_till_next;
pt = &gps->points[next_point_index];
+ if (next_point_index < gps->totpoints - 1 &&
+ angle_v3v3v3(&gps->points[next_point_index - 1].x,
+ &gps->points[next_point_index].x,
+ &gps->points[next_point_index + 1].x) < sharp_threshold) {
+ copy_v3_v3(result, &pt->x);
+ pt->flag |= GP_SPOINT_TEMP_TAG;
+ next_point_index++;
+ return next_point_index == 0 ? gps->totpoints : next_point_index;
+ }
+ next_point_index++;
copy_v3_v3(point, &pt->x);
copy_v3_v3(step_start, point);
- next_point_index++;
if (!(next_point_index < gps->totpoints)) {
- next_point_index = gps->totpoints - 1;
- break;
+ if (gps->flag & GP_STROKE_CYCLIC) {
+ next_point_index = 0;
+ }
+ else {
+ next_point_index = gps->totpoints - 1;
+ break;
+ }
}
pt = &gps->points[next_point_index];
copy_v3_v3(point, &pt->x);
@@ -296,15 +330,16 @@ static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
if (remaining_till_next < remaining_march) {
pt = &gps->points[next_point_index];
copy_v3_v3(result, &pt->x);
+ /* Stroke marching only terminates here. */
return 0;
}
float ratio = remaining_march / remaining_till_next;
interp_v3_v3v3(result, step_start, point, ratio);
- return next_point_index;
+ return next_point_index == 0 ? gps->totpoints : next_point_index;
}
-static int stroke_march_count(const bGPDstroke *gps, const float dist)
+static int stroke_march_count(const bGPDstroke *gps, const float dist, const float sharp_threshold)
{
int point_count = 0;
float point[3];
@@ -315,8 +350,13 @@ static int stroke_march_count(const bGPDstroke *gps, const float dist)
copy_v3_v3(point, &pt->x);
point_count++;
+ /* Sharp points will be tagged by the stroke_march_next_point_no_interp() call below. */
+ for (int i = 0; i < gps->totpoints; i++) {
+ gps->points[i].flag &= (~GP_SPOINT_TEMP_TAG);
+ }
+
while ((next_point_index = stroke_march_next_point_no_interp(
- gps, next_point_index, point, dist, point)) > -1) {
+ gps, next_point_index, point, dist, sharp_threshold, point)) > -1) {
point_count++;
if (next_point_index == 0) {
break; /* last point finished */
@@ -394,7 +434,11 @@ static void stroke_interpolate_deform_weights(
}
}
-bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, const bool select)
+bool BKE_gpencil_stroke_sample(bGPdata *gpd,
+ bGPDstroke *gps,
+ const float dist,
+ const bool select,
+ const float sharp_threshold)
{
bGPDspoint *pt = gps->points;
bGPDspoint *pt1 = nullptr;
@@ -406,7 +450,7 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist,
return false;
}
/* TODO: Implement feature point preservation. */
- int count = stroke_march_count(gps, dist);
+ int count = stroke_march_count(gps, dist, sharp_threshold);
bGPDspoint *new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * count,
"gp_stroke_points_sampled");
@@ -491,6 +535,8 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist,
gps->totpoints = i;
+ gps->flag &= (~GP_STROKE_CYCLIC);
+
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gpd, gps);
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 680b313c47b..d734fb2678e 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -4356,6 +4356,7 @@ static int gpencil_stroke_sample_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
const float length = RNA_float_get(op->ptr, "length");
+ const float sharp_threshold = RNA_float_get(op->ptr, "sharp_threshold");
/* sanity checks */
if (ELEM(NULL, gpd)) {
@@ -4365,7 +4366,7 @@ static int gpencil_stroke_sample_exec(bContext *C, wmOperator *op)
/* Go through each editable + selected stroke */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
- BKE_gpencil_stroke_sample(gpd, gps, length, true);
+ BKE_gpencil_stroke_sample(gpd, gps, length, true, sharp_threshold);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
diff --git a/source/blender/editors/gpencil/gpencil_trace_utils.c b/source/blender/editors/gpencil/gpencil_trace_utils.c
index 10be8c3e91e..735759d40ec 100644
--- a/source/blender/editors/gpencil/gpencil_trace_utils.c
+++ b/source/blender/editors/gpencil/gpencil_trace_utils.c
@@ -314,7 +314,7 @@ void ED_gpencil_trace_data_to_strokes(Main *bmain,
if (sample > 0.0f) {
/* Resample stroke. Don't need to call to BKE_gpencil_stroke_geometry_update() because
* the sample function already call that. */
- BKE_gpencil_stroke_sample(gpd, gps, sample, false);
+ BKE_gpencil_stroke_sample(gpd, gps, sample, false, 0);
}
else {
BKE_gpencil_stroke_geometry_update(gpd, gps);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
index 3b7b82e3085..365b9afe348 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
@@ -88,7 +88,7 @@ static void deformStroke(GpencilModifierData *md,
break;
}
case GP_SIMPLIFY_SAMPLE: {
- BKE_gpencil_stroke_sample(gpd, gps, mmd->length, false);
+ BKE_gpencil_stroke_sample(gpd, gps, mmd->length, false, mmd->sharp_threshold);
break;
}
case GP_SIMPLIFY_MERGE: {
@@ -143,6 +143,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
}
else if (mode == GP_SIMPLIFY_SAMPLE) {
uiItemR(layout, ptr, "length", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "sharp_threshold", 0, NULL, ICON_NONE);
}
else if (mode == GP_SIMPLIFY_MERGE) {
uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
index 3c4676beb75..cc3eab02e07 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
@@ -196,7 +196,7 @@ void GpencilExporterPDF::export_gpencil_layers()
/* Sample stroke. */
if (params_.stroke_sample > 0.0f) {
- BKE_gpencil_stroke_sample(gpd_eval, gps_perimeter, params_.stroke_sample, false);
+ BKE_gpencil_stroke_sample(gpd_eval, gps_perimeter, params_.stroke_sample, false, 0);
}
export_stroke_to_polyline(gpl, gps_perimeter, is_stroke, false, false);
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
index d21af4c09eb..f8d30546e39 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
@@ -221,7 +221,7 @@ void GpencilExporterSVG::export_gpencil_layers()
/* Sample stroke. */
if (params_.stroke_sample > 0.0f) {
- BKE_gpencil_stroke_sample(gpd_eval, gps_perimeter, params_.stroke_sample, false);
+ BKE_gpencil_stroke_sample(gpd_eval, gps_perimeter, params_.stroke_sample, false, 0);
}
export_stroke_to_path(gpl, gps_perimeter, node_gpl, false);
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 64099de5a5e..e30dd4e1c8f 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -649,9 +649,10 @@ typedef struct SimplifyGpencilModifierData {
int layer_pass;
/** Sample length */
float length;
+ /** Sample sharp threshold */
+ float sharp_threshold;
/** Merge distance */
float distance;
- char _pad[4];
} SimplifyGpencilModifierData;
typedef enum eSimplifyGpencil_Flag {
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 9c755bbb053..a619d179a33 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -1223,6 +1223,14 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Length", "Length of each segment");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "sharp_threshold", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "sharp_threshold");
+ RNA_def_property_range(prop, 0, M_PI);
+ RNA_def_property_ui_range(prop, 0, M_PI, 1.0, 1);
+ RNA_def_property_ui_text(
+ prop, "Sharp Threshold", "Preserve corners that have sharper angle than this threshold");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
/* Merge */
prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "distance");