diff options
Diffstat (limited to 'source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c')
-rw-r--r-- | source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c | 170 |
1 files changed, 123 insertions, 47 deletions
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index dffa6fce395..f2d1f6776ab 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -430,6 +430,7 @@ static int lineart_occlusion_make_task_info(LineartRenderBuffer *rb, LineartRend LRT_ASSIGN_OCCLUSION_TASK(crease); LRT_ASSIGN_OCCLUSION_TASK(material); LRT_ASSIGN_OCCLUSION_TASK(edge_mark); + LRT_ASSIGN_OCCLUSION_TASK(floating); #undef LRT_ASSIGN_OCCLUSION_TASK @@ -464,6 +465,10 @@ static void lineart_occlusion_worker(TaskPool *__restrict UNUSED(pool), LineartR for (eip = rti->edge_mark.first; eip && eip != rti->edge_mark.last; eip = eip->next) { lineart_occlusion_single_line(rb, eip, rti->thread_id); } + + for (eip = rti->floating.first; eip && eip != rti->floating.last; eip = eip->next) { + lineart_occlusion_single_line(rb, eip, rti->thread_id); + } } } @@ -486,6 +491,7 @@ static void lineart_main_occlusion_begin(LineartRenderBuffer *rb) rb->intersection.last = rb->intersection.first; rb->material.last = rb->material.first; rb->edge_mark.last = rb->edge_mark.first; + rb->floating.last = rb->floating.first; TaskPool *tp = BLI_task_pool_create(NULL, TASK_PRIORITY_HIGH); @@ -720,6 +726,7 @@ static void lineart_triangle_post(LineartTriangle *tri, LineartTriangle *orig) /* Just re-assign normal and set cull flag. */ copy_v3_v3_db(tri->gn, orig->gn); tri->flags = LRT_CULL_GENERATED; + tri->transparency_mask = orig->transparency_mask; } static void lineart_triangle_set_cull_flag(LineartTriangle *tri, uchar flag) @@ -735,6 +742,16 @@ static bool lineart_edge_match(LineartTriangle *tri, LineartEdge *e, int v1, int (tri->v[v2] == e->v1 && tri->v[v1] == e->v2)); } +static void lineart_discard_duplicated_edges(LineartEdge *old_e, int v1id, int v2id) +{ + LineartEdge *e = old_e; + e++; + while (e->v1_obindex == v1id && e->v2_obindex == v2id) { + e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED; + e++; + } +} + /** * Does near-plane cut on 1 triangle only. When cutting with far-plane, the camera vectors gets * reversed by the caller so don't need to implement one in a different direction. @@ -800,6 +817,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb, old_e = ta->e[e_num]; \ new_flag = old_e->flags; \ old_e->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \ + lineart_discard_duplicated_edges(old_e, old_e->v1_obindex, old_e->v2_obindex); \ INCREASE_EDGE \ e->v1 = (v1_link); \ e->v2 = (v2_link); \ @@ -820,12 +838,15 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb, #define REMOVE_TRIANGLE_EDGE \ if (ta->e[0]) { \ ta->e[0]->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \ + lineart_discard_duplicated_edges(ta->e[0], ta->e[0]->v1_obindex, ta->e[0]->v2_obindex); \ } \ if (ta->e[1]) { \ ta->e[1]->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \ + lineart_discard_duplicated_edges(ta->e[1], ta->e[1]->v1_obindex, ta->e[1]->v2_obindex); \ } \ if (ta->e[2]) { \ ta->e[2]->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \ + lineart_discard_duplicated_edges(ta->e[2], ta->e[2]->v1_obindex, ta->e[2]->v2_obindex); \ } switch (in0 + in1 + in2) { @@ -1432,8 +1453,25 @@ static char lineart_identify_feature_line(LineartRenderBuffer *rb, lr = e->l->radial_next; } - if (ll == lr || !lr) { - return LRT_EDGE_FLAG_CONTOUR; + if (!ll && !lr) { + if (!rb->floating_as_contour) { + return LRT_EDGE_FLAG_FLOATING; + } + } + + uint16_t edge_flag_result = 0; + + if (count_freestyle && rb->use_edge_marks) { + FreestyleEdge *fe; + fe = CustomData_bmesh_get(&bm_if_freestyle->edata, e->head.data, CD_FREESTYLE_EDGE); + if (fe->flag & FREESTYLE_EDGE_MARK) { + edge_flag_result |= LRT_EDGE_FLAG_EDGE_MARK; + } + } + + /* Mesh boundary */ + if (!lr || ll == lr) { + return (edge_flag_result | LRT_EDGE_FLAG_CONTOUR); } LineartTriangle *tri1, *tri2; @@ -1449,7 +1487,6 @@ static char lineart_identify_feature_line(LineartRenderBuffer *rb, double *view_vector = vv; double dot_1 = 0, dot_2 = 0; double result; - FreestyleEdge *fe; if (rb->cam_is_persp) { sub_v3_v3v3_db(view_vector, l->gloc, rb->camera_pos); @@ -1462,24 +1499,20 @@ static char lineart_identify_feature_line(LineartRenderBuffer *rb, dot_2 = dot_v3v3_db(view_vector, tri2->gn); if ((result = dot_1 * dot_2) <= 0 && (dot_1 + dot_2)) { - return LRT_EDGE_FLAG_CONTOUR; + edge_flag_result |= LRT_EDGE_FLAG_CONTOUR; } if (rb->use_crease && (dot_v3v3_db(tri1->gn, tri2->gn) < crease_threshold)) { if (!no_crease) { - return LRT_EDGE_FLAG_CREASE; + edge_flag_result |= LRT_EDGE_FLAG_CREASE; } } - else if (rb->use_material && (ll->f->mat_nr != lr->f->mat_nr)) { - return LRT_EDGE_FLAG_MATERIAL; - } - else if (count_freestyle && rb->use_edge_marks) { - fe = CustomData_bmesh_get(&bm_if_freestyle->edata, e->head.data, CD_FREESTYLE_EDGE); - if (fe->flag & FREESTYLE_EDGE_MARK) { - return LRT_EDGE_FLAG_EDGE_MARK; - } + + if (rb->use_material && (ll->f->mat_nr != lr->f->mat_nr)) { + edge_flag_result |= LRT_EDGE_FLAG_MATERIAL; } - return 0; + + return edge_flag_result; } static void lineart_add_edge_to_list(LineartRenderBuffer *rb, LineartEdge *e) @@ -1527,6 +1560,9 @@ static void lineart_add_edge_to_list_thread(LineartObjectInfo *obi, LineartEdge case LRT_EDGE_FLAG_INTERSECTION: LRT_ASSIGN_EDGE(intersection); break; + case LRT_EDGE_FLAG_FLOATING: + LRT_ASSIGN_EDGE(floating); + break; } #undef LRT_ASSIGN_EDGE } @@ -1543,6 +1579,7 @@ static void lineart_finalize_object_edge_list(LineartRenderBuffer *rb, LineartOb LRT_OBI_TO_RB(material); LRT_OBI_TO_RB(edge_mark); LRT_OBI_TO_RB(intersection); + LRT_OBI_TO_RB(floating); #undef LRT_OBI_TO_RB } @@ -1561,6 +1598,17 @@ static void lineart_triangle_adjacent_assign(LineartTriangle *tri, } } +static int lineart_edge_type_duplication_count(char eflag) +{ + int count = 0; + /* See eLineartEdgeFlag for details. */ + for (int i = 0; i < LRT_EDGE_FLAG_FLOATING; i++) { + if (eflag & (1 << i)) { + count++; + } + } + return count; +} static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBuffer *rb) { BMesh *bm; @@ -1639,8 +1687,9 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu CanFindFreestyle = 1; } - /* Only allocate memory for verts and tris as we don't know how many lines we will generate - * yet. */ + /* If we allow duplicated edges, one edge should get added multiple times if is has been + * classified as more than one edge type. This is so we can create multiple different line type + * chains containing the same edge. */ orv = lineart_mem_acquire_thread(&rb->render_data_pool, sizeof(LineartVert) * bm->totvert); ort = lineart_mem_acquire_thread(&rb->render_data_pool, bm->totface * rb->triangle_size); @@ -1653,7 +1702,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu eln->element_count = bm->totvert; eln->object_ref = orig_ob; - obi->v_reln = eln; + obi->v_eln = eln; if (orig_ob->lineart.flags & OBJECT_LRT_OWN_CREASE) { use_crease = cosf(M_PI - orig_ob->lineart.crease_threshold); @@ -1741,8 +1790,9 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu char eflag = lineart_identify_feature_line( rb, e, ort, orv, use_crease, orig_ob->type == OB_FONT, CanFindFreestyle, bm); if (eflag) { - /* Only allocate for feature lines (instead of all lines) to save memory. */ - allocate_la_e++; + /* Only allocate for feature lines (instead of all lines) to save memory. + * If allow duplicated edges, one edge gets added multiple times if it has multiple types. */ + allocate_la_e += rb->allow_duplicated_types ? lineart_edge_type_duplication_count(eflag) : 1; } /* Here we just use bm's flag for when loading actual lines, then we don't need to call * lineart_identify_feature_line() again, e->head.hflag deleted after loading anyway. Always @@ -1770,30 +1820,50 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu continue; } - la_e->v1 = &orv[BM_elem_index_get(e->v1)]; - la_e->v2 = &orv[BM_elem_index_get(e->v2)]; - la_e->v1_obindex = la_e->v1->index; - la_e->v2_obindex = la_e->v2->index; - if (e->l) { - int findex = BM_elem_index_get(e->l->f); - la_e->t1 = lineart_triangle_from_index(rb, ort, findex); - lineart_triangle_adjacent_assign(la_e->t1, &orta[findex], la_e); - if (e->l->radial_next && e->l->radial_next != e->l) { - findex = BM_elem_index_get(e->l->radial_next->f); - la_e->t2 = lineart_triangle_from_index(rb, ort, findex); - lineart_triangle_adjacent_assign(la_e->t2, &orta[findex], la_e); + bool edge_added = false; + + /* See eLineartEdgeFlag for details. */ + for (int flag_bit = 0; flag_bit < LRT_EDGE_FLAG_FLOATING; flag_bit++) { + char use_type = 1 << flag_bit; + if (!(use_type & e->head.hflag)) { + continue; } - } - la_e->flags = e->head.hflag; - la_e->object_ref = orig_ob; - BLI_addtail(&la_e->segments, la_s); - if (usage == OBJECT_LRT_INHERIT || usage == OBJECT_LRT_INCLUDE || - usage == OBJECT_LRT_NO_INTERSECTION) { - lineart_add_edge_to_list_thread(obi, la_e); - } - la_e++; - la_s++; + la_e->v1 = &orv[BM_elem_index_get(e->v1)]; + la_e->v2 = &orv[BM_elem_index_get(e->v2)]; + la_e->v1_obindex = la_e->v1->index; + la_e->v2_obindex = la_e->v2->index; + if (e->l) { + int findex = BM_elem_index_get(e->l->f); + la_e->t1 = lineart_triangle_from_index(rb, ort, findex); + if (!edge_added) { + lineart_triangle_adjacent_assign(la_e->t1, &orta[findex], la_e); + } + if (e->l->radial_next && e->l->radial_next != e->l) { + findex = BM_elem_index_get(e->l->radial_next->f); + la_e->t2 = lineart_triangle_from_index(rb, ort, findex); + if (!edge_added) { + lineart_triangle_adjacent_assign(la_e->t2, &orta[findex], la_e); + } + } + } + la_e->flags = use_type; + la_e->object_ref = orig_ob; + BLI_addtail(&la_e->segments, la_s); + if (usage == OBJECT_LRT_INHERIT || usage == OBJECT_LRT_INCLUDE || + usage == OBJECT_LRT_NO_INTERSECTION) { + lineart_add_edge_to_list_thread(obi, la_e); + } + + edge_added = true; + + la_e++; + la_s++; + + if (!rb->allow_duplicated_types) { + break; + } + } } /* always free bm as it's a copy from before threading */ @@ -1803,9 +1873,8 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu static void lineart_object_load_worker(TaskPool *__restrict UNUSED(pool), LineartObjectLoadTaskInfo *olti) { - LineartRenderBuffer *rb = olti->rb; for (LineartObjectInfo *obi = olti->pending; obi; obi = obi->next) { - lineart_geometry_object_load(obi, rb); + lineart_geometry_object_load(obi, olti->rb); } } @@ -1948,7 +2017,6 @@ static void lineart_main_load_geometries( { double proj[4][4], view[4][4], result[4][4]; float inv[4][4]; - Camera *cam = camera->data; float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); int fit = BKE_camera_sensor_fit(cam->sensor_fit, rb->w, rb->h); @@ -2071,11 +2139,11 @@ static void lineart_main_load_geometries( for (int i = 0; i < thread_count; i++) { for (LineartObjectInfo *obi = olti[i].pending; obi; obi = obi->next) { - if (!obi->v_reln) { + if (!obi->v_eln) { continue; } - LineartVert *v = (LineartVert *)obi->v_reln->pointer; - int v_count = obi->v_reln->element_count; + LineartVert *v = (LineartVert *)obi->v_eln->pointer; + int v_count = obi->v_eln->element_count; for (int vi = 0; vi < v_count; vi++) { v[vi].index += global_i; } @@ -2823,6 +2891,7 @@ static void lineart_destroy_render_data(LineartRenderBuffer *rb) memset(&rb->intersection, 0, sizeof(ListBase)); memset(&rb->edge_mark, 0, sizeof(ListBase)); memset(&rb->material, 0, sizeof(ListBase)); + memset(&rb->floating, 0, sizeof(ListBase)); BLI_listbase_clear(&rb->chains); BLI_listbase_clear(&rb->wasted_cuts); @@ -2919,10 +2988,15 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene, rb->fuzzy_everything = (lmd->calculation_flags & LRT_EVERYTHING_AS_CONTOUR) != 0; rb->allow_boundaries = (lmd->calculation_flags & LRT_ALLOW_CLIPPING_BOUNDARIES) != 0; rb->remove_doubles = (lmd->calculation_flags & LRT_REMOVE_DOUBLES) != 0; + rb->floating_as_contour = (lmd->calculation_flags & LRT_FLOATING_AS_CONTOUR) != 0; + rb->chain_floating_edges = (lmd->calculation_flags & LRT_CHAIN_FLOATING_EDGES) != 0; + rb->chain_geometry_space = (lmd->calculation_flags & LRT_CHAIN_GEOMETRY_SPACE) != 0; /* See lineart_edge_from_triangle() for how this option may impact performance. */ rb->allow_overlapping_edges = (lmd->calculation_flags & LRT_ALLOW_OVERLAPPING_EDGES) != 0; + rb->allow_duplicated_types = (lmd->calculation_flags & LRT_ALLOW_OVERLAP_EDGE_TYPES) != 0; + int16_t edge_types = lmd->edge_types_override; rb->use_contour = (edge_types & LRT_EDGE_FLAG_CONTOUR) != 0; @@ -2930,6 +3004,7 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene, rb->use_material = (edge_types & LRT_EDGE_FLAG_MATERIAL) != 0; rb->use_edge_marks = (edge_types & LRT_EDGE_FLAG_EDGE_MARK) != 0; rb->use_intersections = (edge_types & LRT_EDGE_FLAG_INTERSECTION) != 0; + rb->use_floating = (edge_types & LRT_EDGE_FLAG_FLOATING) != 0; rb->chain_data_pool = &lc->chain_data_pool; @@ -4043,6 +4118,7 @@ static int UNUSED_FUNCTION(lineart_rb_edge_types)(LineartRenderBuffer *rb) types |= rb->use_material ? LRT_EDGE_FLAG_MATERIAL : 0; types |= rb->use_edge_marks ? LRT_EDGE_FLAG_EDGE_MARK : 0; types |= rb->use_intersections ? LRT_EDGE_FLAG_INTERSECTION : 0; + types |= rb->use_floating ? LRT_EDGE_FLAG_FLOATING : 0; return types; } |