[Bf-blender-cvs] [f16a50ba946] soc-2020-greasepencil-curve: GPencil: Implement adaptive editcurve resolution
Falk David
noreply at git.blender.org
Wed Jul 22 16:11:33 CEST 2020
Commit: f16a50ba946ae4ddea18d4f7058fef3a359078b8
Author: Falk David
Date: Wed Jul 22 16:10:25 2020 +0200
Branches: soc-2020-greasepencil-curve
https://developer.blender.org/rBf16a50ba946ae4ddea18d4f7058fef3a359078b8
GPencil: Implement adaptive editcurve resolution
With adaptive curve resolution the arclength of a curve segment is
used to calculate the number of points between two control points.
This means that in general the stroke points are more spaced out.
===================================================================
M release/scripts/startup/bl_ui/space_view3d.py
M source/blender/blenkernel/BKE_gpencil_curve.h
M source/blender/blenkernel/intern/gpencil_curve.c
M source/blender/blenkernel/intern/gpencil_geom.c
M source/blender/editors/gpencil/gpencil_edit_curve.c
M source/blender/editors/gpencil/gpencil_select.c
M source/blender/editors/gpencil/gpencil_utils.c
M source/blender/makesdna/DNA_gpencil_types.h
M source/blender/makesrna/intern/rna_gpencil.c
===================================================================
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 007b8c933ce..0faca0b3413 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -6990,6 +6990,7 @@ class VIEW3D_PT_gpencil_curve_edit(Panel):
layout = self.layout
col = layout.column(align=True)
+ col.prop(gpd, "use_adaptive_curve_resolution")
col.prop(gpd, "edit_curve_resolution")
col.prop(gpd, "curve_edit_threshold")
diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h
index b066e901211..28791acc47a 100644
--- a/source/blender/blenkernel/BKE_gpencil_curve.h
+++ b/source/blender/blenkernel/BKE_gpencil_curve.h
@@ -50,7 +50,7 @@ void BKE_gpencil_editcurve_stroke_sync_selection(struct bGPDstroke *gps, struct
void BKE_gpencil_stroke_editcurve_sync_selection(struct bGPDstroke *gps, struct bGPDcurve *gpc);
void BKE_gpencil_strokes_selected_update_editcurve(struct bGPdata *gpd);
void BKE_gpencil_strokes_selected_sync_selection_editcurve(struct bGPdata *gpd);
-void BKE_gpencil_stroke_update_geometry_from_editcurve(struct bGPDstroke *gps);
+void BKE_gpencil_stroke_update_geometry_from_editcurve(struct bGPDstroke *gps, const uint resolution, bool is_adaptive);
void BKE_gpencil_editcurve_recalculate_handles(struct bGPDstroke *gps);
void BKE_gpencil_editcurve_subdivide(struct bGPDstroke *gps, const int cuts);
diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c
index eb3c78f2827..e38c79f3a0f 100644
--- a/source/blender/blenkernel/intern/gpencil_curve.c
+++ b/source/blender/blenkernel/intern/gpencil_curve.c
@@ -665,6 +665,7 @@ static void gpencil_interpolate_fl_from_to(
float *r = point_offset;
for (int i = 0; i <= it; i++) {
float fac = (float)i / (float)it;
+ // fac = 3.0f * fac * fac - 2.0f * fac * fac * fac; // smooth
*r = interpf(to, from, fac);
r = POINTER_OFFSET(r, stride);
}
@@ -677,12 +678,27 @@ static void gpencil_interpolate_v4_from_to(
float *r = point_offset;
for (int i = 0; i <= it; i++) {
float fac = (float)i / (float)it;
+ // fac = 3.0f * fac * fac - 2.0f * fac * fac * fac; // smooth
interp_v4_v4v4(r, from, to, fac);
r = POINTER_OFFSET(r, stride);
}
}
-static void gpencil_calculate_stroke_points_curve_point(
+static float gpencil_approximate_curve_segment_arclength(bGPDcurve_point *cpt_start,
+ bGPDcurve_point *cpt_end)
+{
+ BezTriple *bezt_start = &cpt_start->bezt;
+ BezTriple *bezt_end = &cpt_end->bezt;
+
+ float chord_len = len_v3v3(bezt_start->vec[1], bezt_end->vec[1]);
+ float net_len = len_v3v3(bezt_start->vec[1], bezt_start->vec[2]);
+ net_len += len_v3v3(bezt_start->vec[2], bezt_end->vec[0]);
+ net_len += len_v3v3(bezt_end->vec[0], bezt_end->vec[1]);
+
+ return (chord_len + net_len) / 2.0f;
+}
+
+static void gpencil_calculate_stroke_points_curve_segment(
bGPDcurve_point *cpt, bGPDcurve_point *cpt_next, float *points_offset, int resolu, int stride)
{
/* sample points on all 3 axis between two curve points */
@@ -714,51 +730,141 @@ static void gpencil_calculate_stroke_points_curve_point(
stride);
}
-/**
- * Recalculate stroke points with the editcurve of the stroke.
- */
-void BKE_gpencil_stroke_update_geometry_from_editcurve(bGPDstroke *gps)
+static float *gpencil_stroke_points_from_editcurve_adaptive_resolu(
+ bGPDcurve_point *curve_point_array,
+ int curve_point_array_len,
+ int resolution,
+ bool is_cyclic,
+ int *r_points_len)
{
- if (gps == NULL || gps->editcurve == NULL) {
- return;
+ /* One stride contains: x, y, z, pressure, strength, Vr, Vg, Vb, Vmix_factor */
+ const uint stride = sizeof(float[9]);
+ const uint cpt_last = curve_point_array_len - 1;
+ const uint num_segments = (is_cyclic) ? curve_point_array_len : curve_point_array_len - 1;
+ int *segment_point_lengths = MEM_callocN(sizeof(int) * num_segments, __func__);
+
+ uint points_len = 0;
+ for (int i = 0; i < cpt_last; i++) {
+ bGPDcurve_point *cpt = &curve_point_array[i];
+ bGPDcurve_point *cpt_next = &curve_point_array[i + 1];
+ float arclen = gpencil_approximate_curve_segment_arclength(cpt, cpt_next);
+ int segment_resolu = (int)floorf(arclen * resolution);
+
+ segment_point_lengths[i] = segment_resolu;
+ points_len += segment_resolu;
}
- bGPDcurve *editcurve = gps->editcurve;
- bGPDcurve_point *curve_point_array = editcurve->curve_points;
- int curve_point_array_len = editcurve->tot_curve_points;
- int resolu = editcurve->resolution;
- bool is_cyclic = gps->flag & GP_STROKE_CYCLIC;
+ if (is_cyclic) {
+ bGPDcurve_point *cpt = &curve_point_array[cpt_last];
+ bGPDcurve_point *cpt_next = &curve_point_array[0];
+ float arclen = gpencil_approximate_curve_segment_arclength(cpt, cpt_next);
+ int segment_resolu = (int)floorf(arclen * resolution);
- const uint array_last = curve_point_array_len - 1;
+ segment_point_lengths[cpt_last] = segment_resolu;
+ points_len += segment_resolu;
+ }
+ points_len += 1;
+
+ float(*r_points)[9] = MEM_callocN((stride * points_len * (is_cyclic ? 2 : 1)), __func__);
+ float *points_offset = &r_points[0][0];
+ int point_index = 0;
+ for (int i = 0; i < cpt_last; i++) {
+ bGPDcurve_point *cpt_curr = &curve_point_array[i];
+ bGPDcurve_point *cpt_next = &curve_point_array[i + 1];
+ int segment_resolu = segment_point_lengths[i];
+ gpencil_calculate_stroke_points_curve_segment(
+ cpt_curr, cpt_next, points_offset, segment_resolu, stride);
+ /* update the index */
+ cpt_curr->point_index = point_index;
+ point_index += segment_resolu;
+ points_offset = POINTER_OFFSET(points_offset, segment_resolu * stride);
+ }
+
+ bGPDcurve_point *cpt_curr = &curve_point_array[cpt_last];
+ cpt_curr->point_index = point_index;
+ if (is_cyclic) {
+ bGPDcurve_point *cpt_next = &curve_point_array[0];
+ int segment_resolu = segment_point_lengths[cpt_last];
+ gpencil_calculate_stroke_points_curve_segment(
+ cpt_curr, cpt_next, points_offset, segment_resolu, stride);
+ }
+
+ MEM_freeN(segment_point_lengths);
+
+ *r_points_len = points_len;
+ return (float(*))r_points;
+}
+
+/**
+ * Helper: calculate the points on a curve with a fixed resolution.
+ */
+static float *gpencil_stroke_points_from_editcurve_fixed_resolu(bGPDcurve_point *curve_point_array,
+ int curve_point_array_len,
+ int resolution,
+ bool is_cyclic,
+ int *r_points_len)
+{
/* One stride contains: x, y, z, pressure, strength, Vr, Vg, Vb, Vmix_factor */
const uint stride = sizeof(float[9]);
- const uint resolu_stride = resolu * stride;
+ const uint array_last = curve_point_array_len - 1;
+ const uint resolu_stride = resolution * stride;
const uint points_len = BKE_curve_calc_coords_axis_len(
- curve_point_array_len, resolu, is_cyclic, false);
+ curve_point_array_len, resolution, is_cyclic, false);
- float(*points)[9] = MEM_callocN((stride * points_len * (is_cyclic ? 2 : 1)), __func__);
- float *points_offset = &points[0][0];
+ float(*r_points)[9] = MEM_callocN((stride * points_len * (is_cyclic ? 2 : 1)), __func__);
+ float *points_offset = &r_points[0][0];
for (unsigned int i = 0; i < array_last; i++) {
bGPDcurve_point *cpt_curr = &curve_point_array[i];
bGPDcurve_point *cpt_next = &curve_point_array[i + 1];
- gpencil_calculate_stroke_points_curve_point(cpt_curr, cpt_next, points_offset, resolu, stride);
+ gpencil_calculate_stroke_points_curve_segment(
+ cpt_curr, cpt_next, points_offset, resolution, stride);
/* update the index */
- cpt_curr->point_index = i * resolu;
+ cpt_curr->point_index = i * resolution;
points_offset = POINTER_OFFSET(points_offset, resolu_stride);
}
+ bGPDcurve_point *cpt_curr = &curve_point_array[array_last];
+ cpt_curr->point_index = array_last * resolution;
if (is_cyclic) {
- bGPDcurve_point *cpt_curr = &curve_point_array[array_last];
bGPDcurve_point *cpt_next = &curve_point_array[0];
+ gpencil_calculate_stroke_points_curve_segment(
+ cpt_curr, cpt_next, points_offset, resolution, stride);
+ }
+
+ *r_points_len = points_len;
+ return (float(*))r_points;
+}
+
+/**
+ * Recalculate stroke points with the editcurve of the stroke.
+ */
+void BKE_gpencil_stroke_update_geometry_from_editcurve(bGPDstroke *gps,
+ const uint resolution,
+ bool adaptive)
+{
+ if (gps == NULL || gps->editcurve == NULL) {
+ return;
+ }
- gpencil_calculate_stroke_points_curve_point(cpt_curr, cpt_next, points_offset, resolu, stride);
+ bGPDcurve *editcurve = gps->editcurve;
+ bGPDcurve_point *curve_point_array = editcurve->curve_points;
+ int curve_point_array_len = editcurve->tot_curve_points;
+ bool is_cyclic = gps->flag & GP_STROKE_CYCLIC;
- cpt_curr->point_index = array_last * resolu;
+ int points_len = 0;
+ float(*points)[9] = NULL;
+ if (adaptive) {
+ points = (float(*)[9])gpencil_stroke_points_from_editcurve_adaptive_resolu(
+ curve_point_array, curve_point_array_len, resolution, is_cyclic, &points_len);
}
else {
- bGPDcurve_point *cpt_curr = &curve_point_array[array_last];
- cpt_curr->point_index = array_last * resolu;
+ points = (float(*)[9])gpencil_stroke_points_from_editcurve_fixed_resolu(
+ curve_point_array, curve_point_array_len, resolution, is_cyclic, &points_len);
+ }
+
+ if (points == NULL || points_len == 0) {
+ return;
}
/* resize stroke point array */
@@ -1012,7 +1118,7 @@ void BKE_gpencil_strokes_selected_update_editcurve(bGPdata *gpd)
if (!(gps->flag & GP_STROKE_SELECT)) {
continue;
}
-
+
/
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list