GP: Improve Subdivide and Simplify

Now the weights are managed in the operators.

The subdivide operator and modifier code have been replaced with a shared function.

Some cleanup also.
This commit is contained in:
Antonioya 2018-08-30 11:06:44 +02:00
parent 3071d67c3a
commit 0845b1c8c8
6 changed files with 171 additions and 213 deletions

View File

@ -162,6 +162,7 @@ void BKE_gpencil_eval_geometry(struct Depsgraph *depsgraph, struct bGPdata *gpd)
void BKE_gpencil_stroke_normal(const struct bGPDstroke *gps, float r_normal[3]);
void BKE_gpencil_simplify_stroke(struct bGPDstroke *gps, float factor);
void BKE_gpencil_simplify_fixed(struct bGPDstroke *gps);
void BKE_gpencil_subdivide(struct bGPDstroke *gps, int level, int flag);
void BKE_gpencil_transform(struct bGPdata *gpd, float mat[4][4]);

View File

@ -241,6 +241,9 @@ static void gpencil_rdp_stroke(bGPDstroke *gps, vec2f *points2d, float epsilon)
dvert_src = &old_dvert[i];
MDeformVert *dvert = &gps->dvert[j];
memcpy(dvert, dvert_src, sizeof(MDeformVert));
if (dvert_src->dw) {
memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight));
}
}
j++;
}
@ -314,6 +317,9 @@ void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
dvert_src = &old_dvert[i];
MDeformVert *dvert = &gps->dvert[j];
memcpy(dvert, dvert_src, sizeof(MDeformVert));
if (dvert_src->dw) {
memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight));
}
}
j++;
}
@ -419,8 +425,9 @@ void BKE_gpencil_stroke_modifiers(Depsgraph *depsgraph, Object *ob, bGPDlayer *g
if (ELEM(md->type,
eGpencilModifierType_Hook,
eGpencilModifierType_Lattice,
eGpencilModifierType_Offset))
{
eGpencilModifierType_Noise,
eGpencilModifierType_Offset)) {
gps->flag |= GP_STROKE_RECALC_CACHES;
}
}
@ -706,3 +713,108 @@ void BKE_gpencil_instance_modifier_instance_tfm(InstanceGpencilModifierData *mmd
/* calculate matrix */
loc_eul_size_to_mat4(r_mat, offset, rot, scale);
}
void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
{
bGPDspoint *temp_points;
MDeformVert *temp_dverts = NULL;
MDeformVert *dvert = NULL;
MDeformVert *dvert_final = NULL;
MDeformVert *dvert_next = NULL;
int totnewpoints, oldtotpoints;
int i2;
for (int s = 0; s < level; s++) {
totnewpoints = gps->totpoints - 1;
/* duplicate points in a temp area */
temp_points = MEM_dupallocN(gps->points);
oldtotpoints = gps->totpoints;
/* resize the points arrys */
gps->totpoints += totnewpoints;
gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
if (gps->dvert != NULL) {
temp_dverts = MEM_dupallocN(gps->dvert);
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
gps->flag |= GP_STROKE_RECALC_CACHES;
/* move points from last to first to new place */
i2 = gps->totpoints - 1;
for (int i = oldtotpoints - 1; i > 0; i--) {
bGPDspoint *pt = &temp_points[i];
bGPDspoint *pt_final = &gps->points[i2];
copy_v3_v3(&pt_final->x, &pt->x);
pt_final->pressure = pt->pressure;
pt_final->strength = pt->strength;
pt_final->time = pt->time;
pt_final->flag = pt->flag;
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
dvert_final = &gps->dvert[i2];
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];
/* add a half way point */
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
dvert_next = &temp_dverts[i + 1];
dvert_final = &gps->dvert[i2];
dvert_final->totweight = dvert->totweight;
dvert_final->dw = MEM_dupallocN(dvert->dw);
/* interpolate weight values */
for (int d = 0; d < dvert->totweight; d++) {
MDeformWeight *dw_a = &dvert->dw[d];
if (dvert_next->totweight > d) {
MDeformWeight *dw_b = &dvert_next->dw[d];
MDeformWeight *dw_final = &dvert_final->dw[d];
dw_final->weight = interpf(dw_a->weight, dw_b->weight, 0.5f);
}
}
}
i2 += 2;
}
MEM_SAFE_FREE(temp_points);
MEM_SAFE_FREE(temp_dverts);
/* move points to smooth stroke (not simple flag )*/
if ((flag & GP_SUBDIV_SIMPLE) == 0) {
/* duplicate points in a temp area with the new subdivide data */
temp_points = MEM_dupallocN(gps->points);
/* 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];
/* move point */
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
}
/* free temp memory */
MEM_SAFE_FREE(temp_points);
}
}
}

View File

@ -6601,8 +6601,10 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
gps->points = newdataadr(fd, gps->points);
/* relink weight data */
if (gps->dvert) {
gps->dvert = newdataadr(fd, gps->dvert);
direct_link_dverts(fd, gps->totpoints, gps->dvert);
}
/* the triangulation is not saved, so need to be recalculated */
gps->triangles = NULL;

View File

