diff options
-rw-r--r-- | source/blender/blenkernel/BKE_gpencil.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/gpencil.c | 129 | ||||
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c | 2 | ||||
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_draw_utils.c | 134 | ||||
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_engine.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_gpencil.c | 33 |
6 files changed, 144 insertions, 156 deletions
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 21356db8abf..6400a4f959e 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -233,6 +233,7 @@ void BKE_gpencil_stroke_2d_flat_ref(const struct bGPDspoint *ref_points, float (*points2d)[2], const float scale, int *r_direction); +void BKE_gpencil_triangulate_stroke_fill(struct bGPdata *gpd, struct bGPDstroke *gps); void BKE_gpencil_transform(struct bGPdata *gpd, float mat[4][4]); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index d0da5c6c0f1..4744d2cf1c0 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -34,6 +34,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_math_vector.h" +#include "BLI_polyfill_2d.h" #include "BLI_string_utils.h" #include "BLT_translation.h" @@ -2517,6 +2518,134 @@ void BKE_gpencil_stroke_2d_flat_ref(const bGPDspoint *ref_points, *r_direction = (int)locy[2]; } +/* calc bounding box in 2d using flat projection data */ +static void gpencil_calc_2d_bounding_box(const float (*points2d)[2], + int totpoints, + float minv[2], + float maxv[2]) +{ + minv[0] = points2d[0][0]; + minv[1] = points2d[0][1]; + maxv[0] = points2d[0][0]; + maxv[1] = points2d[0][1]; + + for (int i = 1; i < totpoints; i++) { + /* min */ + if (points2d[i][0] < minv[0]) { + minv[0] = points2d[i][0]; + } + if (points2d[i][1] < minv[1]) { + minv[1] = points2d[i][1]; + } + /* max */ + if (points2d[i][0] > maxv[0]) { + maxv[0] = points2d[i][0]; + } + if (points2d[i][1] > maxv[1]) { + maxv[1] = points2d[i][1]; + } + } + /* use a perfect square */ + if (maxv[0] > maxv[1]) { + maxv[1] = maxv[0]; + } + else { + maxv[0] = maxv[1]; + } +} + +/* calc texture coordinates using flat projected points */ +static void gpencil_calc_stroke_fill_uv(const float (*points2d)[2], + int totpoints, + const float minv[2], + float maxv[2], + float (*r_uv)[2]) +{ + float d[2]; + d[0] = maxv[0] - minv[0]; + d[1] = maxv[1] - minv[1]; + for (int i = 0; i < totpoints; i++) { + r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0]; + r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1]; + } +} + +/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was + * modified) */ +void BKE_gpencil_triangulate_stroke_fill(bGPdata *gpd, bGPDstroke *gps) +{ + BLI_assert(gps->totpoints >= 3); + + /* allocate memory for temporary areas */ + gps->tot_triangles = gps->totpoints - 2; + uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, + "GP Stroke temp triangulation"); + float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, + "GP Stroke temp 2d points"); + float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data"); + + int direction = 0; + + /* convert to 2d and triangulate */ + BKE_gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction); + BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles); + + /* calc texture coordinates automatically */ + float minv[2]; + float maxv[2]; + /* first needs bounding box data */ + if (gpd->flag & GP_DATA_UV_ADAPTIVE) { + gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv); + } + else { + ARRAY_SET_ITEMS(minv, -1.0f, -1.0f); + ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f); + } + + /* calc uv data */ + gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv); + + /* Number of triangles */ + gps->tot_triangles = gps->totpoints - 2; + /* save triangulation data in stroke cache */ + if (gps->tot_triangles > 0) { + if (gps->triangles == NULL) { + gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, + "GP Stroke triangulation"); + } + else { + gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles); + } + + for (int i = 0; i < gps->tot_triangles; i++) { + bGPDtriangle *stroke_triangle = &gps->triangles[i]; + memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3])); + /* copy texture coordinates */ + copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]); + copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]); + copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]); + } + } + else { + /* No triangles needed - Free anything allocated previously */ + if (gps->triangles) { + MEM_freeN(gps->triangles); + } + + gps->triangles = NULL; + } + + /* disable recalculation flag */ + if (gps->flag & GP_STROKE_RECALC_GEOMETRY) { + gps->flag &= ~GP_STROKE_RECALC_GEOMETRY; + } + + /* clear memory */ + MEM_SAFE_FREE(tmp_triangles); + MEM_SAFE_FREE(points2d); + MEM_SAFE_FREE(uv); +} + float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d) { if (!gps->points || gps->totpoints < 2) { diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c index 8006c784190..cfd99b0bdfc 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -338,7 +338,7 @@ void gpencil_get_fill_geom(struct GpencilBatchCacheElem *be, /* Calculate triangles cache for filling area (must be done only after changes) */ if ((gps->flag & GP_STROKE_RECALC_GEOMETRY) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) { - gpencil_triangulate_stroke_fill(ob, gps); + BKE_gpencil_triangulate_stroke_fill((bGPdata *)ob->data, gps); } BLI_assert(gps->tot_triangles >= 1); diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index cd96b21280f..7e75edfddf3 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -20,8 +20,6 @@ * \ingroup draw */ -#include "BLI_polyfill_2d.h" - #include "DRW_render.h" #include "BKE_gpencil.h" @@ -284,58 +282,6 @@ static bool gpencil_can_draw_stroke(struct MaterialGPencilStyle *gp_style, return true; } -/* calc bounding box in 2d using flat projection data */ -static void gpencil_calc_2d_bounding_box(const float (*points2d)[2], - int totpoints, - float minv[2], - float maxv[2]) -{ - minv[0] = points2d[0][0]; - minv[1] = points2d[0][1]; - maxv[0] = points2d[0][0]; - maxv[1] = points2d[0][1]; - - for (int i = 1; i < totpoints; i++) { - /* min */ - if (points2d[i][0] < minv[0]) { - minv[0] = points2d[i][0]; - } - if (points2d[i][1] < minv[1]) { - minv[1] = points2d[i][1]; - } - /* max */ - if (points2d[i][0] > maxv[0]) { - maxv[0] = points2d[i][0]; - } - if (points2d[i][1] > maxv[1]) { - maxv[1] = points2d[i][1]; - } - } - /* use a perfect square */ - if (maxv[0] > maxv[1]) { - maxv[1] = maxv[0]; - } - else { - maxv[0] = maxv[1]; - } -} - -/* calc texture coordinates using flat projected points */ -static void gpencil_calc_stroke_fill_uv(const float (*points2d)[2], - int totpoints, - const float minv[2], - float maxv[2], - float (*r_uv)[2]) -{ - float d[2]; - d[0] = maxv[0] - minv[0]; - d[1] = maxv[1] - minv[1]; - for (int i = 0; i < totpoints; i++) { - r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0]; - r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1]; - } -} - /* recalc the internal geometry caches for fill and uvs */ static void gpencil_recalc_geometry_caches(Object *ob, bGPDlayer *gpl, @@ -348,7 +294,7 @@ static void gpencil_recalc_geometry_caches(Object *ob, if ((gps->totpoints > 2) && (gp_style->flag & GP_STYLE_FILL_SHOW) && ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0) || (gpl->blend_mode != eGplBlendMode_Regular))) { - gpencil_triangulate_stroke_fill(ob, gps); + BKE_gpencil_triangulate_stroke_fill((bGPdata *)ob->data, gps); } } @@ -1509,84 +1455,6 @@ static void gpencil_draw_onionskins(GpencilBatchCache *cache, } } -/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was - * modified) */ -void gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps) -{ - BLI_assert(gps->totpoints >= 3); - - bGPdata *gpd = (bGPdata *)ob->data; - - /* allocate memory for temporary areas */ - gps->tot_triangles = gps->totpoints - 2; - uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, - "GP Stroke temp triangulation"); - float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, - "GP Stroke temp 2d points"); - float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data"); - - int direction = 0; - - /* convert to 2d and triangulate */ - BKE_gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction); - BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles); - - /* calc texture coordinates automatically */ - float minv[2]; - float maxv[2]; - /* first needs bounding box data */ - if (gpd->flag & GP_DATA_UV_ADAPTIVE) { - gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv); - } - else { - ARRAY_SET_ITEMS(minv, -1.0f, -1.0f); - ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f); - } - - /* calc uv data */ - gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv); - - /* Number of triangles */ - gps->tot_triangles = gps->totpoints - 2; - /* save triangulation data in stroke cache */ - if (gps->tot_triangles > 0) { - if (gps->triangles == NULL) { - gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, - "GP Stroke triangulation"); - } - else { - gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles); - } - - for (int i = 0; i < gps->tot_triangles; i++) { - bGPDtriangle *stroke_triangle = &gps->triangles[i]; - memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3])); - /* copy texture coordinates */ - copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]); - copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]); - copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]); - } - } - else { - /* No triangles needed - Free anything allocated previously */ - if (gps->triangles) { - MEM_freeN(gps->triangles); - } - - gps->triangles = NULL; - } - - /* disable recalculation flag */ - if (gps->flag & GP_STROKE_RECALC_GEOMETRY) { - gps->flag &= ~GP_STROKE_RECALC_GEOMETRY; - } - - /* clear memory */ - MEM_SAFE_FREE(tmp_triangles); - MEM_SAFE_FREE(points2d); - MEM_SAFE_FREE(uv); -} - /* Check if stencil is required */ static bool gpencil_is_stencil_required(MaterialGPencilStyle *gp_style) { diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 04ed19830ed..b5e7349fb88 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -417,7 +417,6 @@ void gpencil_populate_multiedit(struct GPENCIL_e_data *e_data, void *vedata, struct Object *ob, struct tGPencilObjectCache *cache_ob); -void gpencil_triangulate_stroke_fill(struct Object *ob, struct bGPDstroke *gps); void gpencil_populate_particles(struct GPENCIL_e_data *e_data, struct GHash *gh_objects, void *vedata); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 2601600c6ee..46317a30b19 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -167,32 +167,23 @@ static void rna_GPencil_editmode_update(Main *UNUSED(bmain), Scene *UNUSED(scene WM_main_add_notifier(NC_SCENE | ND_MODE | NC_MOVIECLIP, NULL); } -static void UNUSED_FUNCTION(rna_GPencil_onion_skinning_update)(Main *bmain, - Scene *scene, - PointerRNA *ptr) +/* Recalc UVs and Fill for all strokes. */ +static void rna_GPencil_strokes_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bGPdata *gpd = (bGPdata *)ptr->owner_id; - bGPDlayer *gpl; - bool enabled = false; - - /* Ensure that the data-block's onion-skinning toggle flag - * stays in sync with the status of the actual layers - */ - for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->onion_flag & GP_LAYER_ONIONSKIN) { - enabled = true; + if (gpd) { + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + BKE_gpencil_triangulate_stroke_fill(gpd, gps); + } + } } } - if (enabled) { - gpd->flag |= GP_DATA_SHOW_ONIONSKINS; - } - else { - gpd->flag &= ~GP_DATA_SHOW_ONIONSKINS; - } - /* Now do standard updates... */ - rna_GPencil_update(bmain, scene, ptr); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); } /* Poll Callback to filter GP Datablocks to only show those for Annotations */ @@ -1781,7 +1772,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_UV_ADAPTIVE); RNA_def_property_ui_text( prop, "Adaptive UV", "Automatic UVs are calculated depending of the stroke size"); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_strokes_update"); prop = RNA_def_property(srna, "use_autolock_layers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_AUTOLOCK_LAYERS); |