diff options
author | YimingWu <xp8110@outlook.com> | 2021-03-18 05:01:18 +0300 |
---|---|---|
committer | Sebastian Parborg <darkdefende@gmail.com> | 2021-03-18 14:42:41 +0300 |
commit | c114c78f57458ca88b33c1fcf94f1cf78cd51b9f (patch) | |
tree | 912392588431c4e625238d00798253d0665f96b4 /source/blender | |
parent | df280637952d35cfaa74e31f03a0d825b22eddf4 (diff) |
LineArt: Do not calculate lines for objects not included
Only use non included objects for potential occlusion queries.
Don't calculate lines for them.
This fixes intersection lines appearing on objects not included by the
lineart modifier.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h | 17 | ||||
-rw-r--r-- | source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c | 95 |
2 files changed, 81 insertions, 31 deletions
diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h index c523809a4ad..97f4459072f 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h +++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h @@ -193,7 +193,7 @@ typedef struct LineartChainRegisterEntry { LineartLineChainItem *rlci; char picked; - /** left/right mark. + /* left/right mark. * Because we revert list in chaining so we need the flag. */ char is_left; } LineartChainRegisterEntry; @@ -220,7 +220,7 @@ typedef struct LineartRenderBuffer { ListBase triangle_adjacent_pointers; ListBase intersecting_vertex_buffer; - /** Use the one comes with Line Art. */ + /* Use the one comes with Line Art. */ LineartStaticMemPool render_data_pool; ListBase wasted_cuts; SpinLock lock_cuts; @@ -258,7 +258,7 @@ typedef struct LineartRenderBuffer { ListBase chains; - /** For managing calculation tasks for multiple threads. */ + /* For managing calculation tasks for multiple threads. */ SpinLock lock_task; /* settings */ @@ -281,7 +281,7 @@ typedef struct LineartRenderBuffer { bool allow_overlapping_edges; bool remove_doubles; - /** Keep an copy of these data so when line art is running it's self-contained. */ + /* Keep an copy of these data so when line art is running it's self-contained. */ bool cam_is_persp; float cam_obmat[4][4]; double camera_pos[3]; @@ -291,6 +291,15 @@ typedef struct LineartRenderBuffer { float chaining_image_threshold; float chaining_geometry_threshold; float angle_splitting_threshold; + + /* FIXME: (Yiming) Temporary solution for speeding up calculation by not including lines that + * are not in the selected source. This will not be needed after we have a proper scene-wise + * cache running because multiple modifiers can then select results from that without further + * calculation. */ + int _source_type; + struct Collection *_source_collection; + struct Object *_source_object; + } LineartRenderBuffer; #define DBL_TRIANGLE_LIM 1e-8 diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index 6c638478983..41b269c836d 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -1719,18 +1719,35 @@ static void lineart_geometry_object_load(Depsgraph *dg, #undef LRT_MESH_FINISH } +static bool _lineart_object_not_in_source_collection(Collection *source, Object *ob) +{ + CollectionChild *cc; + Collection *c = source->id.orig_id ? (Collection *)source->id.orig_id : source; + if (BKE_collection_has_object(c, (Object *)(ob->id.orig_id))) { + return false; + } + for (cc = source->children.first; cc; cc = cc->next) { + if (!_lineart_object_not_in_source_collection(cc->collection, ob)) { + return false; + } + } + return true; +} + /* See if this object in such collection is used for generating line art, - * Disabling a collection for line art will diable all objects inside. */ -static int lineart_usage_check(Collection *c, Object *ob) + * Disabling a collection for line art will diable 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) { if (!c) { return OBJECT_LRT_INHERENT; } - int object_is_used = (ob->lineart.usage != OBJECT_LRT_INHERENT); + int object_has_special_usage = (ob->lineart.usage != OBJECT_LRT_INHERENT); - if (object_is_used) { + if (object_has_special_usage) { return ob->lineart.usage; } @@ -1755,12 +1772,25 @@ static int lineart_usage_check(Collection *c, Object *ob) } LISTBASE_FOREACH (CollectionChild *, cc, &c->children) { - int result = lineart_usage_check(cc->collection, ob); + int result = lineart_usage_check(cc->collection, ob, _rb); if (result > OBJECT_LRT_INHERENT) { 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) { + 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_INHERENT; } @@ -1813,7 +1843,7 @@ static void lineart_main_load_geometries( int global_i = 0; DEG_OBJECT_ITER_BEGIN (depsgraph, ob, flags) { - int usage = lineart_usage_check(scene->master_collection, ob); + int usage = lineart_usage_check(scene->master_collection, ob, rb); lineart_geometry_object_load(depsgraph, ob, view, proj, rb, usage, &global_i); } @@ -2228,8 +2258,10 @@ static void lineart_vert_set_intersection_2v(LineartVert *rv, LineartVert *v1, L irv->isec2 = v2->index; } -/* This tests a triangle against a virtual line represented by v1---v2. The vertices returned after - * repeated calls to this function is then used to create a triangle/triangle intersection line. */ +/* This tests a triangle against a virtual line represented by v1---v2. The vertices returned + * after + * repeated calls to this function is then used to create a triangle/triangle intersection line. + */ static LineartVert *lineart_triangle_2v_intersection_test(LineartRenderBuffer *rb, LineartVert *v1, LineartVert *v2, @@ -2268,7 +2300,8 @@ static LineartVert *lineart_triangle_2v_intersection_test(LineartRenderBuffer *r interp_v3_v3v3_db(gloc, l->gloc, r->gloc, dot_l / (dot_l + dot_r)); - /* Due to precision issue, we might end up with the same point as the one we already detected. */ + /* Due to precision issue, we might end up with the same point as the one we already detected. + */ if (last && LRT_DOUBLE_CLOSE_ENOUGH(last->gloc[0], gloc[0]) && LRT_DOUBLE_CLOSE_ENOUGH(last->gloc[1], gloc[1]) && LRT_DOUBLE_CLOSE_ENOUGH(last->gloc[2], gloc[2])) { @@ -2401,8 +2434,8 @@ static LineartEdge *lineart_triangle_intersect(LineartRenderBuffer *rb, } } - /* The intersection line has been generated only in geometry space, so we need to transform them - * as well. */ + /* The intersection line has been generated only in geometry space, so we need to transform + * them as well. */ mul_v4_m4v3_db(v1->fbcoord, rb->view_projection, v1->gloc); mul_v4_m4v3_db(v2->fbcoord, rb->view_projection, v2->gloc); mul_v3db_db(v1->fbcoord, (1 / v1->fbcoord[3])); @@ -2476,25 +2509,28 @@ static void lineart_triangle_intersect_in_bounding_area(LineartRenderBuffer *rb, testing_triangle = lip->data; rtt = (LineartTriangleThread *)testing_triangle; - if (testing_triangle == rt || rtt->testing_e[0] == (LineartEdge *)rt || - (testing_triangle->flags & LRT_TRIANGLE_NO_INTERSECTION) || + if (testing_triangle == rt || rtt->testing_e[0] == (LineartEdge *)rt) { + continue; + } + rtt->testing_e[0] = (LineartEdge *)rt; + + if ((testing_triangle->flags & LRT_TRIANGLE_NO_INTERSECTION) || ((testing_triangle->flags & LRT_TRIANGLE_INTERSECTION_ONLY) && - (rt->flags & LRT_TRIANGLE_INTERSECTION_ONLY)) || - lineart_triangle_share_edge(rt, testing_triangle)) { + (rt->flags & LRT_TRIANGLE_INTERSECTION_ONLY))) { continue; } - rtt->testing_e[0] = (LineartEdge *)rt; double *RG0 = testing_triangle->v[0]->gloc, *RG1 = testing_triangle->v[1]->gloc, *RG2 = testing_triangle->v[2]->gloc; - /* Bounding box not overlapping, not potential of intersecting. */ + /* Bounding box not overlapping or triangles share edges, not potential of intersecting. */ if ((MIN3(G0[2], G1[2], G2[2]) > MAX3(RG0[2], RG1[2], RG2[2])) || (MAX3(G0[2], G1[2], G2[2]) < MIN3(RG0[2], RG1[2], RG2[2])) || (MIN3(G0[0], G1[0], G2[0]) > MAX3(RG0[0], RG1[0], RG2[0])) || (MAX3(G0[0], G1[0], G2[0]) < MIN3(RG0[0], RG1[0], RG2[0])) || (MIN3(G0[1], G1[1], G2[1]) > MAX3(RG0[1], RG1[1], RG2[1])) || - (MAX3(G0[1], G1[1], G2[1]) < MIN3(RG0[1], RG1[1], RG2[1]))) { + (MAX3(G0[1], G1[1], G2[1]) < MIN3(RG0[1], RG1[1], RG2[1])) || + lineart_triangle_share_edge(rt, testing_triangle)) { continue; } @@ -3581,6 +3617,11 @@ int MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModifi * occlusion levels will get ignored. */ rb->max_occlusion_level = MAX2(lmd->level_start, lmd->level_end); + /* FIXME: (Yiming) See definition of int LineartRenderBuffer::_source_type for detailes. */ + rb->_source_type = lmd->source_type; + rb->_source_collection = lmd->source_collection; + rb->_source_object = lmd->source_object; + /* Get view vector before loading geometries, because we detect feature lines there. */ lineart_main_get_view_vector(rb); lineart_main_load_geometries( @@ -3608,13 +3649,13 @@ int MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModifi lineart_main_perspective_division(rb); /* Triangle intersections are done here during sequential adding of them. Only after this, - * triangles and lines are all linked with acceleration structure, and the 2D occlusion stage can - * do its job. */ + * triangles and lines are all linked with acceleration structure, and the 2D occlusion stage + * can do its job. */ lineart_main_add_triangles(rb); - /* Link lines to acceleration structure, this can only be done after perspective division, if we - * do it after triangles being added, the acceleration structure has already been subdivided, - * this way we do less list manipulations. */ + /* Link lines to acceleration structure, this can only be done after perspective division, if + * we do it after triangles being added, the acceleration structure has already been + * subdivided, this way we do less list manipulations. */ lineart_main_link_lines(rb); /* "intersection_only" is preserved for being called in a standalone fashion. @@ -3627,12 +3668,12 @@ int MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModifi lineart_main_occlusion_begin(rb); /* Chaining is all single threaded. See lineart_chain.c - * In this particular call, only lines that are geometrically connected (share the _exact_ same - * end point) will be chained together. */ + * In this particular call, only lines that are geometrically connected (share the _exact_ + * same end point) will be chained together. */ MOD_lineart_chain_feature_lines(rb); - /* We are unable to take care of occlusion if we only connect end points, so here we do a spit, - * where the splitting point could be any cut in e->segments. */ + /* We are unable to take care of occlusion if we only connect end points, so here we do a + * spit, where the splitting point could be any cut in e->segments. */ MOD_lineart_chain_split_for_fixed_occlusion(rb); /* Then we connect chains based on the _proximity_ of their end points in geometry or image |