@ -725,9 +725,6 @@ static int gp_frame_clean_loose_exec(bContext *C, wmOperator *op)
if (gpf == NULL)
continue;
if (gpf == NULL)
continue;
/* simply delete strokes which are no loose */
for (gps = gpf->strokes.first; gps; gps = gpsn) {
gpsn = gps->next;

View File

@ -2920,13 +2920,7 @@ static int gp_count_subdivision_cuts(bGPDstroke *gps)
static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDspoint *temp_points;
const int cuts = RNA_int_get(op->ptr, "number_cuts");
MDeformVert *temp_dvert = NULL;
MDeformVert *dvert_final = NULL;
int totnewpoints, oldtotpoints;
int i2;
/* sanity checks */
if (ELEM(NULL, gpd))
@ -2936,81 +2930,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_BEGIN(C, gpl, gps)
{
if (gps->flag & GP_STROKE_SELECT) {
/* loop as many times as cuts */
for (int s = 0; s < cuts; s++) {
totnewpoints = gp_count_subdivision_cuts(gps);
if (totnewpoints == 0) {
continue;
}
/* duplicate points in a temp area */
temp_points = MEM_dupallocN(gps->points);
oldtotpoints = gps->totpoints;
if (gps->dvert != NULL) {
temp_dvert = MEM_dupallocN(gps->dvert);
}
/* resize the points arrys */
gps->totpoints += totnewpoints;
gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
gps->flag |= GP_STROKE_RECALC_CACHES;
/* loop and interpolate */
i2 = 0;
for (int i = 0; i < oldtotpoints; i++) {
bGPDspoint *pt = &temp_points[i];
bGPDspoint *pt_final = &gps->points[i2];
MDeformVert *dvert = NULL;
if (gps->dvert != NULL) {
dvert = &temp_dvert[i];
}
/* copy current point */
copy_v3_v3(&pt_final->x, &pt->x);
pt_final->pressure = pt->pressure;
pt_final->strength = pt->strength;
pt_final->time = pt->time;
pt_final->flag = pt->flag;
if (gps->dvert != NULL) {
dvert_final = &gps->dvert[i2];
dvert_final->totweight = dvert->totweight;
dvert_final->dw = dvert->dw;
}
i2++;
/* if next point is selected add a half way point */
if (pt->flag & GP_SPOINT_SELECT) {
if (i + 1 < oldtotpoints) {
if (temp_points[i + 1].flag & GP_SPOINT_SELECT) {
pt_final = &gps->points[i2];
if (gps->dvert != NULL) {
dvert_final = &gps->dvert[i2];
}
/* Interpolate all values */
bGPDspoint *next = &temp_points[i + 1];
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->flag |= GP_SPOINT_SELECT;
if (gps->dvert != NULL) {
dvert_final->totweight = 0;
dvert_final->dw = NULL;
}
i2++;
}
}
}
}
/* free temp memory */
MEM_SAFE_FREE(temp_points);
MEM_SAFE_FREE(temp_dvert);
}
BKE_gpencil_subdivide(gps, cuts, 0);
}
}
GP_EDITABLE_STROKES_END;

View File

@ -69,9 +69,6 @@ static void deformStroke(
Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
{
SubdivGpencilModifierData *mmd = (SubdivGpencilModifierData *)md;
bGPDspoint *temp_points;
int totnewpoints, oldtotpoints;
int i2;
if (!is_stroke_affected_by_modifier(ob,
mmd->layername, mmd->pass_index, 3, gpl, gps,
@ -80,78 +77,7 @@ static void deformStroke(
return;
}
/* loop as many times as levels */
for (int s = 0; s < mmd->level; s++) {
totnewpoints = gps->totpoints - 1;
/* duplicate points in a temp area */
temp_points = MEM_dupallocN(gps->points);
oldtotpoints = gps->totpoints;
/* resize the points arrys */
gps->totpoints += totnewpoints;
gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
gps->flag |= GP_STROKE_RECALC_CACHES;
/* move points from last to first to new place */
i2 = gps->totpoints - 1;
for (int i = oldtotpoints - 1; i > 0; i--) {
bGPDspoint *pt = &temp_points[i];
bGPDspoint *pt_final = &gps->points[i2];
MDeformVert *dvert = &gps->dvert[i];
MDeformVert *dvert_final = &gps->dvert[i2];
copy_v3_v3(&pt_final->x, &pt->x);
pt_final->pressure = pt->pressure;
pt_final->strength = pt->strength;
pt_final->time = pt->time;
pt_final->flag = pt->flag;
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];
MDeformVert *dvert_final = &gps->dvert[i2];
/* add a half way point */
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
dvert_final->totweight = 0;
dvert_final->dw = NULL;
i2 += 2;
}
MEM_SAFE_FREE(temp_points);
/* move points to smooth stroke (not simple flag )*/
if ((mmd->flag & GP_SUBDIV_SIMPLE) == 0) {
/* duplicate points in a temp area with the new subdivide data */
temp_points = MEM_dupallocN(gps->points);
/* 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];
/* move point */
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
}
/* free temp memory */
MEM_SAFE_FREE(temp_points);
}
}
BKE_gpencil_subdivide(gps, mmd->level, mmd->flag);
}
static void bakeModifier(