From d1e0059eac99654624edee2a2390a3e2fdc4c7cb Mon Sep 17 00:00:00 2001 From: YimingWu Date: Tue, 29 Jun 2021 20:47:55 +0800 Subject: LineArt: Filtering intersection lines using mask numbers Mask value works just like transparency mask. You are able to select intersection lines inside a collection or, between collections. Reviewed By: Sebastian Parborg (zeddb) Differential Revision: https://developer.blender.org/D11309 --- .../scripts/startup/bl_ui/properties_collection.py | 7 ++ .../gpencil_modifiers/intern/MOD_gpencillineart.c | 31 ++++- .../gpencil_modifiers/intern/lineart/MOD_lineart.h | 9 +- .../intern/lineart/lineart_chain.c | 134 ++++++++++++--------- .../gpencil_modifiers/intern/lineart/lineart_cpu.c | 73 +++++++---- .../gpencil_modifiers/intern/lineart/lineart_ops.c | 3 +- source/blender/makesdna/DNA_collection_types.h | 13 +- .../blender/makesdna/DNA_gpencil_modifier_types.h | 12 +- source/blender/makesdna/intern/dna_rename_defs.h | 2 +- source/blender/makesrna/intern/rna_collection.c | 13 ++ .../blender/makesrna/intern/rna_gpencil_modifier.c | 20 ++- 11 files changed, 217 insertions(+), 100 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py index 5a98e638992..27de80bb88d 100644 --- a/release/scripts/startup/bl_ui/properties_collection.py +++ b/release/scripts/startup/bl_ui/properties_collection.py @@ -86,6 +86,13 @@ class COLLECTION_PT_lineart_collection(CollectionButtonsPanel, Panel): row = layout.row() row.prop(collection, "lineart_usage") + layout.prop(collection, "lineart_use_intersection_mask") + + row = layout.row(align=True, heading="Masks") + row.active = collection.lineart_use_intersection_mask + for i in range(0,8): + row.prop(collection, "lineart_intersection_mask", index=i, text=str(i), toggle=True) + classes = ( COLLECTION_PT_collection_flags, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c index f205559b941..9593a1364e7 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c @@ -101,8 +101,9 @@ static void generate_strokes_actual( lmd->use_multiple_levels ? lmd->level_end : lmd->level_start, lmd->target_material ? BKE_gpencil_object_material_index_get(ob, lmd->target_material) : 0, lmd->edge_types, - lmd->material_mask_flags, + lmd->mask_switches, lmd->material_mask_bits, + lmd->intersection_mask, lmd->thickness, lmd->opacity, lmd->source_vertex_group, @@ -462,6 +463,32 @@ static void material_mask_panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(col, ptr, "use_material_mask_match", 0, IFACE_("Match All Masks"), ICON_NONE); } +static void intersection_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); + + const bool is_baked = RNA_boolean_get(ptr, "is_baked"); + uiLayoutSetEnabled(layout, !is_baked); + + uiLayoutSetPropSep(layout, true); + + uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_intersection")); + + uiLayout *row = uiLayoutRow(layout, true); + uiLayoutSetPropDecorate(row, false); + uiLayout *sub = uiLayoutRowWithHeading(row, true, IFACE_("Masks")); + char text[2] = "0"; + + PropertyRNA *prop = RNA_struct_find_property(ptr, "use_intersection_mask"); + for (int i = 0; i < 8; i++, text[0]++) { + uiItemFullR(sub, ptr, prop, i, 0, UI_ITEM_R_TOGGLE, text, ICON_NONE); + } + uiItemL(row, "", ICON_BLANK1); /* Space for decorator. */ + + uiLayout *col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "use_intersection_match", 0, IFACE_("Match All Masks"), ICON_NONE); +} static void face_mark_panel_draw_header(const bContext *UNUSED(C), Panel *panel) { uiLayout *layout = panel->layout; @@ -626,6 +653,8 @@ static void panelRegister(ARegionType *region_type) material_mask_panel_draw_header, material_mask_panel_draw, occlusion_panel); + gpencil_modifier_subpanel_register( + region_type, "intersection", "Intersection", NULL, intersection_panel_draw, panel_type); gpencil_modifier_subpanel_register( region_type, "face_mark", "", face_mark_panel_draw_header, face_mark_panel_draw, panel_type); gpencil_modifier_subpanel_register( diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h index debfabae869..247b0b3f57b 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h +++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h @@ -52,8 +52,8 @@ typedef struct LineartTriangle { /* first culled in line list to use adjacent triangle info, then go through triangle list. */ double gn[3]; - /* Material flag is removed to save space. */ unsigned char material_mask_bits; + unsigned char intersection_mask; unsigned char mat_occlusion; unsigned char flags; /* #eLineartTriangleFlags */ @@ -149,6 +149,7 @@ typedef struct LineartEdge { /** Also for line type determination on chaining. */ unsigned char flags; + unsigned char intersection_mask; /** * Still need this entry because culled lines will not add to object @@ -174,6 +175,7 @@ typedef struct LineartEdgeChain { /** Chain now only contains one type of segments */ int type; unsigned char material_mask_bits; + unsigned char intersection_mask; struct Object *object_ref; } LineartEdgeChain; @@ -188,6 +190,7 @@ typedef struct LineartEdgeChainItem { unsigned char line_type; char occlusion; unsigned char material_mask_bits; + unsigned char intersection_mask; size_t index; } LineartEdgeChainItem; @@ -377,6 +380,7 @@ typedef struct LineartObjectInfo { double normal[4][4]; LineartElementLinkNode *v_eln; int usage; + uint8_t override_intersection_mask; int global_i_offset; bool free_use_mesh; @@ -612,8 +616,9 @@ void MOD_lineart_gpencil_generate(LineartCache *cache, int level_end, int mat_nr, short edge_types, - unsigned char material_mask_flags, + unsigned char mask_switches, unsigned char material_mask_bits, + unsigned char intersection_mask, short thickness, float opacity, const char *source_vgname, diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c index a9f290eb6fa..52485648ee0 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c @@ -38,7 +38,8 @@ static LineartEdge *lineart_line_get_connected(LineartBoundingArea *ba, LineartVert *vt, LineartVert **new_vt, - int match_flag) + int match_flag, + unsigned char match_isec_mask) { for (int i = 0; i < ba->line_count; i++) { LineartEdge *n_e = ba->linked_lines[i]; @@ -51,6 +52,10 @@ static LineartEdge *lineart_line_get_connected(LineartBoundingArea *ba, continue; } + if (n_e->intersection_mask != match_isec_mask) { + continue; + } + *new_vt = LRT_OTHER_VERT(n_e, vt); if (*new_vt) { return n_e; @@ -112,11 +117,11 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb, /* Because the new chain point is overlapping, just replace the type and occlusion level of the * current point. This makes it so that the line to the point after this one has the correct * type and level. */ - LineartEdgeChainItem *old_rlci = ec->chain.last; - old_rlci->line_type = type; - old_rlci->occlusion = level; - old_rlci->material_mask_bits = material_mask_bits; - return old_rlci; + LineartEdgeChainItem *old_eci = ec->chain.last; + old_eci->line_type = type; + old_eci->occlusion = level; + old_eci->material_mask_bits = material_mask_bits; + return old_eci; } eci = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChainItem)); @@ -194,9 +199,10 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb) ec = lineart_chain_create(rb); - /* One chain can only have one object_ref, - * so we assign it based on the first segment we found. */ + /* One chain can only have one object_ref and intersection_mask, + * so we assign them based on the first segment we found. */ ec->object_ref = e->object_ref; + ec->intersection_mask = e->intersection_mask; LineartEdge *new_e; LineartVert *new_vt; @@ -230,7 +236,8 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb) es->occlusion, es->material_mask_bits, e->v1_obindex); - while (ba && (new_e = lineart_line_get_connected(ba, new_vt, &new_vt, e->flags))) { + while (ba && (new_e = lineart_line_get_connected( + ba, new_vt, &new_vt, e->flags, e->intersection_mask))) { new_e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED; if (new_e->t1 || new_e->t2) { @@ -360,7 +367,8 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb) /* Step 3: grow right. */ ba = MOD_lineart_get_bounding_area(rb, e->v2->fbcoord[0], e->v2->fbcoord[1]); new_vt = e->v2; - while (ba && (new_e = lineart_line_get_connected(ba, new_vt, &new_vt, e->flags))) { + while (ba && (new_e = lineart_line_get_connected( + ba, new_vt, &new_vt, e->flags, e->intersection_mask))) { new_e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED; if (new_e->t1 || new_e->t2) { @@ -560,8 +568,8 @@ static void lineart_bounding_area_link_chain(LineartRenderBuffer *rb, LineartEdg void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb) { - LineartEdgeChain *ec, *new_rlc; - LineartEdgeChainItem *eci, *next_rlci; + LineartEdgeChain *ec, *new_ec; + LineartEdgeChainItem *eci, *next_eci; ListBase swap = {0}; swap.first = rb->chains.first; @@ -572,16 +580,16 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb) while ((ec = BLI_pophead(&swap)) != NULL) { ec->next = ec->prev = NULL; BLI_addtail(&rb->chains, ec); - LineartEdgeChainItem *first_rlci = (LineartEdgeChainItem *)ec->chain.first; - int fixed_occ = first_rlci->occlusion; - unsigned char fixed_mask = first_rlci->material_mask_bits; + LineartEdgeChainItem *first_eci = (LineartEdgeChainItem *)ec->chain.first; + int fixed_occ = first_eci->occlusion; + unsigned char fixed_mask = first_eci->material_mask_bits; ec->level = fixed_occ; ec->material_mask_bits = fixed_mask; - for (eci = first_rlci->next; eci; eci = next_rlci) { - next_rlci = eci->next; + for (eci = first_eci->next; eci; eci = next_eci) { + next_eci = eci->next; if (eci->occlusion != fixed_occ || eci->material_mask_bits != fixed_mask) { - if (next_rlci) { - if (lineart_point_overlapping(next_rlci, eci->pos[0], eci->pos[1], 1e-5)) { + if (next_eci) { + if (lineart_point_overlapping(next_eci, eci->pos[0], eci->pos[1], 1e-5)) { continue; } } @@ -593,9 +601,9 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb) /* No need to split at the last point anyway. */ break; } - new_rlc = lineart_chain_create(rb); - new_rlc->chain.first = eci; - new_rlc->chain.last = ec->chain.last; + new_ec = lineart_chain_create(rb); + new_ec->chain.first = eci; + new_ec->chain.last = ec->chain.last; ec->chain.last = eci->prev; ((LineartEdgeChainItem *)ec->chain.last)->next = 0; eci->prev = 0; @@ -610,9 +618,10 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb) fixed_occ, fixed_mask, eci->index); - new_rlc->object_ref = ec->object_ref; - new_rlc->type = ec->type; - ec = new_rlc; + new_ec->object_ref = ec->object_ref; + new_ec->type = ec->type; + new_ec->intersection_mask = ec->intersection_mask; + ec = new_ec; fixed_occ = eci->occlusion; fixed_mask = eci->material_mask_bits; ec->level = fixed_occ; @@ -684,6 +693,7 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf LineartEdgeChainItem *eci, int occlusion, unsigned char material_mask_bits, + unsigned char isec_mask, float dist, float *result_new_len, LineartBoundingArea *caller_ba) @@ -712,7 +722,8 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf continue; } if (cre->ec == ec || (!cre->ec->chain.first) || (cre->ec->level != occlusion) || - (cre->ec->material_mask_bits != material_mask_bits)) { + (cre->ec->material_mask_bits != material_mask_bits) || + (cre->ec->intersection_mask != isec_mask)) { continue; } if (!rb->fuzzy_everything) { @@ -748,8 +759,16 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf if (dist_to < dist && dist_to > 0) { \ LISTBASE_FOREACH (LinkData *, ld, list) { \ LineartBoundingArea *sba = (LineartBoundingArea *)ld->data; \ - adjacent_closest = lineart_chain_get_closest_cre( \ - rb, sba, ec, eci, occlusion, material_mask_bits, dist, &adjacent_new_len, ba); \ + adjacent_closest = lineart_chain_get_closest_cre(rb, \ + sba, \ + ec, \ + eci, \ + occlusion, \ + material_mask_bits, \ + isec_mask, \ + dist, \ + &adjacent_new_len, \ + ba); \ if (adjacent_new_len < dist) { \ dist = adjacent_new_len; \ closest_cre = adjacent_closest; \ @@ -776,13 +795,13 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf void MOD_lineart_chain_connect(LineartRenderBuffer *rb) { LineartEdgeChain *ec; - LineartEdgeChainItem *rlci_l, *rlci_r; + LineartEdgeChainItem *eci_l, *eci_r; LineartBoundingArea *ba_l, *ba_r; LineartChainRegisterEntry *closest_cre_l, *closest_cre_r, *closest_cre; float dist = rb->chaining_image_threshold; float dist_l, dist_r; int occlusion, reverse_main; - unsigned char material_mask_bits; + unsigned char material_mask_bits, isec_mask; ListBase swap = {0}; if (rb->chaining_image_threshold < 0.0001) { @@ -807,15 +826,16 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb) occlusion = ec->level; material_mask_bits = ec->material_mask_bits; + isec_mask = ec->intersection_mask; - rlci_l = ec->chain.first; - rlci_r = ec->chain.last; - while ((ba_l = lineart_bounding_area_get_end_point(rb, rlci_l)) && - (ba_r = lineart_bounding_area_get_end_point(rb, rlci_r))) { + eci_l = ec->chain.first; + eci_r = ec->chain.last; + while ((ba_l = lineart_bounding_area_get_end_point(rb, eci_l)) && + (ba_r = lineart_bounding_area_get_end_point(rb, eci_r))) { closest_cre_l = lineart_chain_get_closest_cre( - rb, ba_l, ec, rlci_l, occlusion, material_mask_bits, dist, &dist_l, NULL); + rb, ba_l, ec, eci_l, occlusion, material_mask_bits, isec_mask, dist, &dist_l, NULL); closest_cre_r = lineart_chain_get_closest_cre( - rb, ba_r, ec, rlci_r, occlusion, material_mask_bits, dist, &dist_r, NULL); + rb, ba_r, ec, eci_r, occlusion, material_mask_bits, isec_mask, dist, &dist_r, NULL); if (closest_cre_l && closest_cre_r) { if (dist_l < dist_r) { closest_cre = closest_cre_l; @@ -847,8 +867,8 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb) lineart_chain_connect(rb, ec, closest_cre->ec, reverse_main, 1); } BLI_remlink(&swap, closest_cre->ec); - rlci_l = ec->chain.first; - rlci_r = ec->chain.last; + eci_l = ec->chain.first; + eci_r = ec->chain.last; } ec->picked = 1; } @@ -876,9 +896,9 @@ float MOD_lineart_chain_compute_length(LineartEdgeChain *ec) void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, const float threshold) { - LineartEdgeChain *ec, *next_rlc; - for (ec = rb->chains.first; ec; ec = next_rlc) { - next_rlc = ec->next; + LineartEdgeChain *ec, *next_ec; + for (ec = rb->chains.first; ec; ec = next_ec) { + next_ec = ec->next; if (MOD_lineart_chain_compute_length(ec) < threshold) { BLI_remlink(&rb->chains, ec); } @@ -910,8 +930,8 @@ void MOD_lineart_chain_clear_picked_flag(LineartCache *lc) */ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad) { - LineartEdgeChain *ec, *new_rlc; - LineartEdgeChainItem *eci, *next_rlci, *prev_rlci; + LineartEdgeChain *ec, *new_ec; + LineartEdgeChainItem *eci, *next_eci, *prev_eci; ListBase swap = {0}; swap.first = rb->chains.first; @@ -922,21 +942,21 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol while ((ec = BLI_pophead(&swap)) != NULL) { ec->next = ec->prev = NULL; BLI_addtail(&rb->chains, ec); - LineartEdgeChainItem *first_rlci = (LineartEdgeChainItem *)ec->chain.first; - for (eci = first_rlci->next; eci; eci = next_rlci) { - next_rlci = eci->next; - prev_rlci = eci->prev; + LineartEdgeChainItem *first_eci = (LineartEdgeChainItem *)ec->chain.first; + for (eci = first_eci->next; eci; eci = next_eci) { + next_eci = eci->next; + prev_eci = eci->prev; float angle = M_PI; - if (next_rlci && prev_rlci) { - angle = angle_v2v2v2(prev_rlci->pos, eci->pos, next_rlci->pos); + if (next_eci && prev_eci) { + angle = angle_v2v2v2(prev_eci->pos, eci->pos, next_eci->pos); } else { break; /* No need to split at the last point anyway. */ } if (angle < angle_threshold_rad) { - new_rlc = lineart_chain_create(rb); - new_rlc->chain.first = eci; - new_rlc->chain.last = ec->chain.last; + new_ec = lineart_chain_create(rb); + new_ec->chain.first = eci; + new_ec->chain.last = ec->chain.last; ec->chain.last = eci->prev; ((LineartEdgeChainItem *)ec->chain.last)->next = 0; eci->prev = 0; @@ -951,11 +971,11 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol ec->level, eci->material_mask_bits, eci->index); - new_rlc->object_ref = ec->object_ref; - new_rlc->type = ec->type; - new_rlc->level = ec->level; - new_rlc->material_mask_bits = ec->material_mask_bits; - ec = new_rlc; + new_ec->object_ref = ec->object_ref; + new_ec->type = ec->type; + new_ec->level = ec->level; + new_ec->material_mask_bits = ec->material_mask_bits; + ec = new_ec; } } } diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index e9f398093a7..477b99d85d0 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -875,7 +875,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb, * (!in0) means "when point 0 is visible". * conditions for point 1, 2 are the same idea. * - * \code{.txt} + * \code{.txt}identify * 1-----|-------0 * | | --- * | |--- @@ -1807,6 +1807,8 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu mat->lineart.mat_occlusion : 1); + tri->intersection_mask = obi->override_intersection_mask; + double gn[3]; copy_v3db_v3fl(gn, f->no); mul_v3_mat3_m4v3_db(tri->gn, normal, gn); @@ -1945,13 +1947,30 @@ static bool _lineart_object_not_in_source_collection(Collection *source, Object return true; } +static uchar lineart_intersection_mask_check(Collection *c, Object *ob) +{ + LISTBASE_FOREACH (CollectionChild *, cc, &c->children) { + uchar result = lineart_intersection_mask_check(cc->collection, ob); + if (result) { + return result; + } + } + + if (c->children.first == NULL) { + if (BKE_collection_has_object(c, (Object *)(ob->id.orig_id))) { + if (c->lineart_flags & COLLECTION_LRT_USE_INTERSECTION_MASK) { + return c->lineart_intersection_mask; + } + } + } + return 0; +} + /** * See if this object in such collection is used for generating line art, * Disabling a collection for line art will doable all objects inside. - * `_rb` is used to provide source selection info. - * See the definition of `rb->_source_type` for details. */ -static int lineart_usage_check(Collection *c, Object *ob, LineartRenderBuffer *_rb) +static int lineart_usage_check(Collection *c, Object *ob) { if (!c) { @@ -1981,29 +2000,15 @@ static int lineart_usage_check(Collection *c, Object *ob, LineartRenderBuffer *_ } return ob->lineart.usage; } - return OBJECT_LRT_INHERIT; } LISTBASE_FOREACH (CollectionChild *, cc, &c->children) { - int result = lineart_usage_check(cc->collection, ob, _rb); + int result = lineart_usage_check(cc->collection, ob); if (result > OBJECT_LRT_INHERIT) { return result; } } - /* Temp solution to speed up calculation in the modifier without cache. See the definition of - * rb->_source_type for details. */ - if (_rb->_source_type == LRT_SOURCE_OBJECT) { - if (ob != _rb->_source_object && ob->id.orig_id != (ID *)_rb->_source_object) { - return OBJECT_LRT_OCCLUSION_ONLY; - } - } - else if (_rb->_source_type == LRT_SOURCE_COLLECTION) { - if (_lineart_object_not_in_source_collection(_rb->_source_collection, ob)) { - return OBJECT_LRT_OCCLUSION_ONLY; - } - } - return OBJECT_LRT_INHERIT; } @@ -2123,7 +2128,9 @@ static void lineart_main_load_geometries( DEG_OBJECT_ITER_BEGIN (depsgraph, ob, flags) { LineartObjectInfo *obi = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartObjectInfo)); - obi->usage = lineart_usage_check(scene->master_collection, ob, rb); + obi->usage = lineart_usage_check(scene->master_collection, ob); + obi->override_intersection_mask = lineart_intersection_mask_check(scene->master_collection, + ob); Mesh *use_mesh; if (obi->usage == OBJECT_LRT_EXCLUDE) { @@ -2841,6 +2848,7 @@ static LineartEdge *lineart_triangle_intersect(LineartRenderBuffer *rb, BLI_addtail(&result->segments, es); /* Don't need to OR flags right now, just a type mark. */ result->flags = LRT_EDGE_FLAG_INTERSECTION; + result->intersection_mask = (tri->intersection_mask | testing->intersection_mask); lineart_prepend_edge_direct(&rb->intersection.first, result); int r1, r2, c1, c2, row, col; @@ -4191,8 +4199,9 @@ static void lineart_gpencil_generate(LineartCache *cache, Object *source_object, Collection *source_collection, int types, - uchar material_mask_flags, + uchar mask_switches, uchar material_mask_bits, + uchar intersection_mask, short thickness, float opacity, const char *source_vgname, @@ -4248,8 +4257,8 @@ static void lineart_gpencil_generate(LineartCache *cache, continue; } } - if (material_mask_flags & LRT_GPENCIL_MATERIAL_MASK_ENABLE) { - if (material_mask_flags & LRT_GPENCIL_MATERIAL_MASK_MATCH) { + if (mask_switches & LRT_GPENCIL_MATERIAL_MASK_ENABLE) { + if (mask_switches & LRT_GPENCIL_MATERIAL_MASK_MATCH) { if (ec->material_mask_bits != material_mask_bits) { continue; } @@ -4260,6 +4269,18 @@ static void lineart_gpencil_generate(LineartCache *cache, } } } + if (types & LRT_EDGE_FLAG_INTERSECTION) { + if (mask_switches & LRT_GPENCIL_INTERSECTION_MATCH) { + if (ec->intersection_mask != intersection_mask) { + continue; + } + } + else { + if ((intersection_mask) && !(ec->intersection_mask & intersection_mask)) { + continue; + } + } + } /* Preserved: If we ever do asynchronous generation, this picked flag should be set here. */ // ec->picked = 1; @@ -4354,8 +4375,9 @@ void MOD_lineart_gpencil_generate(LineartCache *cache, int level_end, int mat_nr, short edge_types, - uchar material_mask_flags, + uchar mask_switches, uchar material_mask_bits, + uchar intersection_mask, short thickness, float opacity, const char *source_vgname, @@ -4403,8 +4425,9 @@ void MOD_lineart_gpencil_generate(LineartCache *cache, source_object, source_collection, use_types, - material_mask_flags, + mask_switches, material_mask_bits, + intersection_mask, thickness, opacity, source_vgname, diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c index b0ead0013d8..988c90483a6 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c @@ -143,8 +143,9 @@ static bool bake_strokes(Object *ob, lmd->use_multiple_levels ? lmd->level_end : lmd->level_start, lmd->target_material ? BKE_gpencil_object_material_index_get(ob, lmd->target_material) : 0, lmd->edge_types, - lmd->material_mask_flags, + lmd->mask_switches, lmd->material_mask_bits, + lmd->intersection_mask, lmd->thickness, lmd->opacity, lmd->source_vertex_group, diff --git a/source/blender/makesdna/DNA_collection_types.h b/source/blender/makesdna/DNA_collection_types.h index aa91699ae40..1defa8b782b 100644 --- a/source/blender/makesdna/DNA_collection_types.h +++ b/source/blender/makesdna/DNA_collection_types.h @@ -46,9 +46,6 @@ typedef struct CollectionChild { struct Collection *collection; } CollectionChild; -/** - * \warning while the values seem to be flags, they aren't treated as flags. - */ enum eCollectionLineArt_Usage { COLLECTION_LRT_INCLUDE = 0, COLLECTION_LRT_OCCLUSION_ONLY = (1 << 0), @@ -57,6 +54,10 @@ enum eCollectionLineArt_Usage { COLLECTION_LRT_NO_INTERSECTION = (1 << 3), }; +enum eCollectionLineArt_Flags { + COLLECTION_LRT_USE_INTERSECTION_MASK = (1 << 0), +}; + typedef struct Collection { ID id; @@ -74,8 +75,10 @@ typedef struct Collection { /* Runtime-only, always cleared on file load. */ short tag; - /** Line Art engine specific */ - short lineart_usage; + short lineart_usage; /* eCollectionLineArt_Usage */ + unsigned char lineart_flags; /* eCollectionLineArt_Flags */ + unsigned char lineart_intersection_mask; + char _pad[6]; int16_t color_tag; diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 0bd7e500044..40e4c65c4b8 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -883,11 +883,14 @@ typedef enum eLineArtGPencilModifierFlags { LRT_GPENCIL_USE_CACHE = (1 << 4), } eLineArtGPencilModifierFlags; -typedef enum eLineartGpencilMaterialMaskFlags { +typedef enum eLineartGpencilMaskSwitches { LRT_GPENCIL_MATERIAL_MASK_ENABLE = (1 << 0), /** When set, material mask bit comparisons are done with bit wise "AND" instead of "OR". */ LRT_GPENCIL_MATERIAL_MASK_MATCH = (1 << 1), -} eLineartGpencilMaterialMaskFlags; + LRT_GPENCIL_INTERSECTION_MATCH = (1 << 2), +} eLineartGpencilMaskSwitches; + +struct LineartCache; struct LineartCache; @@ -918,8 +921,11 @@ typedef struct LineartGpencilModifierData { float opacity; short thickness; - unsigned char material_mask_flags; /* eLineartGpencilMaterialMaskFlags */ + unsigned char mask_switches; /* eLineartGpencilMaskSwitches */ unsigned char material_mask_bits; + unsigned char intersection_mask; + + char _pad[7]; /** `0..1` range for cosine angle */ float crease_threshold; diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index 57abf708f60..735be0c10bf 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -134,6 +134,6 @@ DNA_STRUCT_RENAME_ELEM(RigidBodyWorld, steps_per_second, substeps_per_frame) * global_areas. See D9442. */ DNA_STRUCT_RENAME_ELEM(wmWindow, global_area_map, global_areas) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, line_types, edge_types) -DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, material_mask_flags) +DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, mask_switches) DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_mask, material_mask_bits) DNA_STRUCT_RENAME_ELEM(MaterialLineArt, transparency_mask, material_mask_bits) diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c index 643503e52fa..577a3273e21 100644 --- a/source/blender/makesrna/intern/rna_collection.c +++ b/source/blender/makesrna/intern/rna_collection.c @@ -548,6 +548,19 @@ void RNA_def_collections(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Usage", "How to use this collection in line art"); RNA_def_property_update(prop, NC_SCENE, NULL); + prop = RNA_def_property(srna, "lineart_use_intersection_mask", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "lineart_flags", 1); + RNA_def_property_ui_text( + prop, "Use Intersection Masks", "Use custom intersection mask for faces in this collection"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop = RNA_def_property(srna, "lineart_intersection_mask", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "lineart_intersection_mask", 1); + RNA_def_property_array(prop, 8); + RNA_def_property_ui_text( + prop, "Masks", "Intersection generated by this collection will have this mask value"); + RNA_def_property_update(prop, NC_SCENE, NULL); + prop = RNA_def_property(srna, "color_tag", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "color_tag"); RNA_def_property_enum_funcs( diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 24b1e66bbb5..3e6048e30c4 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -2997,15 +2997,13 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "use_material_mask", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna( - prop, NULL, "material_mask_flags", LRT_GPENCIL_MATERIAL_MASK_ENABLE); + RNA_def_property_boolean_sdna(prop, NULL, "mask_switches", LRT_GPENCIL_MATERIAL_MASK_ENABLE); RNA_def_property_ui_text( prop, "Use Material Mask", "Use material masks to filter out occluded strokes"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "use_material_mask_match", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna( - prop, NULL, "material_mask_flags", LRT_GPENCIL_MATERIAL_MASK_MATCH); + RNA_def_property_boolean_sdna(prop, NULL, "mask_switches", LRT_GPENCIL_MATERIAL_MASK_MATCH); RNA_def_property_ui_text( prop, "Match Masks", "Require matching all material masks instead of just one"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); @@ -3013,7 +3011,19 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna) prop = RNA_def_property(srna, "use_material_mask_bits", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "material_mask_bits", 1); RNA_def_property_array(prop, 8); - RNA_def_property_ui_text(prop, "Mask", ""); + RNA_def_property_ui_text(prop, "Masks", "Mask bits to match from Material Line Art settings"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_intersection_match", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mask_switches", LRT_GPENCIL_INTERSECTION_MATCH); + RNA_def_property_ui_text( + prop, "Match Intersection", "Require matching all intersection masks instead of just one"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_intersection_mask", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "intersection_mask", 1); + RNA_def_property_array(prop, 8); + RNA_def_property_ui_text(prop, "Masks", "Mask bits to match from Collection Line Art settings"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); RNA_define_lib_overridable(false); -- cgit v1.2.3