diff options
Diffstat (limited to 'source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c')
-rw-r--r-- | source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c | 182 |
1 files changed, 143 insertions, 39 deletions
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c index 1d84bb8e232..f32141a31eb 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c @@ -17,13 +17,16 @@ #define LRT_OTHER_VERT(e, vt) ((vt) == (e)->v1 ? (e)->v2 : ((vt) == (e)->v2 ? (e)->v1 : NULL)) +struct Object; + /* Get a connected line, only for lines who has the exact given vert, or (in the case of * intersection lines) who has a vert that has the exact same position. */ static LineartEdge *lineart_line_get_connected(LineartBoundingArea *ba, LineartVert *vt, LineartVert **new_vt, int match_flag, - uint8_t match_isec_mask) + uint8_t match_isec_mask, + struct Object *match_isec_object) { for (int i = 0; i < ba->line_count; i++) { LineartEdge *n_e = ba->linked_lines[i]; @@ -46,6 +49,9 @@ static LineartEdge *lineart_line_get_connected(LineartBoundingArea *ba, } if (n_e->flags & LRT_EDGE_FLAG_INTERSECTION) { + if (n_e->object_ref != match_isec_object) { + continue; + } if (vt->fbcoord[0] == n_e->v1->fbcoord[0] && vt->fbcoord[1] == n_e->v1->fbcoord[1]) { *new_vt = LRT_OTHER_VERT(n_e, n_e->v1); return n_e; @@ -87,12 +93,13 @@ static bool lineart_point_overlapping(LineartEdgeChainItem *eci, static LineartEdgeChainItem *lineart_chain_append_point(LineartData *ld, LineartEdgeChain *ec, - float *fbcoord, - float *gpos, - float *normal, + float fbcoord[4], + float gpos[3], + float normal[3], uint8_t type, int level, uint8_t material_mask_bits, + uint32_t shadow_mask_bits, size_t index) { LineartEdgeChainItem *eci; @@ -105,6 +112,7 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartData *ld, old_eci->line_type = type; old_eci->occlusion = level; old_eci->material_mask_bits = material_mask_bits; + old_eci->shadow_mask_bits = shadow_mask_bits; return old_eci; } @@ -117,6 +125,7 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartData *ld, eci->line_type = type & LRT_EDGE_FLAG_ALL_TYPE; eci->occlusion = level; eci->material_mask_bits = material_mask_bits; + eci->shadow_mask_bits = shadow_mask_bits; BLI_addtail(&ec->chain, eci); return eci; @@ -124,12 +133,13 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartData *ld, static LineartEdgeChainItem *lineart_chain_prepend_point(LineartData *ld, LineartEdgeChain *ec, - float *fbcoord, - float *gpos, - float *normal, + float fbcoord[4], + float gpos[3], + float normal[3], uint8_t type, int level, uint8_t material_mask_bits, + uint32_t shadow_mask_bits, size_t index) { LineartEdgeChainItem *eci; @@ -147,6 +157,7 @@ static LineartEdgeChainItem *lineart_chain_prepend_point(LineartData *ld, eci->line_type = type & LRT_EDGE_FLAG_ALL_TYPE; eci->occlusion = level; eci->material_mask_bits = material_mask_bits; + eci->shadow_mask_bits = shadow_mask_bits; BLI_addhead(&ec->chain, eci); return eci; @@ -160,6 +171,7 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) LineartEdgeSegment *es; int last_occlusion; uint8_t last_transparency; + uint32_t last_shadow; /* Used when converting from double. */ float use_fbcoord[4]; float use_gpos[3]; @@ -219,9 +231,10 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) e->flags, es->occlusion, es->material_mask_bits, + es->shadow_mask_bits, e->v1->index); while (ba && (new_e = lineart_line_get_connected( - ba, new_vt, &new_vt, e->flags, e->intersection_mask))) { + ba, new_vt, &new_vt, e->flags, ec->intersection_mask, ec->object_ref))) { new_e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED; if (new_e->t1 || new_e->t2) { @@ -243,8 +256,8 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) for (es = new_e->segments.last; es; es = es->prev) { double gpos[3], lpos[3]; double *lfb = new_e->v1->fbcoord, *rfb = new_e->v2->fbcoord; - double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]); - interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->at); + double global_at = lfb[3] * es->ratio / (es->ratio * lfb[3] + (1 - es->ratio) * rfb[3]); + interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->ratio); interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at); use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at); POS_TO_FLOAT(lpos, gpos) @@ -256,21 +269,24 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) new_e->flags, es->occlusion, es->material_mask_bits, + es->shadow_mask_bits, new_e->v1->index); last_occlusion = es->occlusion; last_transparency = es->material_mask_bits; + last_shadow = es->shadow_mask_bits; } } else if (new_vt == new_e->v2) { es = new_e->segments.first; last_occlusion = es->occlusion; last_transparency = es->material_mask_bits; + last_shadow = es->shadow_mask_bits; es = es->next; for (; es; es = es->next) { double gpos[3], lpos[3]; double *lfb = new_e->v1->fbcoord, *rfb = new_e->v2->fbcoord; - double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]); - interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->at); + double global_at = lfb[3] * es->ratio / (es->ratio * lfb[3] + (1 - es->ratio) * rfb[3]); + interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->ratio); interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at); use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at); POS_TO_FLOAT(lpos, gpos) @@ -282,9 +298,11 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) new_e->flags, last_occlusion, last_transparency, + last_shadow, new_e->v2->index); last_occlusion = es->occlusion; last_transparency = es->material_mask_bits; + last_shadow = es->shadow_mask_bits; } VERT_COORD_TO_FLOAT(new_e->v2); lineart_chain_prepend_point(ld, @@ -295,6 +313,7 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) new_e->flags, last_occlusion, last_transparency, + last_shadow, new_e->v2->index); } ba = MOD_lineart_get_bounding_area(ld, new_vt->fbcoord[0], new_vt->fbcoord[1]); @@ -318,13 +337,14 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) /* Step 2: Adding all cuts from the given line, so we can continue connecting the right side * of the line. */ es = e->segments.first; - last_occlusion = ((LineartEdgeSegment *)es)->occlusion; - last_transparency = ((LineartEdgeSegment *)es)->material_mask_bits; + last_occlusion = es->occlusion; + last_transparency = es->material_mask_bits; + last_shadow = es->shadow_mask_bits; for (es = es->next; es; es = es->next) { double gpos[3], lpos[3]; double *lfb = e->v1->fbcoord, *rfb = e->v2->fbcoord; - double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]); - interp_v3_v3v3_db(lpos, e->v1->fbcoord, e->v2->fbcoord, es->at); + double global_at = lfb[3] * es->ratio / (es->ratio * lfb[3] + (1 - es->ratio) * rfb[3]); + interp_v3_v3v3_db(lpos, e->v1->fbcoord, e->v2->fbcoord, es->ratio); interp_v3_v3v3_db(gpos, e->v1->gloc, e->v2->gloc, global_at); use_fbcoord[3] = interpf(e->v2->fbcoord[3], e->v1->fbcoord[3], global_at); POS_TO_FLOAT(lpos, gpos) @@ -336,9 +356,11 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) e->flags, es->occlusion, es->material_mask_bits, + es->shadow_mask_bits, e->v1->index); last_occlusion = es->occlusion; last_transparency = es->material_mask_bits; + last_shadow = es->shadow_mask_bits; } VERT_COORD_TO_FLOAT(e->v2) lineart_chain_append_point(ld, @@ -349,13 +371,14 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) e->flags, last_occlusion, last_transparency, + last_shadow, e->v2->index); /* Step 3: grow right. */ ba = MOD_lineart_get_bounding_area(ld, 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, e->intersection_mask))) { + ba, new_vt, &new_vt, e->flags, ec->intersection_mask, ec->object_ref))) { new_e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED; if (new_e->t1 || new_e->t2) { @@ -381,18 +404,21 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) es = new_e->segments.last; last_occlusion = es->occlusion; last_transparency = es->material_mask_bits; + last_shadow = es->shadow_mask_bits; /* Fix leading vertex occlusion. */ eci->occlusion = last_occlusion; eci->material_mask_bits = last_transparency; + eci->shadow_mask_bits = last_shadow; for (es = new_e->segments.last; es; es = es->prev) { double gpos[3], lpos[3]; double *lfb = new_e->v1->fbcoord, *rfb = new_e->v2->fbcoord; - double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]); - interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->at); + double global_at = lfb[3] * es->ratio / (es->ratio * lfb[3] + (1 - es->ratio) * rfb[3]); + interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->ratio); interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at); use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at); last_occlusion = es->prev ? es->prev->occlusion : last_occlusion; last_transparency = es->prev ? es->prev->material_mask_bits : last_transparency; + last_shadow = es->prev ? es->prev->shadow_mask_bits : last_shadow; POS_TO_FLOAT(lpos, gpos) lineart_chain_append_point(ld, ec, @@ -402,6 +428,7 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) new_e->flags, last_occlusion, last_transparency, + last_shadow, new_e->v1->index); } } @@ -409,14 +436,16 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) es = new_e->segments.first; last_occlusion = es->occlusion; last_transparency = es->material_mask_bits; + last_shadow = es->shadow_mask_bits; eci->occlusion = last_occlusion; eci->material_mask_bits = last_transparency; + eci->shadow_mask_bits = last_shadow; es = es->next; for (; es; es = es->next) { double gpos[3], lpos[3]; double *lfb = new_e->v1->fbcoord, *rfb = new_e->v2->fbcoord; - double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]); - interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->at); + double global_at = lfb[3] * es->ratio / (es->ratio * lfb[3] + (1 - es->ratio) * rfb[3]); + interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->ratio); interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at); use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at); POS_TO_FLOAT(lpos, gpos) @@ -428,9 +457,11 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) new_e->flags, es->occlusion, es->material_mask_bits, + es->shadow_mask_bits, new_e->v2->index); last_occlusion = es->occlusion; last_transparency = es->material_mask_bits; + last_shadow = es->shadow_mask_bits; } VERT_COORD_TO_FLOAT(new_e->v2) lineart_chain_append_point(ld, @@ -441,6 +472,7 @@ void MOD_lineart_chain_feature_lines(LineartData *ld) new_e->flags, last_occlusion, last_transparency, + last_shadow, new_e->v2->index); } ba = MOD_lineart_get_bounding_area(ld, new_vt->fbcoord[0], new_vt->fbcoord[1]); @@ -509,7 +541,7 @@ static void lineart_bounding_area_link_point_recursive(LineartData *ld, { if (root->child == NULL) { LineartChainRegisterEntry *cre = lineart_list_append_pointer_pool_sized( - &root->linked_chains, &ld->render_data_pool, ec, sizeof(LineartChainRegisterEntry)); + &root->linked_chains, ld->chain_data_pool, ec, sizeof(LineartChainRegisterEntry)); cre->eci = eci; @@ -565,6 +597,7 @@ static bool lineart_chain_fix_ambiguous_segments(LineartEdgeChain *ec, int fixed_occ = last_matching_eci->occlusion; uint8_t fixed_mask = last_matching_eci->material_mask_bits; + uint32_t fixed_shadow = last_matching_eci->shadow_mask_bits; LineartEdgeChainItem *can_skip_to = NULL; LineartEdgeChainItem *last_eci = last_matching_eci; @@ -579,7 +612,8 @@ static bool lineart_chain_fix_ambiguous_segments(LineartEdgeChain *ec, if (eci->occlusion < fixed_occ) { break; } - if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ) { + if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ && + eci->shadow_mask_bits == fixed_shadow) { can_skip_to = eci; } } @@ -589,12 +623,14 @@ static bool lineart_chain_fix_ambiguous_segments(LineartEdgeChain *ec, LineartEdgeChainItem *next_eci; for (LineartEdgeChainItem *eci = last_matching_eci->next; eci != can_skip_to; eci = next_eci) { next_eci = eci->next; - if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ) { + if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ && + eci->shadow_mask_bits == fixed_shadow) { continue; } if (preserve_details) { eci->material_mask_bits = fixed_mask; eci->occlusion = fixed_occ; + eci->shadow_mask_bits = fixed_shadow; } else { BLI_remlink(&ec->chain, eci); @@ -628,11 +664,14 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartData *ld) LineartEdgeChainItem *first_eci = (LineartEdgeChainItem *)ec->chain.first; int fixed_occ = first_eci->occlusion; uint8_t fixed_mask = first_eci->material_mask_bits; + uint32_t fixed_shadow = first_eci->shadow_mask_bits; ec->level = fixed_occ; ec->material_mask_bits = fixed_mask; + ec->shadow_mask_bits = fixed_shadow; 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 (eci->occlusion != fixed_occ || eci->material_mask_bits != fixed_mask || + eci->shadow_mask_bits != fixed_shadow) { if (next_eci) { if (lineart_point_overlapping(next_eci, eci->pos[0], eci->pos[1], 1e-5)) { continue; @@ -649,6 +688,7 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartData *ld) /* Set the same occlusion level for the end vertex, so when further connection is needed * the backwards occlusion info is also correct. */ eci->occlusion = fixed_occ; + eci->shadow_mask_bits = fixed_shadow; eci->material_mask_bits = fixed_mask; /* No need to split at the last point anyway. */ break; @@ -670,6 +710,7 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartData *ld) eci->line_type, fixed_occ, fixed_mask, + fixed_shadow, eci->index); new_ec->object_ref = ec->object_ref; new_ec->type = ec->type; @@ -677,13 +718,16 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartData *ld) ec = new_ec; fixed_occ = eci->occlusion; fixed_mask = eci->material_mask_bits; + fixed_shadow = eci->shadow_mask_bits; ec->level = fixed_occ; ec->material_mask_bits = fixed_mask; + ec->shadow_mask_bits = fixed_shadow; } } } - /* Get rid of those very short "zig-zag" lines that jumps around visibility. */ - MOD_lineart_chain_discard_short(ld, DBL_EDGE_LIM); + + MOD_lineart_chain_discard_unused(ld, DBL_EDGE_LIM, ld->conf.max_occlusion_level); + LISTBASE_FOREACH (LineartEdgeChain *, iec, &ld->chains) { lineart_bounding_area_link_chain(ld, iec); } @@ -749,6 +793,7 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartData *ld, int occlusion, uint8_t material_mask_bits, uint8_t isec_mask, + uint32_t shadow_mask, int loop_id, float dist, float *result_new_len, @@ -779,7 +824,7 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartData *ld, } if (cre->ec == ec || (!cre->ec->chain.first) || (cre->ec->level != occlusion) || (cre->ec->material_mask_bits != material_mask_bits) || - (cre->ec->intersection_mask != isec_mask)) { + (cre->ec->intersection_mask != isec_mask) || (cre->ec->shadow_mask_bits != shadow_mask)) { continue; } if (!ld->conf.fuzzy_everything) { @@ -826,6 +871,7 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartData *ld, occlusion, \ material_mask_bits, \ isec_mask, \ + shadow_mask, \ loop_id, \ dist, \ &adjacent_new_len, \ @@ -856,8 +902,9 @@ void MOD_lineart_chain_connect(LineartData *ld) LineartChainRegisterEntry *closest_cre_l, *closest_cre_r, *closest_cre; float dist = ld->conf.chaining_image_threshold; float dist_l, dist_r; - int occlusion, reverse_main, loop_id; - uint8_t material_mask_bits, isec_mask; + int reverse_main, loop_id; + uint8_t occlusion, material_mask_bits, isec_mask; + uint32_t shadow_mask; ListBase swap = {0}; if (ld->conf.chaining_image_threshold < 0.0001) { @@ -871,7 +918,7 @@ void MOD_lineart_chain_connect(LineartData *ld) while ((ec = BLI_pophead(&swap)) != NULL) { ec->next = ec->prev = NULL; - if (ec->picked) { + if (ec->picked || ec->chain.first == ec->chain.last) { continue; } BLI_addtail(&ld->chains, ec); @@ -884,6 +931,7 @@ void MOD_lineart_chain_connect(LineartData *ld) occlusion = ec->level; material_mask_bits = ec->material_mask_bits; isec_mask = ec->intersection_mask; + shadow_mask = ec->shadow_mask_bits; eci_l = ec->chain.first; eci_r = ec->chain.last; @@ -896,6 +944,7 @@ void MOD_lineart_chain_connect(LineartData *ld) occlusion, material_mask_bits, isec_mask, + shadow_mask, loop_id, dist, &dist_l, @@ -907,6 +956,7 @@ void MOD_lineart_chain_connect(LineartData *ld) occlusion, material_mask_bits, isec_mask, + shadow_mask, loop_id, dist, &dist_r, @@ -969,12 +1019,14 @@ float MOD_lineart_chain_compute_length(LineartEdgeChain *ec) return offset_accum; } -void MOD_lineart_chain_discard_short(LineartData *ld, const float threshold) +void MOD_lineart_chain_discard_unused(LineartData *ld, + const float threshold, + uint8_t max_occlusion) { LineartEdgeChain *ec, *next_ec; for (ec = ld->chains.first; ec; ec = next_ec) { next_ec = ec->next; - if (MOD_lineart_chain_compute_length(ec) < threshold) { + if (ec->level > max_occlusion || MOD_lineart_chain_compute_length(ec) < threshold) { BLI_remlink(&ld->chains, ec); } } @@ -999,6 +1051,38 @@ void MOD_lineart_chain_clear_picked_flag(LineartCache *lc) } } +LineartElementLinkNode *lineart_find_matching_eln_obj(ListBase *elns, struct Object *obj) +{ + LISTBASE_FOREACH (LineartElementLinkNode *, eln, elns) { + if (eln->object_ref == obj) { + return eln; + } + } + return NULL; +} + +void MOD_lineart_finalize_chains(LineartData *ld) +{ + LISTBASE_FOREACH (LineartEdgeChain *, ec, &ld->chains) { + if (ELEM(ec->type, + LRT_EDGE_FLAG_INTERSECTION, + LRT_EDGE_FLAG_PROJECTED_SHADOW, + LRT_EDGE_FLAG_LIGHT_CONTOUR)) { + continue; + } + LineartElementLinkNode *eln = lineart_find_matching_eln_obj(&ld->geom.vertex_buffer_pointers, + ec->object_ref); + BLI_assert(eln != NULL); + if (LIKELY(eln)) { + LISTBASE_FOREACH (LineartEdgeChainItem *, eci, &ec->chain) { + if (eci->index > eln->global_index_offset) { + eci->index -= eln->global_index_offset; + } + } + } + } +} + void MOD_lineart_smooth_chains(LineartData *ld, float tolerance) { LISTBASE_FOREACH (LineartEdgeChain *, ec, &ld->chains) { @@ -1072,20 +1156,22 @@ static LineartEdgeChainItem *lineart_chain_create_crossing_point(LineartData *ld LineartEdgeChainItem *eci_outside) { float isec[2]; - float LU[2] = {-1.0f, 1.0f}, LB[2] = {-1.0f, -1.0f}, RU[2] = {1.0f, 1.0f}, RB[2] = {1.0f, -1.0f}; + /* l: left, r: right, b: bottom, u: top. */ + float ref_lu[2] = {-1.0f, 1.0f}, ref_lb[2] = {-1.0f, -1.0f}, ref_ru[2] = {1.0f, 1.0f}, + ref_rb[2] = {1.0f, -1.0f}; bool found = false; LineartEdgeChainItem *eci2 = eci_outside, *eci1 = eci_inside; if (eci2->pos[0] < -1.0f) { - found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, LU, LB, isec) > 0); + found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, ref_lu, ref_lb, isec) > 0); } if (!found && eci2->pos[0] > 1.0f) { - found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, RU, RB, isec) > 0); + found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, ref_ru, ref_rb, isec) > 0); } if (!found && eci2->pos[1] < -1.0f) { - found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, LB, RB, isec) > 0); + found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, ref_lb, ref_rb, isec) > 0); } if (!found && eci2->pos[1] > 1.0f) { - found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, LU, RU, isec) > 0); + found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, ref_lu, ref_ru, isec) > 0); } if (UNLIKELY(!found)) { @@ -1126,7 +1212,7 @@ void MOD_lineart_chain_clip_at_border(LineartData *ld) LineartEdgeChainItem *first_eci = (LineartEdgeChainItem *)ec->chain.first; is_inside = LRT_ECI_INSIDE(first_eci) ? true : false; if (!is_inside) { - ec->picked = true; + ec->picked = 1; } for (eci = first_eci->next; eci; eci = next_eci) { next_eci = eci->next; @@ -1219,6 +1305,7 @@ void MOD_lineart_chain_split_angle(LineartData *ld, float angle_threshold_rad) eci->line_type, ec->level, eci->material_mask_bits, + eci->shadow_mask_bits, eci->index); new_ec->object_ref = ec->object_ref; new_ec->type = ec->type; @@ -1226,6 +1313,7 @@ void MOD_lineart_chain_split_angle(LineartData *ld, float angle_threshold_rad) new_ec->loop_id = ec->loop_id; new_ec->intersection_mask = ec->intersection_mask; new_ec->material_mask_bits = ec->material_mask_bits; + new_ec->shadow_mask_bits = ec->shadow_mask_bits; ec = new_ec; } } @@ -1270,3 +1358,19 @@ void MOD_lineart_chain_offset_towards_camera(LineartData *ld, float dist, bool u } } } + +void MOD_lineart_chain_find_silhouette_backdrop_objects(LineartData *ld) +{ + LISTBASE_FOREACH (LineartEdgeChain *, ec, &ld->chains) { + if (ec->type == LRT_EDGE_FLAG_CONTOUR && + ec->shadow_mask_bits & LRT_SHADOW_SILHOUETTE_ERASED_GROUP) { + uint32_t target = ec->shadow_mask_bits & LRT_OBINDEX_HIGHER; + LineartElementLinkNode *eln = lineart_find_matching_eln(&ld->geom.line_buffer_pointers, + target); + if (!eln) { + continue; + } + ec->silhouette_backdrop = eln->object_ref; + } + } +} |