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:
Diffstat (limited to 'source/blender/blenkernel/intern/gpencil_geom.c')
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.c273
1 files changed, 178 insertions, 95 deletions
diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c
index 4dcd94fdeec..be5a148f6f9 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.c
+++ b/source/blender/blenkernel/intern/gpencil_geom.c
@@ -523,7 +523,7 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist,
gps->totpoints = i;
/* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
return true;
}
@@ -708,7 +708,7 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd,
* Keep the end point. */
BKE_gpencil_stroke_trim_points(gps, 0, old_count);
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
return true;
}
@@ -1376,29 +1376,25 @@ void BKE_gpencil_stroke_uv_update(bGPDstroke *gps)
* Recalc all internal geometry data for the stroke
* \param gpd: Grease pencil data-block
* \param gps: Grease pencil stroke
+ * \param flag: eGPStrokeGeoUpdateFlag flag (use GP_GEO_UPDATE_DEFAULT=0 for the default)
*/
-void BKE_gpencil_stroke_geometry_update(bGPdata *gpd, bGPDstroke *gps)
+void BKE_gpencil_stroke_geometry_update(bGPdata *gpd,
+ bGPDstroke *gps,
+ const eGPStrokeGeoUpdateFlag flag)
{
if (gps == NULL) {
return;
}
- if (gps->editcurve != NULL) {
- if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
- /* curve geometry was updated: stroke needs recalculation */
- if (gps->flag & GP_STROKE_NEEDS_CURVE_UPDATE) {
- bool is_adaptive = gpd->flag & GP_DATA_CURVE_ADAPTIVE_RESOLUTION;
- BKE_gpencil_stroke_update_geometry_from_editcurve(
- gps, gpd->curve_edit_resolution, is_adaptive);
- gps->flag &= ~GP_STROKE_NEEDS_CURVE_UPDATE;
- }
- }
- else {
- /* stroke geometry was updated: editcurve needs recalculation */
- gps->editcurve->flag |= GP_CURVE_NEEDS_STROKE_UPDATE;
- }
+ /* Update curve points first if it's a bezier stroke. */
+ if (GPENCIL_STROKE_TYPE_BEZIER(gps) && GP_GEO_UPDATE_POLYLINE_REGENERATE_ANY(flag)) {
+ /* Regenerate the polyline points from the curve data. */
+ const uint resolution = gpd->curve_edit_resolution;
+ const bool is_adaptive = gpd->flag & GP_DATA_CURVE_ADAPTIVE_RESOLUTION;
+ BKE_gpencil_stroke_update_geometry_from_editcurve(gps, resolution, is_adaptive, flag);
}
+ /* Triangulate the stroke. */
if (gps->totpoints > 2) {
BKE_gpencil_stroke_fill_triangulate(gps);
}
@@ -1407,7 +1403,7 @@ void BKE_gpencil_stroke_geometry_update(bGPdata *gpd, bGPDstroke *gps)
MEM_SAFE_FREE(gps->triangles);
}
- /* calc uv data along the stroke */
+ /* Calc UV data along the stroke. */
BKE_gpencil_stroke_uv_update(gps);
/* Calc stroke bounding box. */
@@ -1559,7 +1555,7 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps)
MEM_SAFE_FREE(old_dvert);
}
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
return intersect;
}
@@ -1736,7 +1732,7 @@ void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps,
gps->totpoints = tot;
/* triangles cache needs to be recalculated */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
}
}
@@ -1884,7 +1880,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e
gps->totpoints = j;
/* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
MEM_SAFE_FREE(old_points);
MEM_SAFE_FREE(old_dvert);
@@ -1950,7 +1946,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
gps->totpoints = j;
/* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
MEM_SAFE_FREE(old_points);
MEM_SAFE_FREE(old_dvert);
@@ -2072,7 +2068,7 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
}
/* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
}
/* Merge by distance ------------------------------------- */
@@ -2157,7 +2153,7 @@ void BKE_gpencil_stroke_merge_distance(bGPdata *gpd,
}
/* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
}
typedef struct GpEdge {
@@ -2372,7 +2368,7 @@ static void gpencil_generate_edgeloops(Object *ob,
pt->strength = 1.0f;
}
- BKE_gpencil_stroke_geometry_update(gpd, gps_stroke);
+ BKE_gpencil_stroke_geometry_update(gpd, gps_stroke, GP_GEO_UPDATE_DEFAULT);
}
/* Free memory. */
@@ -2557,7 +2553,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
BKE_gpencil_stroke_subdivide(gpd, gps_fill, 1, GP_SUBDIV_SIMPLE);
}
- BKE_gpencil_stroke_geometry_update(gpd, gps_fill);
+ BKE_gpencil_stroke_geometry_update(gpd, gps_fill, GP_GEO_UPDATE_DEFAULT);
}
}
}
@@ -2614,7 +2610,7 @@ void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4])
}
/* Distortion may mean we need to re-triangulate. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
}
}
}
@@ -2706,7 +2702,7 @@ void BKE_gpencil_point_coords_apply(bGPdata *gpd, const GPencilPointCoordinates
}
/* Distortion may mean we need to re-triangulate. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
}
}
}
@@ -2743,7 +2739,7 @@ void BKE_gpencil_point_coords_apply_with_mat4(bGPdata *gpd,
}
/* Distortion may mean we need to re-triangulate. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
}
}
}
@@ -2768,49 +2764,108 @@ void BKE_gpencil_stroke_set_random_color(bGPDstroke *gps)
}
}
+static void gpencil_flip_beztriple(BezTriple *bezt)
+{
+ /* Flip handle position. */
+ float tmp[3];
+ copy_v3_v3(tmp, bezt->vec[0]);
+ copy_v3_v3(bezt->vec[0], bezt->vec[2]);
+ copy_v3_v3(bezt->vec[2], tmp);
+
+ /* Flip type and slection flag. */
+ SWAP(uint8_t, bezt->h1, bezt->h2);
+ SWAP(uint8_t, bezt->f1, bezt->f3);
+}
+
/* Flip stroke. */
void BKE_gpencil_stroke_flip(bGPDstroke *gps)
{
- int end = gps->totpoints - 1;
-
- for (int i = 0; i < gps->totpoints / 2; i++) {
- bGPDspoint *point, *point2;
- bGPDspoint pt;
-
- /* save first point */
- point = &gps->points[i];
- pt.x = point->x;
- pt.y = point->y;
- pt.z = point->z;
- pt.flag = point->flag;
- pt.pressure = point->pressure;
- pt.strength = point->strength;
- pt.time = point->time;
- copy_v4_v4(pt.vert_color, point->vert_color);
-
- /* replace first point with last point */
- point2 = &gps->points[end];
- point->x = point2->x;
- point->y = point2->y;
- point->z = point2->z;
- point->flag = point2->flag;
- point->pressure = point2->pressure;
- point->strength = point2->strength;
- point->time = point2->time;
- copy_v4_v4(point->vert_color, point2->vert_color);
-
- /* replace last point with first saved before */
- point = &gps->points[end];
- point->x = pt.x;
- point->y = pt.y;
- point->z = pt.z;
- point->flag = pt.flag;
- point->pressure = pt.pressure;
- point->strength = pt.strength;
- point->time = pt.time;
- copy_v4_v4(point->vert_color, pt.vert_color);
-
- end--;
+ if (GPENCIL_STROKE_TYPE_BEZIER(gps)) {
+ bGPDcurve *gpc = gps->editcurve;
+
+ int end = gpc->tot_curve_points - 1;
+ for (int i = 0; i < gpc->tot_curve_points / 2; i++) {
+ bGPDcurve_point *cpt_first = &gpc->curve_points[i];
+ bGPDcurve_point *cpt_last = &gpc->curve_points[end];
+ bGPDcurve_point temp;
+
+ memcpy(&temp.bezt, &cpt_first->bezt, sizeof(BezTriple));
+ temp.pressure = cpt_first->pressure;
+ temp.strength = cpt_first->strength;
+ temp.point_index = cpt_first->point_index;
+ temp.flag = cpt_first->flag;
+ temp.uv_fac = cpt_first->uv_fac;
+ temp.uv_rot = cpt_first->uv_rot;
+ copy_v2_v2(temp.uv_fill, cpt_first->uv_fill);
+ copy_v4_v4(temp.vert_color, cpt_first->vert_color);
+
+ memcpy(&cpt_first->bezt, &cpt_last->bezt, sizeof(BezTriple));
+ gpencil_flip_beztriple(&cpt_first->bezt);
+ cpt_first->pressure = cpt_last->pressure;
+ cpt_first->strength = cpt_last->strength;
+ cpt_first->point_index = cpt_last->point_index;
+ cpt_first->flag = cpt_last->flag;
+ cpt_first->uv_fac = cpt_last->uv_fac;
+ cpt_first->uv_rot = cpt_last->uv_rot;
+ copy_v2_v2(cpt_first->uv_fill, cpt_last->uv_fill);
+ copy_v4_v4(cpt_first->vert_color, cpt_last->vert_color);
+
+ memcpy(&cpt_last->bezt, &temp.bezt, sizeof(BezTriple));
+ gpencil_flip_beztriple(&cpt_last->bezt);
+ cpt_last->pressure = temp.pressure;
+ cpt_last->strength = temp.strength;
+ cpt_last->point_index = temp.point_index;
+ cpt_last->flag = temp.flag;
+ cpt_last->uv_fac = temp.uv_fac;
+ cpt_last->uv_rot = temp.uv_rot;
+ copy_v2_v2(cpt_last->uv_fill, temp.uv_fill);
+ copy_v4_v4(cpt_last->vert_color, temp.vert_color);
+
+ end--;
+ }
+ }
+ else {
+ int end = gps->totpoints - 1;
+
+ for (int i = 0; i < gps->totpoints / 2; i++) {
+ bGPDspoint *point, *point2;
+ bGPDspoint pt;
+
+ /* save first point */
+ point = &gps->points[i];
+ pt.x = point->x;
+ pt.y = point->y;
+ pt.z = point->z;
+ pt.flag = point->flag;
+ pt.pressure = point->pressure;
+ pt.strength = point->strength;
+ pt.time = point->time;
+ copy_v4_v4(pt.vert_color, point->vert_color);
+
+ /* replace first point with last point */
+ point2 = &gps->points[end];
+ point->x = point2->x;
+ point->y = point2->y;
+ point->z = point2->z;
+ point->flag = point2->flag;
+ point->pressure = point2->pressure;
+ point->strength = point2->strength;
+ point->time = point2->time;
+ copy_v4_v4(point->vert_color, point2->vert_color);
+
+ /* replace last point with first saved before */
+ point = &gps->points[end];
+ point->x = pt.x;
+ point->y = pt.y;
+ point->z = pt.z;
+ point->flag = pt.flag;
+ point->pressure = pt.pressure;
+ point->strength = pt.strength;
+ point->time = pt.time;
+ copy_v4_v4(point->vert_color, pt.vert_color);
+
+ end--;
+ }
}
}
@@ -2901,7 +2956,7 @@ static void gpencil_stroke_join_islands(bGPdata *gpd,
/* add new stroke at head */
BLI_addhead(&gpf->strokes, join_stroke);
/* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, join_stroke);
+ BKE_gpencil_stroke_geometry_update(gpd, join_stroke, GP_GEO_UPDATE_DEFAULT);
/* remove first stroke */
BLI_remlink(&gpf->strokes, gps_first);
@@ -3053,7 +3108,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
}
else {
/* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, new_stroke);
+ BKE_gpencil_stroke_geometry_update(gpd, new_stroke, GP_GEO_UPDATE_DEFAULT);
if (next_stroke) {
BLI_insertlinkbefore(&gpf->strokes, next_stroke, new_stroke);
@@ -3137,10 +3192,10 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd,
sizeof(bGPDcurve_point) * island_length);
BKE_gpencil_editcurve_recalculate_handles(new_stroke);
- new_stroke->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
+ BKE_gpencil_curve_sync_selection(gpd, new_stroke);
/* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, new_stroke);
+ BKE_gpencil_stroke_geometry_update(gpd, new_stroke, GP_GEO_UPDATE_DEFAULT);
if (next_stroke) {
BLI_insertlinkbefore(&gpf->strokes, next_stroke, new_stroke);
@@ -3170,10 +3225,10 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd,
sizeof(bGPDcurve_point) * first_tot_points);
BKE_gpencil_editcurve_recalculate_handles(gps_last);
- gps_last->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
+ BKE_gpencil_curve_sync_selection(gpd, gps_last);
/* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gpd, gps_last);
+ BKE_gpencil_stroke_geometry_update(gpd, gps_last, GP_GEO_UPDATE_DEFAULT);
/* remove first one */
BLI_remlink(&gpf->strokes, gps_first);
@@ -3241,7 +3296,6 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
{
bGPDspoint point;
bGPDspoint *pt;
- int i;
const float delta[3] = {1.0f, 1.0f, 1.0f};
float deltatime = 0.0f;
@@ -3250,6 +3304,11 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
return;
}
+ /* Cannot join strokes of different types for now... */
+ if (GPENCIL_STROKE_TYPE_BEZIER(gps_a) != GPENCIL_STROKE_TYPE_BEZIER(gps_b)) {
+ return;
+ }
+
if ((gps_a->totpoints == 0) || (gps_b->totpoints == 0)) {
return;
}
@@ -3302,28 +3361,52 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
BKE_gpencil_stroke_flip(gps_b);
}
- /* don't visibly link the first and last points? */
- if (leave_gaps) {
- /* 1st: add one tail point to start invisible area */
- point = gps_a->points[gps_a->totpoints - 1];
- deltatime = point.time;
+ const float thickness_ratio = (fit_thickness && gps_a->thickness > 0.0f) ?
+ (float)gps_b->thickness / (float)gps_a->thickness :
+ 1.0f;
+
+ if (GPENCIL_STROKE_TYPE_BEZIER(gps_a)) {
+ /* TODO: Support leave gaps. */
+ bGPDcurve *gpc_a = gps_a->editcurve;
+ bGPDcurve *gpc_b = gps_b->editcurve;
- gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, 0.0f);
+ int old_num_points = gpc_a->tot_curve_points;
+ gpc_a->tot_curve_points += gpc_b->tot_curve_points;
+ gpc_a->curve_points = MEM_recallocN(gpc_a->curve_points,
+ sizeof(bGPDcurve_point) * gpc_a->tot_curve_points);
- /* 2nd: add one head point to finish invisible area */
- point = gps_b->points[0];
- gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, deltatime);
+ memcpy(gpc_a->curve_points + old_num_points,
+ gpc_b->curve_points,
+ sizeof(bGPDcurve_point) * gpc_b->tot_curve_points);
+ /* TODO: copy dvert curve data. */
+
+ /* Rescale other points. */
+ for (int i = old_num_points; i < gpc_a->tot_curve_points; i++) {
+ bGPDcurve_point *cpt = &gpc_a->curve_points[i];
+ cpt->pressure *= thickness_ratio;
+ }
}
+ else {
+ /* don't visibly link the first and last points? */
+ if (leave_gaps) {
+ /* 1st: add one tail point to start invisible area */
+ point = gps_a->points[gps_a->totpoints - 1];
+ deltatime = point.time;
- const float ratio = (fit_thickness && gps_a->thickness > 0.0f) ?
- (float)gps_b->thickness / (float)gps_a->thickness :
- 1.0f;
+ gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, 0.0f);
- /* 3rd: add all points */
- for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) {
- MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : NULL;
- gpencil_stroke_copy_point(
- gps_a, dvert, pt, delta, pt->pressure * ratio, pt->strength, deltatime);
+ /* 2nd: add one head point to finish invisible area */
+ point = gps_b->points[0];
+ gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, deltatime);
+ }
+
+ /* 3rd: add all points */
+ for (int i = 0; i < gps_b->totpoints && pt; i++) {
+ pt = &gps_b->points[i];
+ MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : NULL;
+ gpencil_stroke_copy_point(
+ gps_a, dvert, pt, delta, pt->pressure * thickness_ratio, pt->strength, deltatime);
+ }
}
}
@@ -3556,7 +3639,7 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
}
/* Update the geometry of the stroke. */
- BKE_gpencil_stroke_geometry_update(gpd, gps);
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
}
/**
@@ -4067,7 +4150,7 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
MEM_freeN(perimeter_points);
/* Triangles cache needs to be recalculated. */
- BKE_gpencil_stroke_geometry_update(gpd, perimeter_stroke);
+ BKE_gpencil_stroke_geometry_update(gpd, perimeter_stroke, GP_GEO_UPDATE_DEFAULT);
perimeter_stroke->flag |= GP_STROKE_SELECT | GP_STROKE_CYCLIC;