Commit: 94c416195e1b7e2bc761074eac7a74aa4ee55124 Author: Antonio Vazquez Date: Thu Aug 8 15:49:36 2019 +0200 Branches: greasepencil-object https://developer.blender.org/rB94c416195e1b7e2bc761074eac7a74aa4ee55124
Merge branch 'master' into greasepencil-object =================================================================== =================================================================== diff --cc source/blender/blenkernel/intern/gpencil.c index 858f8be6dff,efdb35d4409..c04afb582c5 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@@ -2720,390 -2139,80 +2720,468 @@@ void BKE_gpencil_dissolve_points(bGPDfr } } +/* Merge by distance ------------------------------------- */ +/* Reduce a series of points when the distance is below a threshold. + * Special case for first and last points (both are keeped) for other points, + * the merge point is interpolated between points. + * + */ +void BKE_gpencil_merge_distance_stroke(bGPDframe *gpf, + bGPDstroke *gps, + const float threshold, + const bool use_unselected) +{ + bGPDspoint *pt = NULL; + bGPDspoint *pt_next = NULL; + float tagged = false; + /* Use square distance to speed up loop */ + const float th_square = threshold * threshold; + /* Need to have something to merge. */ + if (gps->totpoints < 2) { + return; + } + int i = 0; + int step = 1; + while ((i < gps->totpoints - 1) && (i + step < gps->totpoints)) { + pt = &gps->points[i]; + if (pt->flag & GP_SPOINT_TAG) { + i++; + step = 1; + continue; + } + pt_next = &gps->points[i + step]; + /* Do not recalc tagged points. */ + if (pt_next->flag & GP_SPOINT_TAG) { + step++; + continue; + } + /* Check if contiguous points are selected. */ + if (!use_unselected) { + if (((pt->flag & GP_SPOINT_SELECT) == 0) || ((pt_next->flag & GP_SPOINT_SELECT) == 0)) { + i++; + step = 1; + continue; + } + } + float len_square = len_squared_v3v3(&pt->x, &pt_next->x); + if (len_square <= th_square) { + tagged = true; + if (i != gps->totpoints - 1) { + /* Tag second point for delete. */ + pt_next->flag |= GP_SPOINT_TAG; + } + else { + pt->flag |= GP_SPOINT_TAG; + } + /* Jump to next pair of points, keeping first point segment equals.*/ + step++; + } + else { + /* Analyze next point. */ + i++; + step = 1; + } + } + + /* Always untag extremes. */ + pt = &gps->points[0]; + pt->flag &= ~GP_SPOINT_TAG; + pt = &gps->points[gps->totpoints - 1]; + pt->flag &= ~GP_SPOINT_TAG; + + /* Dissolve tagged points */ + if (tagged) { + BKE_gpencil_dissolve_points(gpf, gps, GP_SPOINT_TAG); + } +} + +/* Helper function to check materials with same color */ +static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material *r_mat) +{ + Material *ma = NULL; + float color_cu[4]; + linearrgb_to_srgb_v3_v3(color_cu, color); + float hsv1[4]; + rgb_to_hsv_v(color_cu, hsv1); + hsv1[3] = color[3]; + + for (int i = 1; i <= ob_gp->totcol; i++) { + ma = give_current_material(ob_gp, i); + MaterialGPencilStyle *gp_style = ma->gp_style; + /* Check color with small tolerance (better in HSV). */ + float hsv2[4]; + rgb_to_hsv_v(gp_style->fill_rgba, hsv2); + hsv2[3] = gp_style->fill_rgba[3]; + if (compare_v4v4(hsv1, hsv2, 0.01f)) { + r_mat = ma; + return i - 1; + } + } + + r_mat = NULL; + return -1; +} + +/* Add gpencil material using curve material as base */ +static Material *gpencil_add_from_curve_material(Main *bmain, + Object *ob_gp, + float cu_color[4], + const bool gpencil_lines, + const bool fill, + int *r_idx) +{ + Material *mat_gp = BKE_gpencil_object_material_new( + bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx); + MaterialGPencilStyle *gp_style = mat_gp->gp_style; + + /* Stroke color. */ + if (gpencil_lines) { + ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f); + } + else { + linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color); + } + + /* Fill color. */ + linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color); + /* Fill is false if the original curva hasn't material assigned. */ + if (fill) { + gp_style->flag |= GP_STYLE_FILL_SHOW; + } + + return mat_gp; +} + +/* Helper function to create new stroke section */ +static void gpencil_add_new_points(bGPDstroke *gps, + float *coord_array, + float pressure, + int init, + int totpoints, + float init_co[3], + bool last) +{ + for (int i = 0; i < totpoints; i++) { + bGPDspoint *pt = &gps->points[i + init]; + copy_v3_v3(&pt->x, &coord_array[3 * i]); + /* Be sure the last point is not on top of the first point of the curve or + * the close of the stroke will produce glitches. */ + if ((last) && (i > 0) && (i == totpoints - 1)) { + float dist = len_v3v3(init_co, &pt->x); + if (dist < 0.1f) { + /* Interpolate between previous point and current to back slightly. */ + bGPDspoint *pt_prev = &gps->points[i + init - 1]; + interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f); + } + } + + pt->pressure = pressure; + pt->strength = 1.0f; + } +} + +/* Helper function to get the first collection that includes the object. */ +static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob) +{ + Collection *mycol = NULL; + FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { + for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) { + if ((mycol == NULL) && (cob->ob == ob)) { + mycol = collection; + } + } + } + FOREACH_SCENE_COLLECTION_END; + + return mycol; +} + +/* Helper function to convert one spline to grease pencil stroke. */ +static void gpencil_convert_spline(Main *bmain, + Scene *scene, + Object *ob_gp, + Object *ob_cu, + const bool gpencil_lines, + const bool use_collections, + bGPDframe *gpf, + Nurb *nu) +{ + Curve *cu = (Curve *)ob_cu->data; + bool cyclic = true; + + /* Create Stroke. */ + bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke"); + gps->thickness = 1.0f; + gps->gradient_f = 1.0f; + ARRAY_SET_ITEMS(gps->gradient_s, 1.0f, 1.0f); + ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND); + gps->inittime = 0.0f; + + /* Enable recalculation flag by default. */ + gps->flag |= GP_STROKE_RECALC_GEOMETRY; + gps->flag &= ~GP_STROKE_SELECT; + gps->flag |= GP_STROKE_3DSPACE; + + gps->mat_nr = 0; + /* Count total points + * The total of points must consider that last point of each segment is equal to the first + * point of next segment. + */ + int totpoints = 0; + int segments = 0; + int resolu = nu->resolu + 1; + segments = nu->pntsu; + if (((nu->flagu & CU_NURB_CYCLIC) == 0) || (nu->pntsu == 2)) { + segments--; + cyclic = false; + } + totpoints = (resolu * segments) - (segments - 1); + + /* Allocate memory for storage points, but keep empty. */ + gps->totpoints = totpoints; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + /* Initialize triangle memory to dummy data. */ + gps->tot_triangles = 0; + gps->triangles = NULL; + + /* Materials + * Notice: The color of the material is the color of viewport and not the final shader color. + */ + Material *mat_gp = NULL; + bool fill = true; + /* Check if grease pencil has a material with same color.*/ + float color[4]; + if ((cu->mat) && (*cu->mat)) { + Material *mat_cu = *cu->mat; + copy_v4_v4(color, &mat_cu->r); + } + else { + /* Pink (unassigned) */ + zero_v4(color); + color[0] = 1.0f; + color[2] = 1.0f; + color[3] = 1.0f; + fill = false; + } + + /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and + * there is only one color, the stroke must not be closed, fill to false and use for + * stroke the fill color. + */ + bool only_stroke = false; + if (ob_cu->totcol == 1) { + Material *ma_stroke = give_current_material(ob_cu, 1); + if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) { + only_stroke = true; + } + } + + int r_idx = gpencil_check_same_material_color(ob_gp, color, mat_gp); + if (r_idx < 0) { + Material *ma_stroke = NULL; + mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx); + /* If object has more than 1 material, use second material for stroke color. */ + if (ob_cu->totcol > 1) { + ma_stroke = give_current_material(ob_cu, 2); + linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &ma_stroke->r); + mat_gp->gp_style->stroke_rgba[3] = ma_stroke->a; + } + else if (only_stroke) { + /* Also use the first color if the fill is none for stroke color. */ + ma_stroke = give_current_material(ob_cu, 1); + linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &ma_stroke->r); + mat_gp->gp_style->stroke_rgba[3] = ma_stroke->a; + /* set fill to off. */ + mat_gp->gp_style->flag &= ~GP_STYLE_FILL_SHOW; + } + } + /* Assign material index to stroke. */ + gps->mat_nr = r_idx; + + /* Add stroke to frame.*/ + BLI_addtail(&gpf->strokes, gps); + + /* Read all segments of the curve. */ + int init = 0; + resolu = nu->resolu + 1; + segments = nu->pntsu; + if (((nu->flagu & CU_NURB_CYCLIC) == 0) || (nu->pntsu == 2)) { + segments--; + } + /* Get all interpolated curve points of Beziert */ + float init_co[3]; + for (int s = 0; s < segment @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs