From 870ad7d05db2e14164d818cd5320345fd8110a69 Mon Sep 17 00:00:00 2001 From: YimingWu Date: Sat, 14 May 2022 00:03:40 +0800 Subject: Fix T96781: LineArt proper object iterator. This patch get rid of the _incorrectly used_ DG iterator in object loading, and uses scene objects iteration to prevent problems. Reviewed By: Sebastian Parborg (zeddb) Differential Revision: https://developer.blender.org/D14907 --- .../gpencil_modifiers/intern/MOD_gpencillineart.c | 25 ++-- .../gpencil_modifiers/intern/lineart/lineart_cpu.c | 144 +++++++++++---------- 2 files changed, 93 insertions(+), 76 deletions(-) (limited to 'source') diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c index 0e7df2a136d..a07ef2eb195 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c @@ -218,9 +218,18 @@ static void add_this_collection(Collection *c, if (!c) { return; } + bool default_add = true; + /* Do not do nested collection usage check, this is consistent with lineart calculation, because + * collection usage doesn't have a INHERIT mode. This might initially be derived from the fact + * that an object can be inside multiple collections, but might be irrelevant now with the way + * objects are iterated. Keep this logic for now. */ + if (c->lineart_usage & COLLECTION_LRT_EXCLUDE) { + default_add = false; + } FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (c, ob, mode) { if (ELEM(ob->type, OB_MESH, OB_MBALL, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) { - if (ob->lineart.usage != OBJECT_LRT_EXCLUDE) { + if ((ob->lineart.usage == OBJECT_LRT_INHERIT && default_add) || + ob->lineart.usage != OBJECT_LRT_EXCLUDE) { DEG_add_object_relation(ctx->node, ob, DEG_OB_COMP_GEOMETRY, "Line Art Modifier"); DEG_add_object_relation(ctx->node, ob, DEG_OB_COMP_TRANSFORM, "Line Art Modifier"); } @@ -239,15 +248,11 @@ static void updateDepsgraph(GpencilModifierData *md, DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Line Art Modifier"); LineartGpencilModifierData *lmd = (LineartGpencilModifierData *)md; - if (lmd->source_type == LRT_SOURCE_OBJECT && lmd->source_object) { - DEG_add_object_relation( - ctx->node, lmd->source_object, DEG_OB_COMP_GEOMETRY, "Line Art Modifier"); - DEG_add_object_relation( - ctx->node, lmd->source_object, DEG_OB_COMP_TRANSFORM, "Line Art Modifier"); - } - else { - add_this_collection(ctx->scene->master_collection, ctx, mode); - } + + /* Always add whole master collection because line art will need the whole scene for + * visibility computation. Line art exclusion is handled inside #add_this_collection. */ + add_this_collection(ctx->scene->master_collection, ctx, mode); + if (lmd->calculation_flags & LRT_USE_CUSTOM_CAMERA && lmd->source_camera) { DEG_add_object_relation( ctx->node, lmd->source_camera, DEG_OB_COMP_TRANSFORM, "Line Art Modifier"); diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index b09bb15ce81..11d368b819c 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -21,6 +21,7 @@ #include "BKE_collection.h" #include "BKE_customdata.h" #include "BKE_deform.h" +#include "BKE_duplilist.h" #include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_gpencil.h" @@ -2398,6 +2399,64 @@ static bool lineart_geometry_check_visible(double (*model_view_proj)[4], return true; } +static void lineart_object_load_single_instance(LineartRenderBuffer *rb, + Depsgraph *depsgraph, + Scene *scene, + Object *ob, + Object *ref_ob, + float use_mat[4][4], + bool is_render, + LineartObjectLoadTaskInfo *olti, + int thread_count) +{ + LineartObjectInfo *obi = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartObjectInfo)); + obi->usage = lineart_usage_check(scene->master_collection, ob, is_render); + obi->override_intersection_mask = lineart_intersection_mask_check(scene->master_collection, ob); + Mesh *use_mesh; + + if (obi->usage == OBJECT_LRT_EXCLUDE) { + return; + } + + /* Prepare the matrix used for transforming this specific object (instance). This has to be + * done before mesh boundbox check because the function needs that. */ + mul_m4db_m4db_m4fl_uniq(obi->model_view_proj, rb->view_projection, use_mat); + mul_m4db_m4db_m4fl_uniq(obi->model_view, rb->view, use_mat); + + if (!ELEM(ob->type, OB_MESH, OB_MBALL, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) { + return; + } + if (ob->type == OB_MESH) { + use_mesh = BKE_object_get_evaluated_mesh(ob); + } + else { + use_mesh = BKE_mesh_new_from_object(depsgraph, ob, true, true); + } + + /* In case we still can not get any mesh geometry data from the object */ + if (!use_mesh) { + return; + } + + if (!lineart_geometry_check_visible(obi->model_view_proj, rb->shift_x, rb->shift_y, use_mesh)) { + return; + } + + if (ob->type != OB_MESH) { + obi->free_use_mesh = true; + } + + /* Make normal matrix. */ + float imat[4][4]; + invert_m4_m4(imat, use_mat); + transpose_m4(imat); + copy_m4d_m4(obi->normal, imat); + + obi->original_me = use_mesh; + obi->original_ob = (ref_ob->id.orig_id ? (Object *)ref_ob->id.orig_id : (Object *)ref_ob); + lineart_geometry_load_assign_thread(olti, obi, thread_count, use_mesh->totpoly); +} + static void lineart_main_load_geometries( Depsgraph *depsgraph, Scene *scene, @@ -2446,14 +2505,6 @@ static void lineart_main_load_geometries( BLI_listbase_clear(&rb->triangle_buffer_pointers); BLI_listbase_clear(&rb->vertex_buffer_pointers); - int flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | - DEG_ITER_OBJECT_FLAG_VISIBLE; - - /* Instance duplicated & particles. */ - if (allow_duplicates) { - flags |= DEG_ITER_OBJECT_FLAG_DUPLI; - } - int thread_count = rb->thread_count; /* This memory is in render buffer memory pool. so we don't need to free those after loading. @@ -2461,73 +2512,34 @@ static void lineart_main_load_geometries( LineartObjectLoadTaskInfo *olti = lineart_mem_acquire( &rb->render_data_pool, sizeof(LineartObjectLoadTaskInfo) * thread_count); - bool is_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER; - - 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, is_render); - obi->override_intersection_mask = lineart_intersection_mask_check(scene->master_collection, - ob); - Mesh *use_mesh; - - if (obi->usage == OBJECT_LRT_EXCLUDE) { - continue; - } + eEvaluationMode eval_mode = DEG_get_mode(depsgraph); + bool is_render = eval_mode == DAG_EVAL_RENDER; - Object *use_ob = DEG_get_evaluated_object(depsgraph, ob); - /* Prepare the matrix used for transforming this specific object (instance). This has to be - * done before mesh boundbox check because the function needs that. */ - mul_m4db_m4db_m4fl_uniq(obi->model_view_proj, rb->view_projection, ob->obmat); - mul_m4db_m4db_m4fl_uniq(obi->model_view, rb->view, ob->obmat); + FOREACH_SCENE_OBJECT_BEGIN (scene, ob) { + Object *eval_ob = DEG_get_evaluated_object(depsgraph, ob); - if (!ELEM(use_ob->type, OB_MESH, OB_MBALL, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) { + if (!eval_ob) { continue; } - if (use_ob->type == OB_MESH) { - use_mesh = BKE_object_get_evaluated_mesh(use_ob); - } - else { - /* If DEG_ITER_OBJECT_FLAG_DUPLI is set, some curve objects may also have an evaluated mesh - * object in the list. To avoid adding duplicate geometry, ignore evaluated curve objects - * in those cases. */ - if (allow_duplicates && BKE_object_get_evaluated_mesh(ob) != NULL) { - continue; - } - use_mesh = BKE_mesh_new_from_object(depsgraph, use_ob, true, true); + if (BKE_object_visibility(eval_ob, eval_mode) & OB_VISIBLE_SELF) { + lineart_object_load_single_instance( + rb, depsgraph, scene, eval_ob, eval_ob, eval_ob->obmat, is_render, olti, thread_count); } - - /* In case we still can not get any mesh geometry data from the object */ - if (!use_mesh) { - continue; - } - - if (!lineart_geometry_check_visible( - obi->model_view_proj, rb->shift_x, rb->shift_y, use_mesh)) { - if (ob->type != OB_MESH) { - BKE_id_free(NULL, use_mesh); - } - if (G.debug_value == 4000) { - bound_box_discard_count++; + if (allow_duplicates) { + ListBase *dupli = object_duplilist(depsgraph, scene, eval_ob); + LISTBASE_FOREACH (DupliObject *, dob, dupli) { + if (BKE_object_visibility(eval_ob, eval_mode) & + (OB_VISIBLE_PARTICLES | OB_VISIBLE_INSTANCES)) { + Object *ob_ref = (dob->type & OB_DUPLIPARTS) ? eval_ob : dob->ob; + lineart_object_load_single_instance( + rb, depsgraph, scene, dob->ob, ob_ref, dob->mat, is_render, olti, thread_count); + } } - continue; - } - - if (ob->type != OB_MESH) { - obi->free_use_mesh = true; + free_object_duplilist(dupli); } - - /* Make normal matrix. */ - float imat[4][4]; - invert_m4_m4(imat, ob->obmat); - transpose_m4(imat); - copy_m4d_m4(obi->normal, imat); - - obi->original_me = use_mesh; - obi->original_ob = (ob->id.orig_id ? (Object *)ob->id.orig_id : (Object *)ob); - lineart_geometry_load_assign_thread(olti, obi, thread_count, use_mesh->totpoly); } - DEG_OBJECT_ITER_END; + FOREACH_SCENE_OBJECT_END; TaskPool *tp = BLI_task_pool_create(NULL, TASK_PRIORITY_HIGH); -- cgit v1.2.3