[Bf-blender-cvs] [870ad7d05db] master: Fix T96781: LineArt proper object iterator.

YimingWu noreply at git.blender.org
Fri May 13 18:05:12 CEST 2022


Commit: 870ad7d05db2e14164d818cd5320345fd8110a69
Author: YimingWu
Date:   Sat May 14 00:03:40 2022 +0800
Branches: master
https://developer.blender.org/rB870ad7d05db2e14164d818cd5320345fd8110a69

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

===================================================================

M	source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
M	source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c

===================================================================

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);



More information about the Bf-blender-cvs mailing list