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.cc')
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc157
1 files changed, 100 insertions, 57 deletions
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index 365171b300f..865bcebee25 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);
@@ -2052,27 +2098,30 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
MDeformVert *dvert_final = nullptr;
MDeformVert *dvert_next = nullptr;
int totnewpoints, oldtotpoints;
- int i2;
+
+ bool cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
for (int s = 0; s < level; s++) {
- totnewpoints = gps->totpoints - 1;
+ totnewpoints = gps->totpoints;
+ if (!cyclic) {
+ totnewpoints--;
+ }
/* duplicate points in a temp area */
- temp_points = (bGPDspoint *)MEM_dupallocN(gps->points);
+ temp_points = gps->points;
oldtotpoints = gps->totpoints;
/* resize the points arrays */
gps->totpoints += totnewpoints;
- gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ gps->points = (bGPDspoint *)MEM_malloc_arrayN(gps->totpoints, sizeof(*gps->points), __func__);
if (gps->dvert != nullptr) {
- temp_dverts = (MDeformVert *)MEM_dupallocN(gps->dvert);
- gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ temp_dverts = gps->dvert;
+ gps->dvert = (MDeformVert *)MEM_malloc_arrayN(gps->totpoints, sizeof(*gps->dvert), __func__);
}
/* move points from last to first to new place */
- i2 = gps->totpoints - 1;
- for (int i = oldtotpoints - 1; i > 0; i--) {
+ for (int i = 0; i < oldtotpoints; i++) {
bGPDspoint *pt = &temp_points[i];
- bGPDspoint *pt_final = &gps->points[i2];
+ bGPDspoint *pt_final = &gps->points[i * 2];
copy_v3_v3(&pt_final->x, &pt->x);
pt_final->pressure = pt->pressure;
@@ -2085,18 +2134,16 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
if (gps->dvert != nullptr) {
dvert = &temp_dverts[i];
- dvert_final = &gps->dvert[i2];
+ dvert_final = &gps->dvert[i * 2];
dvert_final->totweight = dvert->totweight;
dvert_final->dw = dvert->dw;
}
- i2 -= 2;
}
/* interpolate mid points */
- i2 = 1;
- for (int i = 0; i < oldtotpoints - 1; i++) {
- bGPDspoint *pt = &temp_points[i];
- bGPDspoint *next = &temp_points[i + 1];
- bGPDspoint *pt_final = &gps->points[i2];
+ for (int i = cyclic ? 0 : 1, j = cyclic ? oldtotpoints - 1 : 0; i < oldtotpoints; j = i, i++) {
+ bGPDspoint *pt = &temp_points[j];
+ bGPDspoint *next = &temp_points[i];
+ bGPDspoint *pt_final = &gps->points[j * 2 + 1];
/* add a half way point */
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
@@ -2109,9 +2156,9 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
if (gps->dvert != nullptr) {
- dvert = &temp_dverts[i];
- dvert_next = &temp_dverts[i + 1];
- dvert_final = &gps->dvert[i2];
+ dvert = &temp_dverts[j];
+ dvert_next = &temp_dverts[i];
+ dvert_final = &gps->dvert[j * 2 + 1];
dvert_final->totweight = dvert->totweight;
dvert_final->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw);
@@ -2126,8 +2173,6 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
}
}
}
-
- i2 += 2;
}
MEM_SAFE_FREE(temp_points);
@@ -2135,20 +2180,18 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
/* Move points to smooth stroke (not simple type). */
if (type != GP_SUBDIV_SIMPLE) {
- /* duplicate points in a temp area with the new subdivide data */
- temp_points = (bGPDspoint *)MEM_dupallocN(gps->points);
-
+ float mid[3];
/* extreme points are not changed */
- for (int i = 0; i < gps->totpoints - 2; i++) {
- bGPDspoint *pt = &temp_points[i];
- bGPDspoint *next = &temp_points[i + 1];
- bGPDspoint *pt_final = &gps->points[i + 1];
+ for (int i = cyclic ? 0 : 2, j = cyclic ? gps->totpoints - 2 : 0; i < gps->totpoints - 2;
+ j = i, i += 2) {
+ bGPDspoint *prev = &gps->points[j + 1];
+ bGPDspoint *pt = &gps->points[i];
+ bGPDspoint *next = &gps->points[i + 1];
/* move point */
- interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
+ interp_v3_v3v3(mid, &prev->x, &next->x, 0.5f);
+ interp_v3_v3v3(&pt->x, mid, &pt->x, 0.5f);
}
- /* free temp memory */
- MEM_SAFE_FREE(temp_points);
}
}